登录,注册和节点添加备用源
This commit is contained in:
parent
7b3351ebfd
commit
a417929817
|
|
@ -42,6 +42,7 @@ import com.yingmao.clash.view.adapter.NodeListAdapter
|
|||
import com.yingmao.clash.view.dialog.DialogDoMainChoose
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.MainScope
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.sync.Semaphore
|
||||
|
|
@ -165,10 +166,12 @@ class ChangeNodeActivity : BaseActivity(), View.OnClickListener {
|
|||
override fun onReceive(context: Context?, intent: Intent?) {
|
||||
when (intent?.action) {
|
||||
Intents.ACTION_NODE_LIST -> {
|
||||
Log.d("ACTION_NODE_LIST ACTION_NODE_LIST")
|
||||
// val parcelableArrayListExtra = intent.getParcelableArrayListExtra<Map<String,Any>>("")
|
||||
hideLoading()
|
||||
// stopTimer()
|
||||
timerJob?.cancel()
|
||||
dialogDoMainChoose?.dismiss()
|
||||
// var json = intent.getStringExtra("node_list")
|
||||
// Log.d("onReceive: $json")
|
||||
// currNodeJsonA = json
|
||||
|
|
@ -177,6 +180,9 @@ class ChangeNodeActivity : BaseActivity(), View.OnClickListener {
|
|||
if (TextUtils.isEmpty(json)) {
|
||||
return
|
||||
}
|
||||
//缓存订阅地址
|
||||
NewMainActivity.subUrl=nowSubUrl
|
||||
MMKV.defaultMMKV().encode(BZYConstants.PROFILE_SUB_URL, nowSubUrl)
|
||||
//缓存节点
|
||||
MMKV.defaultMMKV().encode(BZYConstants.NODE_All_ITEM_NAME_KEY, json)
|
||||
currentNode = getNodesInfo(json)
|
||||
|
|
@ -212,42 +218,67 @@ class ChangeNodeActivity : BaseActivity(), View.OnClickListener {
|
|||
var is_runing = false
|
||||
private var timer: Timer? = null
|
||||
private var timerTask: TimerTask? = null
|
||||
var nowSubUrl: String = ""
|
||||
private fun updateProfile(isDelete: Boolean) {
|
||||
// showLoading("正在获取...", this@ChangeNodeActivity)
|
||||
|
||||
launch(Dispatchers.IO) {
|
||||
NewMainActivity.profileBinder?.let { profileManager ->
|
||||
var pro = profileManager.queryAll().find {
|
||||
it.name == Conf.getClashConfName(this@ChangeNodeActivity.applicationContext)
|
||||
}
|
||||
try {
|
||||
|
||||
if (pro == null) {
|
||||
//为空的情况下选择第一个
|
||||
profileManager.queryAll().forEach { profile ->
|
||||
pro = profile
|
||||
return@forEach
|
||||
|
||||
launch(Dispatchers.IO) {
|
||||
NewMainActivity.profileBinder?.let { profileManager ->
|
||||
var mProfile = profileManager.queryAll().find {
|
||||
it.name == Conf.getClashConfName(this@ChangeNodeActivity.applicationContext)
|
||||
}
|
||||
|
||||
if (mProfile == null) {
|
||||
//为空的情况下选择第一个
|
||||
profileManager.queryAll().forEach { profile ->
|
||||
mProfile = profile
|
||||
return@forEach
|
||||
}
|
||||
}
|
||||
|
||||
mProfile?.let { profile ->
|
||||
uuid = profile.uuid
|
||||
Log.d("ChangeNode22 uuid==>${profile.uuid}")
|
||||
if (isDelete) {
|
||||
Log.d("gogogogogo isDelete")
|
||||
profileManager.delete(profile.uuid)
|
||||
MMKV.defaultMMKV()
|
||||
.removeValueForKey(BZYConstants.NODE_All_ITEM_NAME_KEY)
|
||||
// setSub2(profileManager, NewMainActivity.subUrl)
|
||||
setSub2(profileManager, nowSubUrl)
|
||||
} else {
|
||||
Log.d("gogogogogo update")
|
||||
profileManager.setActive(profile)
|
||||
delay(500)
|
||||
if (!TextUtils.isEmpty(profile.source)) {
|
||||
Log.d("updateProfile pro.source==>${profile.source}, url==>${nowSubUrl}")
|
||||
if (profile.source != nowSubUrl) {
|
||||
Log.d("updateProfile patch")
|
||||
profileManager.patch(
|
||||
profile.uuid,
|
||||
profile.name,
|
||||
nowSubUrl,
|
||||
1800000L
|
||||
)
|
||||
Log.d("updateProfile patch 1")
|
||||
profileManager.commit(profile.uuid) { status ->
|
||||
Log.d("updateProfile updateStatus: " + Gson().toJson(status.args) + ", pro==>" + status.progress)
|
||||
}
|
||||
Log.d("updateProfile patch 2")
|
||||
}
|
||||
}
|
||||
Log.d("updateProfile go update")
|
||||
profileManager.update(profile.uuid)
|
||||
}
|
||||
Log.d("gogogogogo end")
|
||||
}
|
||||
}
|
||||
|
||||
pro?.uuid?.let { pu ->
|
||||
uuid = pu
|
||||
com.cncat.vpn.common.log.Log.d("ChangeNode22 uuid==>$pu")
|
||||
com.cncat.vpn.common.log.Log.d("gogogogogo")
|
||||
if (isDelete) {
|
||||
com.cncat.vpn.common.log.Log.d("gogogogogo isDelete")
|
||||
profileManager.delete(pu)
|
||||
// setSub2(profileManager, NewMainActivity.subUrl)
|
||||
setSub2(profileManager, NewMainActivity.subUrl)
|
||||
} else {
|
||||
com.cncat.vpn.common.log.Log.d("gogogogogo update")
|
||||
profileManager.setActive(pro!!)
|
||||
delay(500)
|
||||
profileManager.update(pu)
|
||||
}
|
||||
com.cncat.vpn.common.log.Log.d("gogogogogo end")
|
||||
}
|
||||
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -273,19 +304,27 @@ class ChangeNodeActivity : BaseActivity(), View.OnClickListener {
|
|||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
|
||||
NewMainActivity.subUrl?.let {
|
||||
nowSubUrl = it
|
||||
}
|
||||
doProfile()
|
||||
|
||||
}
|
||||
|
||||
fun doProfile() {
|
||||
if (TextUtils.isEmpty(cacheNodeStr)) {
|
||||
showLoading("正在获取...", this@ChangeNodeActivity)
|
||||
startTimer()
|
||||
|
||||
}
|
||||
showLoading("正在获取...", this@ChangeNodeActivity)
|
||||
startTimer()
|
||||
updateProfile(false)
|
||||
}
|
||||
|
||||
private fun changeSubUrl(originalUrl: String, newUrl: String) {
|
||||
nowSubUrl = originalUrl.replace(Regex("https://[^/]+/"), "$newUrl/")
|
||||
|
||||
}
|
||||
|
||||
val reloadLock = Semaphore(10)
|
||||
private fun setPing() {
|
||||
if (!NewAccFragment.clashRunning) {
|
||||
|
|
@ -452,44 +491,55 @@ class ChangeNodeActivity : BaseActivity(), View.OnClickListener {
|
|||
private fun startTimer() {
|
||||
GetNodeTimeOutNum = 10
|
||||
timerJob = launch {
|
||||
repeat(10) {
|
||||
repeat(11) {
|
||||
Log.d("GetNodeTimeOutNum==>$GetNodeTimeOutNum")
|
||||
if (GetNodeTimeOutNum >= 5) {
|
||||
GetNodeTimeOutNum--
|
||||
} else {
|
||||
//超时后删除配置文件重新创建
|
||||
if (GetNodeTimeOutNum == 0) {
|
||||
hideLoading()
|
||||
Log.d("isCreate==>$isCreate")
|
||||
if (!isCreate) {
|
||||
isCreate = true
|
||||
showLoading("获取节点超时,正在重新配置...", this@ChangeNodeActivity)
|
||||
createProfile()
|
||||
} else {
|
||||
Log.d("stopTimer...")
|
||||
RxToast.error("获取节点失败...请尝试切换其他地址")
|
||||
delay(1000)
|
||||
this@ChangeNodeActivity.finish()
|
||||
}
|
||||
Log.d("stopTimer...")
|
||||
RxToast.error("获取节点失败...请尝试切换其他地址")
|
||||
showDomainList()
|
||||
timerJob?.cancel()
|
||||
// delay(1000)
|
||||
// this@ChangeNodeActivity.finish()
|
||||
|
||||
}
|
||||
GetNodeTimeOutNum--
|
||||
delay(1000)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var dialogDoMainChoose:DialogDoMainChoose? =null
|
||||
private fun showDomainList() {
|
||||
try {
|
||||
SplashHelper(changeNodeVM).getHostWithFallback { success ->
|
||||
MainScope().launch {
|
||||
if (success) {
|
||||
if (dialogDoMainChoose==null) {
|
||||
dialogDoMainChoose = DialogDoMainChoose(this@ChangeNodeActivity)
|
||||
}
|
||||
if (dialogDoMainChoose?.isShowing==false) {
|
||||
dialogDoMainChoose?.setOnTryButtonListener(object :
|
||||
DialogDoMainChoose.OnTryButtonListener {
|
||||
override fun tryButton() {
|
||||
var currentHost = MMKV.defaultMMKV()
|
||||
.decodeString(BZYConstants.MMKV_KEY_CURRENT_HOST, "")
|
||||
com.cncat.vpn.common.log.Log.d("tryButton currentHost==>${currentHost}")
|
||||
var oldUrl = nowSubUrl
|
||||
currentHost?.let { changeSubUrl(oldUrl, it) }
|
||||
doProfile()
|
||||
}
|
||||
|
||||
val dialogDoMainChoose = DialogDoMainChoose(this@ChangeNodeActivity)
|
||||
dialogDoMainChoose.setOnTryButtonListener(object :
|
||||
DialogDoMainChoose.OnTryButtonListener {
|
||||
override fun tryButton() {
|
||||
var currentHost = MMKV.defaultMMKV()
|
||||
.decodeString(BZYConstants.MMKV_KEY_CURRENT_HOST, "")
|
||||
com.cncat.vpn.common.log.Log.d("tryButton currentHost==>${currentHost}")
|
||||
doProfile()
|
||||
override fun cancel() {
|
||||
com.cncat.vpn.common.log.Log.d("tryButton CHECK_LOGIN cancel")
|
||||
dialogDoMainChoose?.dismiss()
|
||||
}
|
||||
})
|
||||
dialogDoMainChoose?.show()
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
dialogDoMainChoose.show()
|
||||
}
|
||||
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,10 +35,15 @@ import com.yingmao.clash.util.CommonUtils
|
|||
import com.yingmao.clash.util.Utils
|
||||
import com.yingmao.clash.view.PasswordTransformationMethodBigDot
|
||||
import com.yingmao.clash.view.RxToast
|
||||
import com.yingmao.clash.view.dialog.DialogDoMainChoose
|
||||
import com.yingmao.clash.vm.LoginAtyVM
|
||||
import com.yingmao.clash.vm.SplashAtyVM
|
||||
import kotlinx.coroutines.MainScope
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class LoginActivity : BaseActivity(), View.OnClickListener {
|
||||
private lateinit var loginViewMode: LoginAtyVM
|
||||
private lateinit var splashAtyVM: SplashAtyVM
|
||||
private lateinit var usernameEt: EditText
|
||||
private lateinit var passwordEt: EditText
|
||||
private lateinit var usernameErrorTv: TextView
|
||||
|
|
@ -64,6 +69,7 @@ class LoginActivity : BaseActivity(), View.OnClickListener {
|
|||
//点击输入框外边隐藏输入法 必须在setContentView之后调用
|
||||
setupUI(findViewById<ViewGroup>(android.R.id.content).getChildAt(0))
|
||||
loginViewMode = ViewModelProvider(this).get(LoginAtyVM::class.java)
|
||||
splashAtyVM = ViewModelProvider(this).get(SplashAtyVM::class.java)
|
||||
observe(this, loginViewMode)
|
||||
initViews()
|
||||
}
|
||||
|
|
@ -146,18 +152,49 @@ class LoginActivity : BaseActivity(), View.OnClickListener {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
var dialogDoMainChoose: DialogDoMainChoose? = null
|
||||
override fun httpFailure(httpStatus: HttpStatus.Failure) {
|
||||
super.httpFailure(httpStatus)
|
||||
if (httpStatus.reqType == HttpReqType.LOGIN) {
|
||||
if (super.switchServer()) {
|
||||
loginViewMode.login(username_encrypt, password_encrypt)
|
||||
} else {
|
||||
if (::rxDialogShapeLoading.isInitialized && rxDialogShapeLoading.isShowing) {
|
||||
rxDialogShapeLoading.cancel()
|
||||
SplashHelper(splashAtyVM).getHostWithFallback { success ->
|
||||
MainScope().launch {
|
||||
if (success) {
|
||||
if (dialogDoMainChoose==null) {
|
||||
dialogDoMainChoose = DialogDoMainChoose(this@LoginActivity)
|
||||
}
|
||||
if (dialogDoMainChoose?.isShowing==false) {
|
||||
dialogDoMainChoose?.setOnTryButtonListener(object :
|
||||
DialogDoMainChoose.OnTryButtonListener {
|
||||
override fun tryButton() {
|
||||
var currentHost = MMKV.defaultMMKV()
|
||||
.decodeString(BZYConstants.MMKV_KEY_CURRENT_HOST, "")
|
||||
com.cncat.vpn.common.log.Log.d("tryButton CHECK_LOGIN currentHost==>${currentHost}")
|
||||
loginViewMode.login(username_encrypt, password_encrypt)
|
||||
}
|
||||
|
||||
override fun cancel() {
|
||||
com.cncat.vpn.common.log.Log.d("tryButton CHECK_LOGIN cancel")
|
||||
dialogDoMainChoose?.dismiss()
|
||||
}
|
||||
})
|
||||
dialogDoMainChoose?.show()
|
||||
}
|
||||
}else{
|
||||
if (::rxDialogShapeLoading.isInitialized && rxDialogShapeLoading.isShowing) {
|
||||
rxDialogShapeLoading.cancel()
|
||||
}
|
||||
RxToast.error(resources.getString(R.string.LoginException))
|
||||
}
|
||||
}
|
||||
RxToast.error(resources.getString(R.string.LoginException))
|
||||
}
|
||||
// if (super.switchServer()) {
|
||||
// loginViewMode.login(username_encrypt, password_encrypt)
|
||||
// } else {
|
||||
// if (::rxDialogShapeLoading.isInitialized && rxDialogShapeLoading.isShowing) {
|
||||
// rxDialogShapeLoading.cancel()
|
||||
// }
|
||||
// RxToast.error(resources.getString(R.string.LoginException))
|
||||
// }
|
||||
} else if (httpStatus.reqType == HttpReqType.CHECK_LOGIN) {
|
||||
if (::rxDialogShapeLoading.isInitialized && rxDialogShapeLoading.isShowing) {
|
||||
rxDialogShapeLoading.cancel()
|
||||
|
|
|
|||
|
|
@ -524,13 +524,25 @@ class NewMainActivity : BaseActivity() {
|
|||
}
|
||||
data.data?.let { url ->
|
||||
android.util.Log.e("Data", "机场URL:=${url}")
|
||||
// var url2="https://www.otcopusapp.cc/lx3af288h5i8pz380/api/v1/client/subscribe?token=d6bc98c7ea53099fa5bd1a3ea415ebb6"
|
||||
// var url2="https://api.ymvpnpro11.cc:8700/7air2vr7ikiqzgvxz/api/v1/client/subscribe?token=5af82930d222840cbc2dec572b21d6c6"
|
||||
if (url.isNotEmpty()) {
|
||||
//todo 判断订阅地址是否修改过,未修改就用接口返回的地址反之使用本地修改的地址
|
||||
var pro_sub_url =
|
||||
MMKV.defaultMMKV().decodeString(BZYConstants.PROFILE_SUB_URL, "")
|
||||
if (!TextUtils.isEmpty(pro_sub_url)){
|
||||
if (pro_sub_url == url) {
|
||||
subUrl = url
|
||||
} else {
|
||||
subUrl = pro_sub_url
|
||||
}
|
||||
}else{
|
||||
subUrl = url
|
||||
}
|
||||
|
||||
|
||||
subUrl = url
|
||||
lifecycleScope.launch(Dispatchers.IO) {
|
||||
// setSub(url)
|
||||
setSub2(url)
|
||||
subUrl?.let { setSub2(it) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -648,7 +660,7 @@ class NewMainActivity : BaseActivity() {
|
|||
MMKV.defaultMMKV().removeValueForKey(BZYConstants.MMKV_KEY_CURRENT_NODE)
|
||||
MMKV.defaultMMKV().removeValueForKey(BZYConstants.NODE_SELECTED_NAME_KEY)
|
||||
MMKV.defaultMMKV().removeValueForKey(BZYConstants.MMKV_KEY_VPN_UserCommand)
|
||||
|
||||
MMKV.defaultMMKV().removeValueForKey(BZYConstants.NODE_All_ITEM_NAME_KEY)
|
||||
Log.d("cleanUserInfo clashRunning==>${clashRunning}")
|
||||
if (clashRunning) {
|
||||
fragments.filterIsInstance<NewAccFragment>().forEach { it.stopClash() }
|
||||
|
|
|
|||
|
|
@ -0,0 +1,51 @@
|
|||
package com.yingmao.clash.act
|
||||
import android.util.Log
|
||||
import com.yingmao.clash.base.PublicViewMode
|
||||
import com.yingmao.clash.listener.AsyncCallback
|
||||
import com.yingmao.clash.vm.SplashAtyVM
|
||||
|
||||
class SplashHelper(private val splashAtyVM: PublicViewMode) {
|
||||
|
||||
fun getHostWithFallback(callback: (Boolean) -> Unit) {
|
||||
tryGetHost(
|
||||
{ splashAtyVM.getHostByGithub(it) },
|
||||
{ splashAtyVM.getHostByAWS(it) },
|
||||
{ splashAtyVM.getHost(it) },
|
||||
callback
|
||||
)
|
||||
}
|
||||
|
||||
private fun tryGetHost(
|
||||
first: (AsyncCallback) -> Unit,
|
||||
second: (AsyncCallback) -> Unit,
|
||||
third: (AsyncCallback) -> Unit,
|
||||
callback: (Boolean) -> Unit
|
||||
) {
|
||||
first(createCallback("getHostByGithub method success", "getHostByGithub method failed", callback) {
|
||||
second(createCallback("getHostByAWS method success", "getHostByAWS method failed", callback) {
|
||||
third(createCallback("getHost method success", "getHost methods failed", callback) {
|
||||
callback(false) // 所有方法都失败
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
private fun createCallback(
|
||||
successLog: String,
|
||||
errorLog: String,
|
||||
callback: (Boolean) -> Unit,
|
||||
onFailure: () -> Unit
|
||||
): AsyncCallback {
|
||||
return object : AsyncCallback {
|
||||
override suspend fun suc() {
|
||||
Log.e("data", successLog)
|
||||
callback(true) // 成功时回调
|
||||
}
|
||||
|
||||
override fun err() {
|
||||
Log.e("data", errorLog)
|
||||
onFailure() // 失败时尝试下一个方法
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -174,46 +174,55 @@ class SplashActivity : BaseActivity() {
|
|||
if (BuildConfig.is_back_cn == true) { //没有备用域名所以无需调用getHost
|
||||
isNeedRegister()
|
||||
} else {
|
||||
splashAtyVM.getHostByGithub(object : AsyncCallback {
|
||||
override suspend fun suc() {
|
||||
Log.e("data", "getHostByGithub suc")
|
||||
MainScope().launch {
|
||||
SplashHelper(splashAtyVM).getHostWithFallback { success ->
|
||||
MainScope().launch {
|
||||
if (success) {
|
||||
isNeedRegister()
|
||||
} else {
|
||||
isNeedRegister()
|
||||
}
|
||||
}
|
||||
|
||||
override fun err() {
|
||||
Log.e("data", "getHostByGithub err")
|
||||
splashAtyVM.getHostByAWS(object : AsyncCallback {
|
||||
override suspend fun suc() {
|
||||
Log.e("data", "getHostByAWS suc")
|
||||
MainScope().launch {
|
||||
isNeedRegister()
|
||||
}
|
||||
}
|
||||
|
||||
override fun err() {
|
||||
Log.e("data", "getHostByAWS err")
|
||||
splashAtyVM.getHost(object : AsyncCallback {
|
||||
override suspend fun suc() {
|
||||
Log.e("data", "getHost suc")
|
||||
MainScope().launch {
|
||||
isNeedRegister()
|
||||
}
|
||||
}
|
||||
|
||||
override fun err() {
|
||||
Log.e("data", "getHost err")
|
||||
//全部失败后也调用
|
||||
MainScope().launch {
|
||||
isNeedRegister()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
// splashAtyVM.getHostByGithub(object : AsyncCallback {
|
||||
// override suspend fun suc() {
|
||||
// Log.e("data", "getHostByGithub suc")
|
||||
// MainScope().launch {
|
||||
// isNeedRegister()
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// override fun err() {
|
||||
// Log.e("data", "getHostByGithub err")
|
||||
// splashAtyVM.getHostByAWS(object : AsyncCallback {
|
||||
// override suspend fun suc() {
|
||||
// Log.e("data", "getHostByAWS suc")
|
||||
// MainScope().launch {
|
||||
// isNeedRegister()
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// override fun err() {
|
||||
// Log.e("data", "getHostByAWS err")
|
||||
// splashAtyVM.getHost(object : AsyncCallback {
|
||||
// override suspend fun suc() {
|
||||
// Log.e("data", "getHost suc")
|
||||
// MainScope().launch {
|
||||
// isNeedRegister()
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// override fun err() {
|
||||
// Log.e("data", "getHost err")
|
||||
// //全部失败后也调用
|
||||
// MainScope().launch {
|
||||
// isNeedRegister()
|
||||
// }
|
||||
// }
|
||||
// })
|
||||
// }
|
||||
// })
|
||||
// }
|
||||
// })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -488,6 +497,7 @@ class SplashActivity : BaseActivity() {
|
|||
override fun httpSuccess(httpStatus: HttpStatus.Success) {
|
||||
when (httpStatus.reqType) {
|
||||
HttpReqType.REGISTER -> {
|
||||
dialogDoMainChoose?.dismiss()
|
||||
with(httpStatus.rsp as RegisterRsp) {
|
||||
if (code == "10000" || code == "200") {
|
||||
if (data != null) {
|
||||
|
|
@ -591,6 +601,7 @@ class SplashActivity : BaseActivity() {
|
|||
}
|
||||
|
||||
HttpReqType.CHECK_LOGIN -> {
|
||||
dialogDoMainChoose?.dismiss()
|
||||
(httpStatus.rsp as CheckLoginRsp).let { checkLoginRsp ->
|
||||
if (checkLoginRsp.code == 0) {
|
||||
com.cncat.vpn.common.log.Log.d("splash CHECK_LOGIN==>")
|
||||
|
|
@ -621,25 +632,36 @@ class SplashActivity : BaseActivity() {
|
|||
}
|
||||
}
|
||||
|
||||
var dialogDoMainChoose: DialogDoMainChoose? = null
|
||||
override fun httpFailure(httpStatus: HttpStatus.Failure) {
|
||||
when (httpStatus.reqType) {
|
||||
HttpReqType.REGISTER -> {
|
||||
rlPb.visibility=View.GONE
|
||||
rlPb.visibility = View.GONE
|
||||
|
||||
com.cncat.vpn.common.log.Log.d("httpFailure HttpReqType.REGISTER")
|
||||
try {
|
||||
RxToast.error("检测到网络异常,请尝试切换其他地址.")
|
||||
val dialogDoMainChoose = DialogDoMainChoose(this@SplashActivity)
|
||||
dialogDoMainChoose.setOnTryButtonListener(object :
|
||||
DialogDoMainChoose.OnTryButtonListener {
|
||||
override fun tryButton() {
|
||||
var currentHost = MMKV.defaultMMKV()
|
||||
.decodeString(BZYConstants.MMKV_KEY_CURRENT_HOST, "")
|
||||
com.cncat.vpn.common.log.Log.d("tryButton currentHost==>${currentHost}")
|
||||
doRegisterByEncryption()
|
||||
}
|
||||
})
|
||||
dialogDoMainChoose.show()
|
||||
if (dialogDoMainChoose==null) {
|
||||
dialogDoMainChoose = DialogDoMainChoose(this@SplashActivity)
|
||||
}
|
||||
if (dialogDoMainChoose?.isShowing==false){
|
||||
dialogDoMainChoose?.setOnTryButtonListener(object :
|
||||
DialogDoMainChoose.OnTryButtonListener {
|
||||
override fun tryButton() {
|
||||
var currentHost = MMKV.defaultMMKV()
|
||||
.decodeString(BZYConstants.MMKV_KEY_CURRENT_HOST, "")
|
||||
com.cncat.vpn.common.log.Log.d("tryButton currentHost==>${currentHost}")
|
||||
doRegisterByEncryption()
|
||||
}
|
||||
|
||||
override fun cancel() {
|
||||
com.cncat.vpn.common.log.Log.d("tryButton REGISTER cancel")
|
||||
dialogDoMainChoose?.dismiss()
|
||||
dialogDoMainChoose=null
|
||||
}
|
||||
})
|
||||
dialogDoMainChoose?.show()
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
|
|
@ -682,11 +704,45 @@ class SplashActivity : BaseActivity() {
|
|||
|
||||
HttpReqType.CHECK_LOGIN -> {
|
||||
com.cncat.vpn.common.log.Log.d("httpFailure HttpReqType.CHECK_LOGIN")
|
||||
if (super.switchServer()) {
|
||||
splashAtyVM.checkLogin()
|
||||
} else {
|
||||
try {
|
||||
RxToast.error("检测到网络异常,请尝试切换其他地址.")
|
||||
SplashHelper(splashAtyVM).getHostWithFallback { success ->
|
||||
MainScope().launch {
|
||||
if (success) {
|
||||
if (dialogDoMainChoose==null) {
|
||||
dialogDoMainChoose = DialogDoMainChoose(this@SplashActivity)
|
||||
}
|
||||
if (dialogDoMainChoose?.isShowing==false){
|
||||
dialogDoMainChoose?.setOnTryButtonListener(object :
|
||||
DialogDoMainChoose.OnTryButtonListener {
|
||||
override fun tryButton() {
|
||||
var currentHost = MMKV.defaultMMKV()
|
||||
.decodeString(BZYConstants.MMKV_KEY_CURRENT_HOST, "")
|
||||
com.cncat.vpn.common.log.Log.d("tryButton CHECK_LOGIN currentHost==>${currentHost}")
|
||||
splashAtyVM.checkLogin()
|
||||
}
|
||||
|
||||
override fun cancel() {
|
||||
com.cncat.vpn.common.log.Log.d("tryButton CHECK_LOGIN cancel")
|
||||
dialogDoMainChoose?.dismiss()
|
||||
}
|
||||
})
|
||||
dialogDoMainChoose?.show()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
toLoginPage()
|
||||
}
|
||||
|
||||
// if (super.switchServer()) {
|
||||
// splashAtyVM.checkLogin()
|
||||
// } else {
|
||||
// toLoginPage()
|
||||
// }
|
||||
}
|
||||
|
||||
else -> {}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,17 @@
|
|||
package com.yingmao.clash.base
|
||||
|
||||
|
||||
import android.text.TextUtils
|
||||
import com.yingmao.clash.net.http.HttpApi
|
||||
import com.yingmao.clash.net.http.NetService
|
||||
import com.orhanobut.logger.Logger
|
||||
import com.tencent.mmkv.MMKV
|
||||
import com.yingmao.clash.BuildConfig
|
||||
import com.yingmao.clash.conf.BZYConstants
|
||||
import com.yingmao.clash.entity.DomainRsp
|
||||
import com.yingmao.clash.listener.AsyncCallback
|
||||
import com.yingmao.clash.net.http.HttpReqType
|
||||
import com.yingmao.clash.util.AESUtil
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.launch
|
||||
import java.util.ArrayList
|
||||
|
|
@ -17,6 +24,95 @@ open class PublicViewMode: BaseViewMode() {
|
|||
// return acls.size > 3
|
||||
// }
|
||||
|
||||
fun getHost(callback: AsyncCallback) {
|
||||
val rt =
|
||||
NetService.instances.createFreeBaseUrl("https://yingmao.oss-cn-hongkong.aliyuncs.com/")
|
||||
doAsyncNoNeedReturn(HttpReqType.GET_HOST) {
|
||||
try { //TODO bug 会引起崩溃
|
||||
var host = if (BuildConfig.is_ym) {
|
||||
rt.getHost()
|
||||
|
||||
} else if (BuildConfig.is_tz) {
|
||||
rt.getHostTZ()
|
||||
} else {
|
||||
rt.getHostDef()
|
||||
}
|
||||
// Log.e("data", "2:$host")
|
||||
if (!TextUtils.isEmpty(host)) {
|
||||
host = AESUtil.decrypt(host)
|
||||
val hostSet = host.split("+").toSet()
|
||||
MMKV.defaultMMKV().encode(BZYConstants.MMKV_KEY_ROUTER_HOST, hostSet)
|
||||
}
|
||||
// Log.e("data", "22:$host")
|
||||
|
||||
callback.suc()
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
callback.err()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun getHostByGithub(callback: AsyncCallback) {
|
||||
val rt = NetService.instances.createFreeBaseUrl("https://raw.githubusercontent1.com/")
|
||||
doAsyncNoNeedReturn(HttpReqType.GET_HOST) {
|
||||
try {
|
||||
val host = when {
|
||||
BuildConfig.is_ym -> {
|
||||
rt.getHostGithub()
|
||||
}
|
||||
BuildConfig.is_tz -> {
|
||||
rt.getHostTZ()
|
||||
}
|
||||
else -> {
|
||||
rt.getHostDef()
|
||||
}
|
||||
}
|
||||
host?.takeIf { it.isNotEmpty() }?.let {
|
||||
com.cncat.vpn.common.log.Log.d("getHostByGithub host-->${it}")
|
||||
val decryptedHost = AESUtil.decrypt(it)
|
||||
com.cncat.vpn.common.log.Log.d("getHostByGithub decryptedHost-->${decryptedHost}")
|
||||
val hostSet = decryptedHost.split("+").toSet()
|
||||
MMKV.defaultMMKV().encode(BZYConstants.MMKV_KEY_ROUTER_HOST, hostSet)
|
||||
}
|
||||
callback.suc()
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
callback.err()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun getHostByAWS(callback: AsyncCallback) {
|
||||
val rt = NetService.instances.createFreeBaseUrl("https://yingmao2.s3.ap-east-1.amazonaws.com/")
|
||||
doAsyncNoNeedReturn(HttpReqType.GET_HOST) {
|
||||
try {
|
||||
val host = when {
|
||||
BuildConfig.is_ym -> {
|
||||
rt.getHostAWS()
|
||||
}
|
||||
BuildConfig.is_tz -> {
|
||||
rt.getHostTZ()
|
||||
}
|
||||
else -> {
|
||||
rt.getHostDef()
|
||||
}
|
||||
}
|
||||
host?.takeIf { it.isNotEmpty() }?.let {
|
||||
com.cncat.vpn.common.log.Log.d("getHostByAWS host-->${it}")
|
||||
val decryptedHost = AESUtil.decrypt(it)
|
||||
com.cncat.vpn.common.log.Log.d("getHostByAWS decryptedHost-->${decryptedHost}")
|
||||
val hostSet = decryptedHost.split("+").toSet()
|
||||
MMKV.defaultMMKV().encode(BZYConstants.MMKV_KEY_ROUTER_HOST, hostSet)
|
||||
}
|
||||
callback.suc()
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
callback.err()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun getServiceAclAndSet(){
|
||||
val httpApi = NetService.instances.createHttpsEncodeStr(HttpApi::class.java)
|
||||
GlobalScope.launch {
|
||||
|
|
|
|||
|
|
@ -63,8 +63,10 @@ class BZYConstants {
|
|||
const val MMKV_KEY_IS_REGISTER = "is_register"
|
||||
//节点
|
||||
const val NODE_SELECTED_NAME_KEY = "node_select_name_key"
|
||||
|
||||
//节点列表
|
||||
const val NODE_All_ITEM_NAME_KEY = "NODE_All_ITEM_NAME_KEY"
|
||||
//订阅地址
|
||||
const val PROFILE_SUB_URL = "PROFILE_SUB_URL"
|
||||
|
||||
//服务器模式(根据手机ip切换后台地址)
|
||||
const val MMKV_KEY_SERVICE_TYPE = "SERVICE_TYPE"
|
||||
|
|
|
|||
|
|
@ -69,6 +69,7 @@ class NetService private constructor() : INetService {
|
|||
}
|
||||
|
||||
var httpClient: OkHttpClient? = null;
|
||||
var downHttpClient: OkHttpClient? = null;
|
||||
|
||||
override fun httpsClient(connTO:Long,readTO:Long,writeTO:Long): OkHttpClient {
|
||||
|
||||
|
|
@ -330,12 +331,12 @@ class NetService private constructor() : INetService {
|
|||
}
|
||||
|
||||
fun downloadFile(url: String, downLoadListener: DownLoadListener) {
|
||||
if (httpClient == null) {
|
||||
httpClient = httpsClient(Down_ConnectTimeOut, Down_ReadTimeOut, Down_WriteTimeOut);
|
||||
if (downHttpClient == null) {
|
||||
downHttpClient = httpsClient(Down_ConnectTimeOut, Down_ReadTimeOut, Down_WriteTimeOut);
|
||||
}
|
||||
val request = Request.Builder().get().url(url).build()
|
||||
|
||||
httpClient?.let { hc ->
|
||||
downHttpClient?.let { hc ->
|
||||
val call = hc.newCall(request)
|
||||
call.enqueue(object : Callback {
|
||||
override fun onFailure(call: Call, e: IOException) {
|
||||
|
|
|
|||
|
|
@ -37,8 +37,10 @@ class DomainListAdapter(layoutResId: Int) :
|
|||
domainSelectedTv.visibility = View.INVISIBLE
|
||||
}
|
||||
val addressName = holder.getView<TextView>(R.id.domain_list_item_tv_address_name)
|
||||
// addressName.text = item.address
|
||||
addressName.text = "地址${addressIndex}"
|
||||
if (!TextUtils.isEmpty(item.address)) {
|
||||
addressName.text = item.address.replace(Regex("https://"), "")
|
||||
}
|
||||
// addressName.text = "地址${addressIndex}"
|
||||
addressIndex++
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,8 +9,6 @@ import android.view.LayoutInflater
|
|||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.Button
|
||||
import android.widget.ImageView
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
|
|
@ -20,16 +18,10 @@ import com.tencent.mmkv.MMKV
|
|||
|
||||
import com.yingmao.clash.R
|
||||
import com.yingmao.clash.conf.BZYConstants
|
||||
import com.yingmao.clash.conf.PayType
|
||||
import com.yingmao.clash.entity.ClashNodebBean
|
||||
import com.yingmao.clash.entity.DomainItemBean
|
||||
import com.yingmao.clash.fragment.NewAccFragment.Companion.CHECK_NODE_RESULT_CODE
|
||||
|
||||
import com.yingmao.clash.view.adapter.DomainListAdapter
|
||||
import com.yingmao.clash.view.adapter.NodeListAdapter
|
||||
import com.yingmao.clash.view.dialog.DialogPayTypeChoose.OnPayTypeCheckedListener
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import java.util.HashSet
|
||||
|
||||
|
||||
/**
|
||||
* @author tamsiree
|
||||
|
|
@ -41,10 +33,11 @@ open class DialogDoMainChoose : RxDialog {
|
|||
private set
|
||||
lateinit var but_try: Button
|
||||
private set
|
||||
lateinit var domainRecyclerView: RecyclerView
|
||||
|
||||
lateinit var but_cancel: Button
|
||||
private set
|
||||
lateinit var onTryListener: OnTryButtonListener
|
||||
lateinit var domainRecyclerView: RecyclerView
|
||||
private set
|
||||
lateinit var onTryListener: OnTryButtonListener
|
||||
|
||||
constructor(context: Context?, themeResId: Int) : super(context!!, themeResId) {
|
||||
initView()
|
||||
|
|
@ -75,11 +68,13 @@ open class DialogDoMainChoose : RxDialog {
|
|||
val dialogView = LayoutInflater.from(context).inflate(R.layout.dialog_domain_choose, null)
|
||||
titleView = dialogView.findViewById(R.id.tv_title)
|
||||
but_try = dialogView.findViewById(R.id.but_try)
|
||||
but_cancel = dialogView.findViewById(R.id.but_cancel)
|
||||
domainRecyclerView = dialogView.findViewById(R.id.domian_list)
|
||||
|
||||
but_try.setOnClickListener {
|
||||
onTryListener.tryButton()
|
||||
}
|
||||
but_cancel.setOnClickListener { onTryListener.cancel() }
|
||||
initAdapter()
|
||||
setContentView(dialogView)
|
||||
setCancelable(false)
|
||||
|
|
@ -133,6 +128,7 @@ open class DialogDoMainChoose : RxDialog {
|
|||
|
||||
interface OnTryButtonListener {
|
||||
fun tryButton()
|
||||
fun cancel()
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -64,94 +64,6 @@ class SplashAtyVM : PublicViewMode() {
|
|||
}
|
||||
}
|
||||
|
||||
fun getHost(callback: AsyncCallback) {
|
||||
val rt =
|
||||
NetService.instances.createFreeBaseUrl("https://yingmao.oss-cn-hongkong.aliyuncs.com/")
|
||||
doAsyncNoNeedReturn(HttpReqType.GET_HOST) {
|
||||
try { //TODO bug 会引起崩溃
|
||||
var host = if (BuildConfig.is_ym) {
|
||||
rt.getHost()
|
||||
|
||||
} else if (BuildConfig.is_tz) {
|
||||
rt.getHostTZ()
|
||||
} else {
|
||||
rt.getHostDef()
|
||||
}
|
||||
// Log.e("data", "2:$host")
|
||||
if (!TextUtils.isEmpty(host)) {
|
||||
host = AESUtil.decrypt(host)
|
||||
val hostSet = host.split("+").toSet()
|
||||
MMKV.defaultMMKV().encode(BZYConstants.MMKV_KEY_ROUTER_HOST, hostSet)
|
||||
}
|
||||
// Log.e("data", "22:$host")
|
||||
|
||||
callback.suc()
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
callback.err()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun getHostByGithub(callback: AsyncCallback) {
|
||||
val rt = NetService.instances.createFreeBaseUrl("https://raw.githubusercontent.com/")
|
||||
doAsyncNoNeedReturn(HttpReqType.GET_HOST) {
|
||||
try {
|
||||
val host = when {
|
||||
BuildConfig.is_ym -> {
|
||||
rt.getHostGithub()
|
||||
}
|
||||
BuildConfig.is_tz -> {
|
||||
rt.getHostTZ()
|
||||
}
|
||||
else -> {
|
||||
rt.getHostDef()
|
||||
}
|
||||
}
|
||||
host?.takeIf { it.isNotEmpty() }?.let {
|
||||
com.cncat.vpn.common.log.Log.d("getHostByGithub host-->${it}")
|
||||
val decryptedHost = AESUtil.decrypt(it)
|
||||
com.cncat.vpn.common.log.Log.d("getHostByGithub decryptedHost-->${decryptedHost}")
|
||||
val hostSet = decryptedHost.split("+").toSet()
|
||||
MMKV.defaultMMKV().encode(BZYConstants.MMKV_KEY_ROUTER_HOST, hostSet)
|
||||
}
|
||||
callback.suc()
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
callback.err()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun getHostByAWS(callback: AsyncCallback) {
|
||||
val rt = NetService.instances.createFreeBaseUrl("https://yingmao2.s3.ap-east-1.amazonaws.com/")
|
||||
doAsyncNoNeedReturn(HttpReqType.GET_HOST) {
|
||||
try {
|
||||
val host = when {
|
||||
BuildConfig.is_ym -> {
|
||||
rt.getHostGithub()
|
||||
}
|
||||
BuildConfig.is_tz -> {
|
||||
rt.getHostTZ()
|
||||
}
|
||||
else -> {
|
||||
rt.getHostDef()
|
||||
}
|
||||
}
|
||||
host?.takeIf { it.isNotEmpty() }?.let {
|
||||
com.cncat.vpn.common.log.Log.d("getHostByAWS host-->${it}")
|
||||
val decryptedHost = AESUtil.decrypt(it)
|
||||
com.cncat.vpn.common.log.Log.d("getHostByAWS decryptedHost-->${decryptedHost}")
|
||||
val hostSet = decryptedHost.split("+").toSet()
|
||||
MMKV.defaultMMKV().encode(BZYConstants.MMKV_KEY_ROUTER_HOST, hostSet)
|
||||
}
|
||||
callback.suc()
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
callback.err()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -14,13 +14,13 @@
|
|||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/shape_round_white"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintWidth_percent="0.8"
|
||||
android:gravity="center"
|
||||
tools:ignore="MissingConstraints">
|
||||
|
||||
<TextView
|
||||
|
|
@ -35,19 +35,14 @@
|
|||
android:textSize="16sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/but_try"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/Resend">
|
||||
|
||||
</Button>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/rg_pay_type"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="40dp"
|
||||
android:layout_marginBottom="15dp"
|
||||
android:layout_marginLeft="10dp"
|
||||
android:layout_marginRight="10dp"
|
||||
android:orientation="vertical">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
|
|
@ -57,7 +52,25 @@
|
|||
|
||||
</androidx.recyclerview.widget.RecyclerView>
|
||||
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_margin="15dp"
|
||||
android:layout_height="wrap_content">
|
||||
<Button
|
||||
android:id="@+id/but_cancel"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/cancel">
|
||||
</Button>
|
||||
<Button
|
||||
android:layout_alignParentRight="true"
|
||||
android:id="@+id/but_try"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/Resend">
|
||||
</Button>
|
||||
</RelativeLayout>
|
||||
</LinearLayout>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@
|
|||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/rl_node_list_item"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="67dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="5dp"
|
||||
android:background="@drawable/node_list_item_bg_selector"
|
||||
android:clickable="true"
|
||||
android:focusable="true">
|
||||
|
|
@ -24,7 +24,7 @@
|
|||
android:text="@string/selected"
|
||||
android:visibility="invisible"
|
||||
android:layout_width="wrap_content"
|
||||
android:textColor="@color/white"
|
||||
android:textColor="@color/green"
|
||||
android:layout_centerVertical="true"
|
||||
android:paddingRight="10dp"
|
||||
android:layout_toLeftOf="@+id/domain_item_checked"
|
||||
|
|
|
|||
Loading…
Reference in New Issue