一键连

1.自动切换源
This commit is contained in:
11111 2026-03-05 15:21:06 +08:00
parent 6c9609347d
commit fcfb3d6656
13 changed files with 213 additions and 252 deletions

View File

@ -46,7 +46,6 @@ import com.yingmao.clash.remote.Resource
import com.yingmao.clash.util.Utils import com.yingmao.clash.util.Utils
import com.yingmao.clash.view.RxToast import com.yingmao.clash.view.RxToast
import com.yingmao.clash.view.adapter.NodeListAdapter import com.yingmao.clash.view.adapter.NodeListAdapter
import com.yingmao.clash.view.dialog.DialogDoMainChoose
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.coroutineScope
@ -77,7 +76,6 @@ class ChangeNodeActivity : BaseActivity(), View.OnClickListener {
val remote = Resource<IRemoteService>() val remote = Resource<IRemoteService>()
var getNodeTimeOutNum = 5 var getNodeTimeOutNum = 5
var isRunDing = false var isRunDing = false
var dialogDoMainChoose: DialogDoMainChoose? = null
var proList: MutableList<ClashNodebBean>? = null var proList: MutableList<ClashNodebBean>? = null
var nowSubUrl: String = "" var nowSubUrl: String = ""
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
@ -197,7 +195,6 @@ class ChangeNodeActivity : BaseActivity(), View.OnClickListener {
Log.d("ACTION_NODE_LIST ACTION_NODE_LIST") Log.d("ACTION_NODE_LIST ACTION_NODE_LIST")
hideLoading() hideLoading()
timerJob?.cancel() timerJob?.cancel()
dialogDoMainChoose?.dismiss()
val json = serStore.nodes val json = serStore.nodes
if (TextUtils.isEmpty(json)) { if (TextUtils.isEmpty(json)) {
return return
@ -224,12 +221,6 @@ class ChangeNodeActivity : BaseActivity(), View.OnClickListener {
broadcastReceiver?.let { broadcastReceiver?.let {
unregisterReceiver(it) unregisterReceiver(it)
} }
if (dialogDoMainChoose != null) {
if (dialogDoMainChoose!!.isShowing) {
dialogDoMainChoose!!.dismiss()
dialogDoMainChoose = null
}
}
} }
override fun onResume() { override fun onResume() {

View File

@ -2,8 +2,6 @@ package com.yingmao.clash.act
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.content.Intent import android.content.Intent
import android.content.res.ColorStateList
import android.graphics.Color
import android.net.Uri import android.net.Uri
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
@ -16,13 +14,22 @@ import android.util.Log
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.view.inputmethod.InputMethodManager import android.view.inputmethod.InputMethodManager
import android.widget.* import android.widget.CheckBox
import android.widget.CompoundButton
import android.widget.EditText
import android.widget.ProgressBar
import android.widget.TextView
import android.widget.Toast
import androidx.core.content.FileProvider import androidx.core.content.FileProvider
import androidx.core.graphics.toColorInt
import androidx.core.net.toUri
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import com.yingmao.clash.view.dialog.RxDialogShapeLoading import com.afollestad.materialdialogs.MaterialDialog
import com.yingmao.clash.net.http.entity.LoginRsp import com.afollestad.materialdialogs.customview.customView
import com.afollestad.materialdialogs.customview.getCustomView
import com.google.android.material.floatingactionbutton.FloatingActionButton
import com.jakewharton.processphoenix.ProcessPhoenix
import com.tencent.mmkv.MMKV import com.tencent.mmkv.MMKV
import com.yingmao.clash.BuildConfig import com.yingmao.clash.BuildConfig
import com.yingmao.clash.R import com.yingmao.clash.R
@ -30,31 +37,23 @@ import com.yingmao.clash.app.MainApplication
import com.yingmao.clash.base.BaseActivity import com.yingmao.clash.base.BaseActivity
import com.yingmao.clash.conf.BZYConstants import com.yingmao.clash.conf.BZYConstants
import com.yingmao.clash.entity.CheckLoginRsp import com.yingmao.clash.entity.CheckLoginRsp
import com.yingmao.clash.levellog.AppLog
import com.yingmao.clash.listener.DownLoadListener import com.yingmao.clash.listener.DownLoadListener
import com.yingmao.clash.net.http.HttpReqType import com.yingmao.clash.net.http.HttpReqType
import com.yingmao.clash.net.http.HttpStatus import com.yingmao.clash.net.http.HttpStatus
import com.yingmao.clash.net.http.entity.AppVersionCheckRsp import com.yingmao.clash.net.http.entity.AppVersionCheckRsp
import com.yingmao.clash.net.http.entity.LoginRsp
import com.yingmao.clash.util.AESUtil import com.yingmao.clash.util.AESUtil
import com.yingmao.clash.util.CommonUtils import com.yingmao.clash.util.CommonUtils
import com.yingmao.clash.view.PasswordTransformationMethodBigDot import com.yingmao.clash.view.PasswordTransformationMethodBigDot
import com.yingmao.clash.view.RxToast import com.yingmao.clash.view.RxToast
import com.yingmao.clash.view.dialog.DialogAppVersion import com.yingmao.clash.view.dialog.DialogAppVersion
import com.yingmao.clash.view.dialog.DialogDoMainChoose import com.yingmao.clash.view.dialog.RxDialogShapeLoading
import com.yingmao.clash.vm.LoginAtyVM import com.yingmao.clash.vm.LoginAtyVM
import com.yingmao.clash.vm.SplashAtyVM import com.yingmao.clash.vm.SplashAtyVM
import com.yingmao.clash.webview.CustomerServiceWebView import com.yingmao.clash.webview.CustomerServiceWebView
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.async import kotlinx.coroutines.async
import kotlinx.coroutines.launch
import java.io.File import java.io.File
import androidx.core.graphics.toColorInt
import androidx.core.net.toUri
import com.afollestad.materialdialogs.MaterialDialog
import com.afollestad.materialdialogs.customview.customView
import com.afollestad.materialdialogs.customview.getCustomView
import com.google.android.material.floatingactionbutton.FloatingActionButton
import com.jakewharton.processphoenix.ProcessPhoenix
import com.yingmao.clash.levellog.AppLog
class LoginActivity : BaseActivity(), View.OnClickListener { class LoginActivity : BaseActivity(), View.OnClickListener {
private lateinit var loginViewMode: LoginAtyVM private lateinit var loginViewMode: LoginAtyVM
@ -184,55 +183,40 @@ class LoginActivity : BaseActivity(), View.OnClickListener {
} }
} }
var dialogDoMainChoose: DialogDoMainChoose? = null
override fun httpFailure(httpStatus: HttpStatus.Failure) { override fun httpFailure(httpStatus: HttpStatus.Failure) {
super.httpFailure(httpStatus) super.httpFailure(httpStatus)
if (httpStatus.reqType == HttpReqType.LOGIN) { if (httpStatus.reqType == HttpReqType.LOGIN) {
AppLog.i("SplashActivity", "httpFailure HttpReqType.LOGIN ${httpStatus.msg}") AppLog.i("SplashActivity", "httpFailure HttpReqType.LOGIN ${httpStatus.msg}")
SplashHelper(splashAtyVM).getHostWithFallback { success -> SplashHelper(splashAtyVM).getHostWithFallback { success ->
MainScope().launch { if(switchServer2()){
if (success) { loginViewMode.login(
if (dialogDoMainChoose == null) { usernameEncrypt,
dialogDoMainChoose = DialogDoMainChoose(this@LoginActivity) passwordEncrypt,
} userOAID
if (dialogDoMainChoose?.isShowing == false) { )
dialogDoMainChoose?.setOnTryButtonListener(object : }else{
DialogDoMainChoose.OnTryButtonListener { val userExpireDialog= MaterialDialog(this@LoginActivity).apply {
override fun tryButton() { cornerRadius(res = R.dimen.dp_30)
MMKV.defaultMMKV()
.decodeString(BZYConstants.MMKV_KEY_CURRENT_HOST, "")
loginViewMode.login(
usernameEncrypt,
passwordEncrypt,
userOAID
)
}
override fun cancel() { customView(
com.cncat.vpn.common.log.Log.d("tryButton CHECK_LOGIN cancel") R.layout.lunxunback_view_layout,
dialogDoMainChoose?.dismiss() scrollable = false,
} noVerticalPadding = true,
}) horizontalPadding = false
dialogDoMainChoose?.setOnListItemListener(object : )
DialogDoMainChoose.OnListItemListener {
override fun listItemClick() {
loginViewMode.login(
usernameEncrypt,
passwordEncrypt,
userOAID
)
} getCustomView().findViewById<TextView>(R.id.tvClose).setOnClickListener {
hideLoading()
hideLoadingDialog()
dismiss()
}
}) getCustomView().findViewById<TextView>(R.id.tvRenewal).setOnClickListener {
dialogDoMainChoose?.show() MMKV.defaultMMKV().removeValueForKey(BZYConstants.MMKV_KEY_Switch_Finsh_Set)
ProcessPhoenix.triggerRebirth(this@LoginActivity)
} }
} else {
if (::rxDialogShapeLoading.isInitialized && rxDialogShapeLoading.isShowing) {
rxDialogShapeLoading.cancel()
}
RxToast.error(resources.getString(R.string.LoginException))
} }
userExpireDialog.show()
} }
} }
} else if (httpStatus.reqType == HttpReqType.CHECK_LOGIN) { } else if (httpStatus.reqType == HttpReqType.CHECK_LOGIN) {
@ -484,7 +468,6 @@ class LoginActivity : BaseActivity(), View.OnClickListener {
MMKV.defaultMMKV().encode(BZYConstants.MMKV_KEY_REMEMBER_PASSWORD, password) MMKV.defaultMMKV().encode(BZYConstants.MMKV_KEY_REMEMBER_PASSWORD, password)
MMKV.defaultMMKV().encode(BZYConstants.MMKV_KEY_REMEMBER_IS_CHECKED, true) MMKV.defaultMMKV().encode(BZYConstants.MMKV_KEY_REMEMBER_IS_CHECKED, true)
} else { } else {
// MMKV.defaultMMKV().removeValueForKey(BZYConstants.MMKV_KEY_REMEMBER_USERNAME)
MMKV.defaultMMKV() MMKV.defaultMMKV()
.removeValueForKey(BZYConstants.MMKV_KEY_REMEMBER_PASSWORD) .removeValueForKey(BZYConstants.MMKV_KEY_REMEMBER_PASSWORD)
MMKV.defaultMMKV().encode(BZYConstants.MMKV_KEY_REMEMBER_IS_CHECKED, false) MMKV.defaultMMKV().encode(BZYConstants.MMKV_KEY_REMEMBER_IS_CHECKED, false)

View File

@ -144,8 +144,7 @@ class MainActivity : BaseActivity() {
var newMainActGlo: Boolean = false var newMainActGlo: Boolean = false
var newUuid: String? = null var newUuid: String? = null
var clashBinder: IClashManager? = null var clashBinder: IClashManager? = null
private var mainBroadcastReceiver: BroadcastReceiver? = null
val trafficStatisticsData = MutableLiveData<String>()
suspend fun setSub2(url: String) { suspend fun setSub2(url: String) {
try { try {
profileBinder?.let { pm -> profileBinder?.let { pm ->
@ -222,20 +221,7 @@ class MainActivity : BaseActivity() {
observe(this, mainAtyVM) observe(this, mainAtyVM)
mainAtyVM.startHeartBeat() mainAtyVM.startHeartBeat()
mainAtyVM.getAirNodes() mainAtyVM.getAirNodes()
val intentFilter = IntentFilter(Intents.ACTION_NODE_LIST)
mainBroadcastReceiver = NodeListBR()
if (Build.VERSION.SDK_INT >= 34 && applicationInfo.targetSdkVersion >= 34) {
registerReceiver(
mainBroadcastReceiver,
intentFilter,
RECEIVER_EXPORTED
)
} else {
registerReceiver(
mainBroadcastReceiver,
intentFilter
)
}
val isGlobal = MMKV.defaultMMKV().decodeBool(BZYConstants.MMKV_KEY_GLOBAL_MODEL, false) val isGlobal = MMKV.defaultMMKV().decodeBool(BZYConstants.MMKV_KEY_GLOBAL_MODEL, false)
newMainActGlo = isGlobal newMainActGlo = isGlobal
startLog() startLog()
@ -260,20 +246,8 @@ class MainActivity : BaseActivity() {
if(!isNotificationEnabledCompat(this@MainActivity)){ if(!isNotificationEnabledCompat(this@MainActivity)){
getNoticePermission() getNoticePermission()
} }
//加载剩余天数 //加载剩余天数
val mmkv = MMKV.defaultMMKV() mainAtyVM.getExpiryDays()
val endTimeDay =
mmkv.decodeLong(BZYConstants.endTimeDay, 0L)
if(endTimeDay==0L) {
mainAtyVM.getExpiryDays()
}else{
val today = isToday(endTimeDay)
if(!today){
mainAtyVM.getExpiryDays()
}
}
} }
fun isNotificationEnabledCompat(context: Context): Boolean { fun isNotificationEnabledCompat(context: Context): Boolean {
return NotificationManagerCompat.from(context).areNotificationsEnabled() return NotificationManagerCompat.from(context).areNotificationsEnabled()
@ -313,31 +287,6 @@ class MainActivity : BaseActivity() {
return return
super.onBackPressed() super.onBackPressed()
} }
inner class NodeListBR : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
when (intent?.action) {
Intents.ACTION_NODE_LIST -> {
Log.i("MainActivity ACTION_NODE_LIST")
val userTraffic=serStore.userTraffic
userTrafficMethod(userTraffic)
}
else -> {
}
}
}
}
fun userTrafficMethod(userTraffic: String) {
val jo = JsonParser.parseString(userTraffic).asJsonObject
val t = jo.get("total").asLong
val d = jo.get("download").asLong
val u = jo.get("upload").asLong
val trafficUsedInGB = String.format("%.2f", (d + u) / 1024.0 / 1024.0 / 1024.0)
val trafficTolTelInGB = String.format("%.2f", t / 1024.0 / 1024.0 / 1024.0)
val userTrafficStr = "流量统计:${trafficUsedInGB}GB / ${trafficTolTelInGB}GB"
trafficStatisticsData.value =userTrafficStr
Log.i("userTrafficMethod::${userTrafficStr}")
}
private fun initData() { private fun initData() {
clashBinder = MainApplication.getApp()?.let { ClashManager(it).wrap() as IClashManager } clashBinder = MainApplication.getApp()?.let { ClashManager(it).wrap() as IClashManager }
profileBinder = profileBinder =
@ -464,30 +413,56 @@ class MainActivity : BaseActivity() {
dismiss() dismiss()
} }
} }
} }else{
data.data.let { netSubUrl -> val netSubStr = data.data
if (netSubUrl.isNotEmpty()) { Log.i("AAAAAAAAAAAAAAAAAA::netSubStr:${netSubStr}")
val proSubUrl = val saveNet = MMKV.defaultMMKV().decodeString(
MMKV.defaultMMKV().decodeString(BZYConstants.PROFILE_SUB_URL, "") BZYConstants.MMKV_KEY_CURRENT_HOST,
subUrl = if (!TextUtils.isEmpty(proSubUrl)) { BuildConfig.service_url
if (proSubUrl == netSubUrl) { )!!
netSubUrl if(netSubStr.isNotEmpty()){
} else { val saveSubUrl =
proSubUrl MMKV.defaultMMKV().decodeString(BZYConstants.PROFILE_SUB_URL, "")!!
if (saveSubUrl.isNotEmpty()){
if(saveSubUrl == netSubStr){
//判断网络传过来的和现在的域名一样不,一样则等于
if(netSubStr.contains(saveNet)){
subUrl=saveSubUrl
}else{
val netSubSpStr = netSubStr.substringAfter(".com")
subUrl=saveNet+netSubSpStr
MMKV.defaultMMKV().encode(BZYConstants.PROFILE_SUB_URL, subUrl)
}
}else{
val subSpStr = saveSubUrl.substringAfter(".com")
subUrl=saveNet+subSpStr
MMKV.defaultMMKV().encode(BZYConstants.PROFILE_SUB_URL, subUrl)
} }
} else { }else{
netSubUrl if(netSubStr.contains(saveNet)){
subUrl=netSubStr
MMKV.defaultMMKV().encode(BZYConstants.PROFILE_SUB_URL, subUrl)
}else{
val netSubSpStr = netSubStr.substringAfter(".com")
subUrl=saveNet+netSubSpStr
MMKV.defaultMMKV().encode(BZYConstants.PROFILE_SUB_URL, subUrl)
}
} }
lifecycleScope.launch(Dispatchers.IO) {
}else{
RxToast.info("获取的订阅连接为空!")
}
lifecycleScope.launch(Dispatchers.IO) {
subUrl?.let { subUrl?.let {
Log.i("netSubUrl:${netSubUrl}::保存机场URL=${proSubUrl}::subUrl:${subUrl}") Log.i("机场链接::subUrl:${subUrl}")
AppLog.i("MainActivity", "网络获取机场netSubUrl:${netSubUrl}") AppLog.i("MainActivity", "机场链接:::${subUrl}")
setSub2(it) setSub2(it)
} }
} }
}
}
}
} }
HttpReqType.GetActivity -> { HttpReqType.GetActivity -> {
@ -522,12 +497,21 @@ class MainActivity : BaseActivity() {
val lastNotice = val lastNotice =
MMKV.defaultMMKV().decodeBool(BZYConstants.NOTICE_READ_TXT, false) MMKV.defaultMMKV().decodeBool(BZYConstants.NOTICE_READ_TXT, false)
if(lastNotice){ if(lastNotice){
// activityDialog?.show()
DialogManager.enqueue(activityDialog!!) DialogManager.enqueue(activityDialog!!)
} }
} }
} }
}else{
if(endTimeDialog!=null){
DialogManager.enqueue(endTimeDialog!!)
}
if(userExpireDialog!=null){
DialogManager.enqueue(userExpireDialog!!)
}
if(noticeCloseDialog!=null){
DialogManager.enqueue(noticeCloseDialog!!)
}
} }
} }
} }
@ -556,6 +540,7 @@ class MainActivity : BaseActivity() {
cleanUserInfo() cleanUserInfo()
} }
payResultLoading?.dismiss() payResultLoading?.dismiss()
hideLoading()
} }
} }
@ -653,21 +638,43 @@ class MainActivity : BaseActivity() {
val endTime = rspData.data.toInt() val endTime = rspData.data.toInt()
if(endTime>0){ if(endTime>0){
val mmkv = MMKV.defaultMMKV() val mmkv = MMKV.defaultMMKV()
endTimeDialog = val endTimeDay =
EndTimeViewDialog(this, endTime) mmkv.decodeInt(BZYConstants.endTimeDay, 0)
endTimeDialog?.setOnDialogClickListener(object : if(endTimeDay==0){
EndTimeViewDialog.OnDialogClickListener { endTimeDialog =
override fun onRechargeClickListener() { EndTimeViewDialog(this, endTime)
//跳转到支付界面 endTimeDialog?.setOnDialogClickListener(object :
goBackupRechargeWeb() EndTimeViewDialog.OnDialogClickListener {
endTimeDialog?.dismiss() override fun onRechargeClickListener() {
//跳转到支付界面
goBackupRechargeWeb()
endTimeDialog?.dismiss()
}
override fun onCancelClickListener() {
endTimeDialog?.dismiss()
mmkv.encode(BZYConstants.endTimeDay,endTime)
}
})
}else{
if(endTimeDay!=endTime){
endTimeDialog =
EndTimeViewDialog(this, endTime)
endTimeDialog?.setOnDialogClickListener(object :
EndTimeViewDialog.OnDialogClickListener {
override fun onRechargeClickListener() {
//跳转到支付界面
goBackupRechargeWeb()
endTimeDialog?.dismiss()
}
override fun onCancelClickListener() {
endTimeDialog?.dismiss()
mmkv.encode(BZYConstants.endTimeDay,endTime)
}
})
} }
override fun onCancelClickListener() { }
endTimeDialog?.dismiss()
val currentTimeMillis = System.currentTimeMillis()
mmkv.encode(BZYConstants.endTimeDay, currentTimeMillis)
}
})
} }
} }
@ -694,6 +701,7 @@ class MainActivity : BaseActivity() {
HttpReqType.CHECK_LOGIN -> { HttpReqType.CHECK_LOGIN -> {
AppLog.i("HomeFragment", " httpFailure CHECK_LOGIN===>${httpStatus.msg}") AppLog.i("HomeFragment", " httpFailure CHECK_LOGIN===>${httpStatus.msg}")
payResultLoading?.dismiss() payResultLoading?.dismiss()
hideLoading()
if(super.switchServer2()){ if(super.switchServer2()){
mainAtyVM.checkLogin() mainAtyVM.checkLogin()
}else{ }else{

View File

@ -42,10 +42,8 @@ import com.yingmao.clash.net.http.entity.RechargeInfoRsp
import com.yingmao.clash.net.http.entity.Trade import com.yingmao.clash.net.http.entity.Trade
import com.yingmao.clash.util.CommonUtils import com.yingmao.clash.util.CommonUtils
import com.yingmao.clash.util.PayUtils import com.yingmao.clash.util.PayUtils
import com.yingmao.clash.util.ThreadUtils
import com.yingmao.clash.util.stopClashService import com.yingmao.clash.util.stopClashService
import com.yingmao.clash.view.RxToast import com.yingmao.clash.view.RxToast
import com.yingmao.clash.view.dialog.DialogDoMainChoose
import com.yingmao.clash.view.dialog.RxDialogShapeLoading import com.yingmao.clash.view.dialog.RxDialogShapeLoading
import com.yingmao.clash.vm.MainAtyVM import com.yingmao.clash.vm.MainAtyVM
import com.yingmao.clash.webview.CustomerServiceWebView import com.yingmao.clash.webview.CustomerServiceWebView
@ -320,7 +318,6 @@ class MemberRechargeActivity : BaseActivity() {
} }
} }
} }
var dialogDoMainChoose: DialogDoMainChoose? = null
private fun showLoadingDialog(content: String) { private fun showLoadingDialog(content: String) {
apply { apply {
if (!::rxDialogShapeLoading.isInitialized) { if (!::rxDialogShapeLoading.isInitialized) {
@ -453,13 +450,6 @@ class MemberRechargeActivity : BaseActivity() {
} }
override fun onDestroy() { override fun onDestroy() {
super.onDestroy() super.onDestroy()
if(dialogDoMainChoose!=null){
if(dialogDoMainChoose!!.isShowing){
dialogDoMainChoose!!.dismiss()
dialogDoMainChoose=null
}
}
} }
private fun cleanUserInfo() { private fun cleanUserInfo() {
MMKV.defaultMMKV().removeValueForKey(BZYConstants.MMKV_KEY_PH_TOKEN) MMKV.defaultMMKV().removeValueForKey(BZYConstants.MMKV_KEY_PH_TOKEN)

View File

@ -16,6 +16,9 @@ import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
import com.afollestad.materialdialogs.MaterialDialog
import com.afollestad.materialdialogs.customview.customView
import com.afollestad.materialdialogs.customview.getCustomView
import com.cncat.vpn.common.constants.Intents import com.cncat.vpn.common.constants.Intents
import com.cncat.vpn.common.log.Log import com.cncat.vpn.common.log.Log
import com.cncat.vpn.core.Clash import com.cncat.vpn.core.Clash
@ -24,6 +27,7 @@ import com.cncat.vpn.service.model.Profile
import com.cncat.vpn.service.remote.IRemoteService import com.cncat.vpn.service.remote.IRemoteService
import com.google.gson.Gson import com.google.gson.Gson
import com.google.gson.JsonParser import com.google.gson.JsonParser
import com.jakewharton.processphoenix.ProcessPhoenix
import com.tencent.mmkv.MMKV import com.tencent.mmkv.MMKV
import com.yingmao.clash.BuildConfig import com.yingmao.clash.BuildConfig
import com.yingmao.clash.R import com.yingmao.clash.R
@ -169,16 +173,6 @@ class NodeGroupActivity : BaseActivity(){
} }
}) })
// if (!TextUtils.isEmpty(serStore.userTraffic)) {
// userTrafficTv.visibility=View.VISIBLE
// var jo = JsonParser.parseString(serStore.userTraffic).asJsonObject
// var t = jo.get("total")
// var d = jo.get("download").asLong
// var u = jo.get("upload").asLong
// val trafficUsedInGB = String.format("%.2f", (d + u) / 1024.0 / 1024.0 / 1024.0)
// userTrafficTv.text="已用流量:${trafficUsedInGB}GB"
// }
} }
private fun getNodesInfo(json: String): MutableList<NodeGroupItem> { private fun getNodesInfo(json: String): MutableList<NodeGroupItem> {
@ -303,6 +297,14 @@ class NodeGroupActivity : BaseActivity(){
setSub2(nowSubUrl) setSub2(nowSubUrl)
} }
}
fun nextDoProfile() {
showLoading("正在获取...", this@NodeGroupActivity)
startTimer()
launch(Dispatchers.IO) {
setSub2(nowSubUrl)
}
} }
private fun changeSubUrl(originalUrl: String, newUrl: String) { private fun changeSubUrl(originalUrl: String, newUrl: String) {
@ -337,29 +339,60 @@ class NodeGroupActivity : BaseActivity(){
repeat(16) { repeat(16) {
Log.d("GetNodeTimeOutNum==>$getNodeTimeOutNum") Log.d("GetNodeTimeOutNum==>$getNodeTimeOutNum")
if (getNodeTimeOutNum == 0) { if (getNodeTimeOutNum == 0) {
// hideLoading()
// RxToast.error("获取节点失败...正在切换其他地址")
// if (setNewData()) {
// timerJob?.cancel()
// MMKV.defaultMMKV()
// .removeValueForKey(BZYConstants.NODE_All_ITEM_NAME_KEY)
// saveSubUrl()
// MainApplication.restartApp(this@NodeGroupActivity, object :
// MainApplication.OnRestartButtonListener {
//
// override fun enterButton() {
//
// }
//
// override fun cancelButton() {
// doProfile()
// }
//
// })
// } else {
// timerJob?.cancel()
// RxToast.error("获取全部线路失败...请切换网络重试")
// }
hideLoading() hideLoading()
RxToast.error("获取节点失败...正在切换其他地址") //更换其他地址的头部用于订阅链接的头部,看下能不能更换成功
if (setNewData()) { if(switchServer2()){
timerJob?.cancel() timerJob?.cancel()
MMKV.defaultMMKV() MMKV.defaultMMKV().removeValueForKey(BZYConstants.NODE_All_ITEM_NAME_KEY)
.removeValueForKey(BZYConstants.NODE_All_ITEM_NAME_KEY)
saveSubUrl() saveSubUrl()
MainApplication.restartApp(this@NodeGroupActivity, object : Log.i("KKKKKKKKKKKKKK data:${nowSubUrl}")
MainApplication.OnRestartButtonListener { nextDoProfile()
}else{
val userExpireDialog= MaterialDialog(this@NodeGroupActivity).apply {
cornerRadius(res = R.dimen.dp_30)
override fun enterButton() { customView(
R.layout.lunxunback_view_layout,
scrollable = false,
noVerticalPadding = true,
horizontalPadding = false
)
getCustomView().findViewById<TextView>(R.id.tvClose).setOnClickListener {
dismiss()
} }
override fun cancelButton() { getCustomView().findViewById<TextView>(R.id.tvRenewal).setOnClickListener {
doProfile() MMKV.defaultMMKV().removeValueForKey(BZYConstants.MMKV_KEY_Switch_Finsh_Set)
ProcessPhoenix.triggerRebirth(this@NodeGroupActivity)
} }
}
}) userExpireDialog.show()
} else {
timerJob?.cancel()
RxToast.error("获取全部线路失败...请切换网络重试")
} }
} }
getNodeTimeOutNum-- getNodeTimeOutNum--
delay(1000) delay(1000)

View File

@ -57,7 +57,6 @@ import com.yingmao.clash.util.AESUtil
import com.yingmao.clash.util.Utils import com.yingmao.clash.util.Utils
import com.yingmao.clash.view.RxToast import com.yingmao.clash.view.RxToast
import com.yingmao.clash.view.dialog.DialogAppVersion import com.yingmao.clash.view.dialog.DialogAppVersion
import com.yingmao.clash.view.dialog.DialogDoMainChoose
import com.yingmao.clash.view.dialog.SplashDialog import com.yingmao.clash.view.dialog.SplashDialog
import com.yingmao.clash.vm.SplashAtyVM import com.yingmao.clash.vm.SplashAtyVM
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@ -393,7 +392,6 @@ class SplashActivity : BaseActivity() {
override fun httpSuccess(httpStatus: HttpStatus.Success) { override fun httpSuccess(httpStatus: HttpStatus.Success) {
when (httpStatus.reqType) { when (httpStatus.reqType) {
HttpReqType.REGISTER -> { HttpReqType.REGISTER -> {
dialogDoMainChoose?.dismiss()
with(httpStatus.rsp as RegisterRsp) { with(httpStatus.rsp as RegisterRsp) {
if (code == "10000" || code == "200") { if (code == "10000" || code == "200") {
if (data != null) { if (data != null) {
@ -510,7 +508,6 @@ class SplashActivity : BaseActivity() {
} }
HttpReqType.CHECK_LOGIN -> { HttpReqType.CHECK_LOGIN -> {
dialogDoMainChoose?.dismiss()
(httpStatus.rsp as CheckLoginRsp).let { checkLoginRsp -> (httpStatus.rsp as CheckLoginRsp).let { checkLoginRsp ->
if (checkLoginRsp.code == 0) { if (checkLoginRsp.code == 0) {
com.cncat.vpn.common.log.Log.d("splash CHECK_LOGIN==>") com.cncat.vpn.common.log.Log.d("splash CHECK_LOGIN==>")
@ -566,7 +563,6 @@ class SplashActivity : BaseActivity() {
} }
} }
var dialogDoMainChoose: DialogDoMainChoose? = null
override fun httpFailure(httpStatus: HttpStatus.Failure) { override fun httpFailure(httpStatus: HttpStatus.Failure) {
when (httpStatus.reqType) { when (httpStatus.reqType) {
HttpReqType.REGISTER -> { HttpReqType.REGISTER -> {
@ -585,7 +581,7 @@ class SplashActivity : BaseActivity() {
noVerticalPadding = true, noVerticalPadding = true,
horizontalPadding = false horizontalPadding = false
) )
getCustomView().findViewById<TextView>(R.id.tv_content).text=initErrMsg getCustomView().findViewById<TextView>(R.id.tv_content).text="当前服务器异常,请点击重试从新加载应用!"
getCustomView().findViewById<TextView>(R.id.tv_cancel).setOnClickListener { getCustomView().findViewById<TextView>(R.id.tv_cancel).setOnClickListener {
dismiss() dismiss()
@ -627,12 +623,12 @@ class SplashActivity : BaseActivity() {
} }
HttpReqType.CHECK_LOGIN -> { HttpReqType.CHECK_LOGIN -> {
com.cncat.vpn.common.log.Log.d("httpFailure HttpReqType.CHECK_LOGIN")
AppLog.i("SplashActivity", "httpFailure HttpReqType.CHECK_LOGIN ${httpStatus.msg}") AppLog.i("SplashActivity", "httpFailure HttpReqType.CHECK_LOGIN ${httpStatus.msg}")
RxToast.error("检测到网络异常,请尝试切换其他地址.")
if (super.switchServer2()) { if (super.switchServer2()) {
splashAtyVM.checkLogin() splashAtyVM.checkLogin()
} else { } else {
//清空缓存的地址信息
MMKV.defaultMMKV().removeValueForKey(BZYConstants.MMKV_KEY_Switch_Finsh_Set)
toLoginPage() toLoginPage()
} }
} }

View File

@ -235,7 +235,7 @@ open class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope(), Br
continue continue
} else { } else {
isChange = true isChange = true
Log.e("Retry", "切换到新url:$url") Log.e("Retry", "切换到新url:$url")
newUrlString = url newUrlString = url
switchFinishSet.add(newUrlString) switchFinishSet.add(newUrlString)
mmkv.encode(BZYConstants.MMKV_KEY_Switch_Finsh_Set, switchFinishSet) mmkv.encode(BZYConstants.MMKV_KEY_Switch_Finsh_Set, switchFinishSet)

View File

@ -428,41 +428,22 @@ class SettingFragment : BaseFragment(), CoroutineScope by CoroutineScope(Dispatc
SplashHelper(mainAtyVM).getHostWithFallback { success -> SplashHelper(mainAtyVM).getHostWithFallback { success ->
MainScope().launch { MainScope().launch {
if (success) { if (success) {
if (dialogDoMainChoose == null) { dialogDoMainChoose = DialogDoMainChoose(activity)
dialogDoMainChoose = DialogDoMainChoose(activity) dialogDoMainChoose?.setOnTryButtonListener(object :
} DialogDoMainChoose.OnTryButtonListener {
if (dialogDoMainChoose?.isShowing == false) { override fun tryButton() {
dialogDoMainChoose?.setOnTryButtonListener(object : MMKV.defaultMMKV().removeValueForKey(BZYConstants.PROFILE_SUB_URL)
DialogDoMainChoose.OnTryButtonListener { MMKV.defaultMMKV().removeValueForKey(BZYConstants.MMKV_KEY_Switch_Finsh_Set)
override fun tryButton() { ProcessPhoenix.triggerRebirth(activity)
RxToast.info(getString(R.string.ModificationFailed)) dialogDoMainChoose?.dismiss()
dialogDoMainChoose?.dismiss() }
}
override fun cancel() { override fun cancel() {
dialogDoMainChoose?.dismiss() dialogDoMainChoose?.dismiss()
} }
}) })
dialogDoMainChoose?.setOnListItemListener(object :
DialogDoMainChoose.OnListItemListener {
override fun listItemClick() {
RxToast.info(getString(R.string.StorageSuccessful))
MainApplication.restartApp(requireActivity(),object:MainApplication.OnRestartButtonListener{
override fun enterButton() {
}
override fun cancelButton() {
dialogDoMainChoose?.dismiss()
}
})
}
})
dialogDoMainChoose?.show() dialogDoMainChoose?.show()
}
} }
} }
} }

View File

@ -37,9 +37,6 @@ open class DialogDoMainChoose : RxDialog {
lateinit var domainRecyclerView: RecyclerView lateinit var domainRecyclerView: RecyclerView
private set private set
lateinit var onTryListener: OnTryButtonListener lateinit var onTryListener: OnTryButtonListener
lateinit var onDomainListItemListener: OnListItemListener
constructor(context: Context?, themeResId: Int) : super(context!!, themeResId) { constructor(context: Context?, themeResId: Int) : super(context!!, themeResId) {
initView() initView()
} }
@ -107,9 +104,6 @@ open class DialogDoMainChoose : RxDialog {
fun setOnTryButtonListener(listener: OnTryButtonListener) { fun setOnTryButtonListener(listener: OnTryButtonListener) {
this.onTryListener = listener this.onTryListener = listener
} }
fun setOnListItemListener(listener: OnListItemListener) {
this.onDomainListItemListener = listener
}
var domainListAdapter: DomainListAdapter = DomainListAdapter(R.layout.domain_list_item_layout) var domainListAdapter: DomainListAdapter = DomainListAdapter(R.layout.domain_list_item_layout)
private fun initAdapter() { private fun initAdapter() {
@ -134,7 +128,6 @@ open class DialogDoMainChoose : RxDialog {
if (domainListAdapter.selectedPosition == position) -1 else position if (domainListAdapter.selectedPosition == position) -1 else position
domainListAdapter.notifyItemChanged(position) domainListAdapter.notifyItemChanged(position)
this.onDomainListItemListener.listItemClick()
} }
} }
} }

View File

@ -1,28 +1,13 @@
package com.yingmao.clash.view.dialog package com.yingmao.clash.view.dialog
import android.annotation.SuppressLint
import android.app.Activity import android.app.Activity
import android.content.Context import android.content.Context
import android.content.DialogInterface import android.content.DialogInterface
import android.content.Intent
import android.text.TextUtils
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.Button
import android.widget.TextView import android.widget.TextView
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.chad.library.adapter.base.BaseQuickAdapter
import com.cncat.vpn.common.log.Log
import com.tencent.mmkv.MMKV
import com.yingmao.clash.R import com.yingmao.clash.R
import com.yingmao.clash.conf.BZYConstants
import com.yingmao.clash.entity.DomainItemBean
import com.yingmao.clash.view.adapter.DomainListAdapter
import com.yingmao.clash.view.dialog.DialogDoMainChoose.OnTryButtonListener
/** /**

View File

@ -80,7 +80,7 @@
android:layout_marginStart="10dp" android:layout_marginStart="10dp"
android:layout_weight="1" android:layout_weight="1"
android:gravity="center" android:gravity="center"
android:text="@string/Resend" android:text="@string/restart"
android:paddingTop="5dp" android:paddingTop="5dp"
android:paddingBottom="5dp"> android:paddingBottom="5dp">
</TextView> </TextView>

View File

@ -20,6 +20,7 @@
android:paddingRight="3dp" android:paddingRight="3dp"
android:textColor="#000" android:textColor="#000"
android:textStyle="bold" android:textStyle="bold"
android:text="@string/txTxTShow"
android:textSize="18sp" /> android:textSize="18sp" />

View File

@ -56,8 +56,8 @@ subprojects {
} }
minSdk = 23 minSdk = 23
targetSdk = 34 targetSdk = 34
versionName = "1.0.5.5" versionName = "1.0.5.6"
versionCode = 1055 versionCode = 1056
resValue("string", "release_name", "v$versionName") resValue("string", "release_name", "v$versionName")
resValue("integer", "release_code", "$versionCode") resValue("integer", "release_code", "$versionCode")
externalNativeBuild { externalNativeBuild {