添加自动切换节点
This commit is contained in:
parent
7c964af900
commit
38f5963797
|
|
@ -29,6 +29,7 @@ import com.yingmao.clash.R
|
||||||
import com.yingmao.clash.base.BaseActivity
|
import com.yingmao.clash.base.BaseActivity
|
||||||
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.service.ProfileManager
|
||||||
import com.yingmao.clash.conf.BZYConstants
|
import com.yingmao.clash.conf.BZYConstants
|
||||||
import com.yingmao.clash.conf.Conf
|
import com.yingmao.clash.conf.Conf
|
||||||
import com.yingmao.clash.entity.ClashNodebBean
|
import com.yingmao.clash.entity.ClashNodebBean
|
||||||
|
|
@ -38,8 +39,11 @@ import com.yingmao.clash.remote.Resource
|
||||||
import com.cncat.vpn.service.model.Profile
|
import com.cncat.vpn.service.model.Profile
|
||||||
import com.cncat.vpn.service.remote.IProfileManager
|
import com.cncat.vpn.service.remote.IProfileManager
|
||||||
import com.cncat.vpn.service.remote.IRemoteService
|
import com.cncat.vpn.service.remote.IRemoteService
|
||||||
|
import com.cncat.vpn.service.remote.wrap
|
||||||
|
import com.yingmao.clash.BuildConfig
|
||||||
import com.yingmao.clash.app.MainApplication
|
import com.yingmao.clash.app.MainApplication
|
||||||
import com.yingmao.clash.fragment.home.HomeFragment
|
import com.yingmao.clash.fragment.home.HomeFragment
|
||||||
|
import com.yingmao.clash.util.CommonUtils
|
||||||
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
|
||||||
|
|
@ -100,6 +104,8 @@ class ChangeNodeActivity : BaseActivity(), View.OnClickListener {
|
||||||
|
|
||||||
private fun initData() {
|
private fun initData() {
|
||||||
// clash = MainApplication.getApp()?.let { ClashManager(it) }
|
// clash = MainApplication.getApp()?.let { ClashManager(it) }
|
||||||
|
// profileBinder =
|
||||||
|
// MainApplication.getApp()?.let { ProfileManager(it).wrap() as IProfileManager }
|
||||||
cacheNodeStr = MMKV.defaultMMKV().decodeString(BZYConstants.NODE_All_ITEM_NAME_KEY, "");
|
cacheNodeStr = MMKV.defaultMMKV().decodeString(BZYConstants.NODE_All_ITEM_NAME_KEY, "");
|
||||||
|
|
||||||
val intentFilter = IntentFilter(Intents.ACTION_NODE_LIST)
|
val intentFilter = IntentFilter(Intents.ACTION_NODE_LIST)
|
||||||
|
|
@ -233,14 +239,21 @@ class ChangeNodeActivity : BaseActivity(), View.OnClickListener {
|
||||||
var nowSubUrl: String = ""
|
var nowSubUrl: String = ""
|
||||||
private fun updateProfile(isDelete: Boolean) {
|
private fun updateProfile(isDelete: Boolean) {
|
||||||
// showLoading("正在获取...", this@ChangeNodeActivity)
|
// showLoading("正在获取...", this@ChangeNodeActivity)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
|
|
||||||
launch(Dispatchers.IO) {
|
launch(Dispatchers.IO) {
|
||||||
UIMainActivity.profileBinder?.let { profileManager ->
|
UIMainActivity.profileBinder?.let { profileManager ->
|
||||||
var mProfile = profileManager.queryAll().find {
|
// var mProfile = profileManager.queryAll().find {
|
||||||
it.name == Conf.getClashConfName(this@ChangeNodeActivity.applicationContext)
|
// it.name == Conf.getClashConfName(this@ChangeNodeActivity.applicationContext)
|
||||||
|
// }
|
||||||
|
var mProfile: Profile? = null
|
||||||
|
Log.d("queryAll().size ==>${profileManager.queryAll().size}")
|
||||||
|
profileManager.queryAll().forEach { it_pf ->
|
||||||
|
var confName =
|
||||||
|
Conf.getClashConfName(this@ChangeNodeActivity.applicationContext)
|
||||||
|
Log.d(" it_pf.name ==>${it_pf.name}, confName==>${confName}")
|
||||||
|
if (confName == it_pf.name) {
|
||||||
|
mProfile = it_pf
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mProfile == null) {
|
if (mProfile == null) {
|
||||||
|
|
@ -256,16 +269,16 @@ class ChangeNodeActivity : BaseActivity(), View.OnClickListener {
|
||||||
Log.d("ChangeNode22 uuid==>${profile.uuid}")
|
Log.d("ChangeNode22 uuid==>${profile.uuid}")
|
||||||
if (isDelete) {
|
if (isDelete) {
|
||||||
Log.d("gogogogogo isDelete")
|
Log.d("gogogogogo isDelete")
|
||||||
profileManager.delete(profile.uuid)
|
// profileManager.delete(profile.uuid)
|
||||||
MMKV.defaultMMKV()
|
MMKV.defaultMMKV()
|
||||||
.removeValueForKey(BZYConstants.NODE_All_ITEM_NAME_KEY)
|
.removeValueForKey(BZYConstants.NODE_All_ITEM_NAME_KEY)
|
||||||
setSub2(profileManager, nowSubUrl)
|
|
||||||
} else {
|
} else {
|
||||||
Log.d("gogogogogo update")
|
Log.d("gogogogogo update")
|
||||||
profileManager.setActive(profile)
|
profileManager.setActive(profile)
|
||||||
delay(500)
|
Log.d("updateProfile pro.source==>${profile.source}, url==>${nowSubUrl}")
|
||||||
if (!TextUtils.isEmpty(profile.source)) {
|
if (!TextUtils.isEmpty(profile.source)) {
|
||||||
// Log.d("updateProfile pro.source==>${profile.source}, url==>${nowSubUrl}")
|
|
||||||
if (profile.source != nowSubUrl) {
|
if (profile.source != nowSubUrl) {
|
||||||
Log.d("updateProfile patch")
|
Log.d("updateProfile patch")
|
||||||
profileManager.patch(
|
profileManager.patch(
|
||||||
|
|
@ -280,6 +293,17 @@ class ChangeNodeActivity : BaseActivity(), View.OnClickListener {
|
||||||
}
|
}
|
||||||
Log.d("updateProfile patch 2")
|
Log.d("updateProfile patch 2")
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
profileManager.patch(
|
||||||
|
profile.uuid,
|
||||||
|
profile.name,
|
||||||
|
nowSubUrl,
|
||||||
|
1800000L
|
||||||
|
)
|
||||||
|
Log.d("updateProfile patch new 1")
|
||||||
|
profileManager.commit(profile.uuid) { status ->
|
||||||
|
Log.d("updateProfile new updateStatus: " + Gson().toJson(status.args) + ", pro==>" + status.progress)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Log.d("updateProfile go update")
|
Log.d("updateProfile go update")
|
||||||
profileManager.update(profile.uuid)
|
profileManager.update(profile.uuid)
|
||||||
|
|
@ -318,23 +342,29 @@ class ChangeNodeActivity : BaseActivity(), View.OnClickListener {
|
||||||
UIMainActivity.subUrl?.let {
|
UIMainActivity.subUrl?.let {
|
||||||
nowSubUrl = it
|
nowSubUrl = it
|
||||||
}
|
}
|
||||||
doProfile()
|
doProfile(false)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun doProfile() {
|
fun doProfile(isDelete: Boolean) {
|
||||||
|
Log.d("doProfile....")
|
||||||
if (TextUtils.isEmpty(cacheNodeStr)) {
|
if (TextUtils.isEmpty(cacheNodeStr)) {
|
||||||
|
|
||||||
}
|
}
|
||||||
showLoading("正在获取...", this@ChangeNodeActivity)
|
showLoading("正在获取...", this@ChangeNodeActivity)
|
||||||
startTimer()
|
startTimer()
|
||||||
updateProfile(false)
|
// updateProfile(isDelete)
|
||||||
|
|
||||||
|
launch(Dispatchers.IO) {
|
||||||
|
UIMainActivity.setSub2(nowSubUrl)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun changeSubUrl(originalUrl: String, newUrl: String) {
|
private fun changeSubUrl(originalUrl: String, newUrl: String) {
|
||||||
if (!originalUrl.isNullOrEmpty() && !newUrl.isNullOrEmpty()) {
|
if (!originalUrl.isNullOrEmpty() && !newUrl.isNullOrEmpty()) {
|
||||||
nowSubUrl = originalUrl.replace(Regex("https://[^/]+/"), "$newUrl/")
|
nowSubUrl = originalUrl.replace(Regex("https://[^/]+/"), "$newUrl/")
|
||||||
|
UIMainActivity.subUrl = nowSubUrl
|
||||||
MMKV.defaultMMKV().encode(BZYConstants.PROFILE_SUB_URL, nowSubUrl)
|
MMKV.defaultMMKV().encode(BZYConstants.PROFILE_SUB_URL, nowSubUrl)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -393,7 +423,6 @@ class ChangeNodeActivity : BaseActivity(), View.OnClickListener {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun setNewData(nodes: MutableList<ClashNodebBean>?) {
|
private fun setNewData(nodes: MutableList<ClashNodebBean>?) {
|
||||||
runOnUiThread {
|
runOnUiThread {
|
||||||
if (nodes != null) {
|
if (nodes != null) {
|
||||||
|
|
@ -449,13 +478,25 @@ class ChangeNodeActivity : BaseActivity(), View.OnClickListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createProfile() {
|
private fun createProfile() {
|
||||||
|
cleanProfile()
|
||||||
launch(Dispatchers.IO) {
|
launch(Dispatchers.IO) {
|
||||||
UIMainActivity.profileBinder?.let { pro ->
|
UIMainActivity.profileBinder?.let { pro ->
|
||||||
uuid?.let { uu ->
|
createMyProfile(pro, nowSubUrl)
|
||||||
pro.delete(uu)
|
|
||||||
delay(500)
|
|
||||||
setSub2(pro, UIMainActivity.subUrl)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun cleanProfile() {
|
||||||
|
launch(Dispatchers.IO) {
|
||||||
|
UIMainActivity.profileBinder?.let { pm ->
|
||||||
|
pm.queryAll().forEach { profile ->
|
||||||
|
Log.d("changeNode cleanProfile go delete name==>${profile.name}, uuid==>${profile.uuid}")
|
||||||
|
pm.delete(profile.uuid)
|
||||||
|
}
|
||||||
|
} ?: let {
|
||||||
|
Log.d("changeNode profileBinder is null")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -466,10 +507,6 @@ class ChangeNodeActivity : BaseActivity(), View.OnClickListener {
|
||||||
com.cncat.vpn.common.log.Log.d("setSub2 url isEmpty")
|
com.cncat.vpn.common.log.Log.d("setSub2 url isEmpty")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
com.cncat.vpn.common.log.Log.d("setSub2 2")
|
|
||||||
|
|
||||||
|
|
||||||
com.cncat.vpn.common.log.Log.d("setSub2 3")
|
com.cncat.vpn.common.log.Log.d("setSub2 3")
|
||||||
val pro = pm.queryAll().find {
|
val pro = pm.queryAll().find {
|
||||||
it.name == Conf.getClashConfName(this@ChangeNodeActivity.applicationContext)
|
it.name == Conf.getClashConfName(this@ChangeNodeActivity.applicationContext)
|
||||||
|
|
@ -502,11 +539,40 @@ class ChangeNodeActivity : BaseActivity(), View.OnClickListener {
|
||||||
"new updateStatus: " + Gson().toJson(status.args) + ", pro==>" + status.progress
|
"new updateStatus: " + Gson().toJson(status.args) + ", pro==>" + status.progress
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
suspend fun createMyProfile(pm: IProfileManager, url: String) {
|
||||||
|
var uuid: UUID = pm.create(
|
||||||
|
Profile.Type.Url, Conf.getClashConfName(this@ChangeNodeActivity.applicationContext)
|
||||||
|
)
|
||||||
|
delay(500)
|
||||||
|
pm.queryByUUID(uuid)?.let { qPro ->
|
||||||
|
Log.d("createMyProfile url==>${url}")
|
||||||
|
pm.setActive(qPro)
|
||||||
|
pm.patch(
|
||||||
|
qPro.uuid, qPro.name,
|
||||||
|
// "https://mojie0201.xn--8stx8olrwkucjq3b.com/api/v1/client/subscribe?token=169110d2674c49604b7e5b5cea341579",
|
||||||
|
// "https://www.otcopusapp.cc/lx3af288h5i8pz380/api/v1/client/subscribe?token=d6bc98c7ea53099fa5bd1a3ea415ebb6",
|
||||||
|
// "https://reg.bazhuayujiasu.cc/api/v1/client/subscribe?token=7f0f025ab341bcec4822d2c90aadf8b0",
|
||||||
|
url, 1800000L
|
||||||
|
)
|
||||||
|
// coroutineScope {
|
||||||
|
pm.commit(qPro.uuid) { status ->
|
||||||
|
android.util.Log.d(
|
||||||
|
Conf.TAG,
|
||||||
|
"new updateStatus: " + Gson().toJson(status.args) + ", pro==>" + status.progress
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UIMainActivity.profileBinder = pm
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var isCreate: Boolean = false
|
var isCreate: Boolean = false
|
||||||
private var timerJob: Job? = null
|
private var timerJob: Job? = null
|
||||||
private fun startTimer() {
|
private fun startTimer() {
|
||||||
|
|
@ -514,15 +580,42 @@ class ChangeNodeActivity : BaseActivity(), View.OnClickListener {
|
||||||
timerJob = launch {
|
timerJob = launch {
|
||||||
repeat(16) {
|
repeat(16) {
|
||||||
Log.d("GetNodeTimeOutNum==>$GetNodeTimeOutNum")
|
Log.d("GetNodeTimeOutNum==>$GetNodeTimeOutNum")
|
||||||
|
|
||||||
if (GetNodeTimeOutNum == 0) {
|
if (GetNodeTimeOutNum == 0) {
|
||||||
hideLoading()
|
hideLoading()
|
||||||
Log.d("stopTimer...")
|
Log.d("stopTimer...")
|
||||||
RxToast.error("获取节点失败...请尝试切换其他地址")
|
RxToast.error("获取节点失败...正在切换其他地址")
|
||||||
showDomainList()
|
// showDomainList()
|
||||||
|
// var mmkv = MMKV.defaultMMKV()
|
||||||
|
// var currentHost = mmkv.decodeString(BZYConstants.MMKV_KEY_CURRENT_HOST, "")
|
||||||
|
if (setNewData()) {
|
||||||
timerJob?.cancel()
|
timerJob?.cancel()
|
||||||
|
// cleanProfile()
|
||||||
|
MMKV.defaultMMKV()
|
||||||
|
.removeValueForKey(BZYConstants.NODE_All_ITEM_NAME_KEY)
|
||||||
|
// createProfile()
|
||||||
|
saveSubUrl()
|
||||||
|
|
||||||
|
MainApplication.restartApp(this@ChangeNodeActivity, object :
|
||||||
|
MainApplication.OnRestartButtonListener {
|
||||||
|
|
||||||
|
override fun enterButton() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun cancelButton() {
|
||||||
|
doProfile(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
// doProfile(false)
|
||||||
|
// isCreate=true
|
||||||
|
} else {
|
||||||
|
timerJob?.cancel()
|
||||||
|
RxToast.error("获取全部线路失败...请切换网络重试")
|
||||||
|
}
|
||||||
// delay(1000)
|
// delay(1000)
|
||||||
// this@ChangeNodeActivity.finish()
|
// this@ChangeNodeActivity.finish()
|
||||||
|
|
||||||
}
|
}
|
||||||
GetNodeTimeOutNum--
|
GetNodeTimeOutNum--
|
||||||
delay(1000)
|
delay(1000)
|
||||||
|
|
@ -545,7 +638,7 @@ class ChangeNodeActivity : BaseActivity(), View.OnClickListener {
|
||||||
DialogDoMainChoose.OnTryButtonListener {
|
DialogDoMainChoose.OnTryButtonListener {
|
||||||
override fun tryButton() {
|
override fun tryButton() {
|
||||||
saveSubUrl()
|
saveSubUrl()
|
||||||
doProfile()
|
doProfile(false)
|
||||||
dialogDoMainChoose?.dismiss()
|
dialogDoMainChoose?.dismiss()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -567,7 +660,7 @@ class ChangeNodeActivity : BaseActivity(), View.OnClickListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun cancelButton() {
|
override fun cancelButton() {
|
||||||
doProfile()
|
doProfile(false)
|
||||||
dialogDoMainChoose?.dismiss()
|
dialogDoMainChoose?.dismiss()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -585,10 +678,90 @@ class ChangeNodeActivity : BaseActivity(), View.OnClickListener {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun setNewData(): Boolean {
|
||||||
|
var mmkv = MMKV.defaultMMKV()
|
||||||
|
val originalUrl =
|
||||||
|
mmkv.decodeString(BZYConstants.MMKV_KEY_CURRENT_HOST, BuildConfig.service_url)
|
||||||
|
var newUrlString = originalUrl
|
||||||
|
var isChange = false
|
||||||
|
val routerHost = mmkv.decodeStringSet(BZYConstants.MMKV_KEY_ROUTER_HOST, HashSet())
|
||||||
|
var switchFinshSet = mmkv.decodeStringSet(BZYConstants.MMKV_KEY_Switch_Finsh_Set, HashSet())
|
||||||
|
routerHost?.let {
|
||||||
|
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
|
// if (!isNetworkAvailable(this@BaseActivity)){
|
||||||
|
// return isChange
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
if (it.isEmpty()) {
|
||||||
|
android.util.Log.d(Conf.TAG, "routerHost isEmpty")
|
||||||
|
return isChange
|
||||||
|
}
|
||||||
|
com.cncat.vpn.common.log.Log.d("switchFinshSet.size==>${switchFinshSet?.size!!} , routerHost.size==>${routerHost.size}")
|
||||||
|
//次数已满
|
||||||
|
if (switchFinshSet?.size!! >= routerHost.size) {
|
||||||
|
return isChange
|
||||||
|
}
|
||||||
|
android.util.Log.d(Conf.TAG, "routerHost not empty")
|
||||||
|
for (url in it) {
|
||||||
|
// com.cncat.vpn.common.log.Log.d("url==>$url")
|
||||||
|
|
||||||
|
if (url == originalUrl) {
|
||||||
|
switchFinshSet?.add(url)
|
||||||
|
mmkv.encode(BZYConstants.MMKV_KEY_Switch_Finsh_Set, switchFinshSet)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if (switchFinshSet?.contains(url) == true) {
|
||||||
|
continue
|
||||||
|
} else {
|
||||||
|
isChange = true
|
||||||
|
android.util.Log.e("Retry", "切换到新url:$url")
|
||||||
|
newUrlString = url
|
||||||
|
switchFinshSet?.add(newUrlString)
|
||||||
|
mmkv.encode(BZYConstants.MMKV_KEY_Switch_Finsh_Set, switchFinshSet)
|
||||||
|
// mmkv.encode(BZYConstants.MMKV_KEY_OLD_CURRENT_HOST, newUrlString)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// val iterator = it.iterator()
|
||||||
|
// while (iterator.hasNext()) {
|
||||||
|
// val newUrl = iterator.next()
|
||||||
|
// android.util.Log.e(
|
||||||
|
// "Data",
|
||||||
|
// "遍历备用的url:$newUrl, contains==>${switchFinshSet?.contains(newUrl)}"
|
||||||
|
// )
|
||||||
|
// if (newUrl == originalUrl) {
|
||||||
|
// switchFinshSet?.add(newUrl)
|
||||||
|
// iterator.remove()
|
||||||
|
// continue
|
||||||
|
// }
|
||||||
|
// if (switchFinshSet?.contains(newUrl) == true) {
|
||||||
|
// iterator.remove()
|
||||||
|
// } else {
|
||||||
|
// android.util.Log.e("Retry", "切换到新url:$newUrl")
|
||||||
|
// newUrlString = newUrl
|
||||||
|
// iterator.remove()
|
||||||
|
// if (originalUrl != null) {
|
||||||
|
// switchFinshSet?.add(originalUrl)
|
||||||
|
// mmkv.encode(BZYConstants.MMKV_KEY_Switch_Finsh_Set, switchFinshSet)
|
||||||
|
// mmkv.encode(BZYConstants.MMKV_KEY_OLD_CURRENT_HOST, originalUrl)
|
||||||
|
// }
|
||||||
|
// break
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// mmkv.encode(BZYConstants.MMKV_KEY_ROUTER_HOST, routerHost)
|
||||||
|
|
||||||
|
mmkv.encode(BZYConstants.MMKV_KEY_CURRENT_HOST, newUrlString)
|
||||||
|
|
||||||
|
}
|
||||||
|
return isChange
|
||||||
|
}
|
||||||
|
|
||||||
private fun saveSubUrl() {
|
private fun saveSubUrl() {
|
||||||
var currentHost = MMKV.defaultMMKV()
|
var currentHost = MMKV.defaultMMKV()
|
||||||
.decodeString(BZYConstants.MMKV_KEY_CURRENT_HOST, "")
|
.decodeString(BZYConstants.MMKV_KEY_CURRENT_HOST, "")
|
||||||
// com.cncat.vpn.common.log.Log.d("tryButton currentHost==>${currentHost}")
|
com.cncat.vpn.common.log.Log.d("tryButton currentHost==>${currentHost}")
|
||||||
var oldUrl = nowSubUrl
|
var oldUrl = nowSubUrl
|
||||||
currentHost?.let { changeSubUrl(oldUrl, it) }
|
currentHost?.let { changeSubUrl(oldUrl, it) }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -362,7 +362,19 @@ class MemberRechargeActivity : BaseActivity() {
|
||||||
override fun httpFailure(httpStatus: HttpStatus.Failure) {
|
override fun httpFailure(httpStatus: HttpStatus.Failure) {
|
||||||
when (httpStatus.reqType) {
|
when (httpStatus.reqType) {
|
||||||
HttpReqType.GET_RECHARGE_INFO -> {
|
HttpReqType.GET_RECHARGE_INFO -> {
|
||||||
showDomainList()
|
// showDomainList()
|
||||||
|
if (super.switchServer2()) {
|
||||||
|
val username =
|
||||||
|
MMKV.defaultMMKV()
|
||||||
|
.decodeString(BZYConstants.MMKV_KEY_REMEMBER_USERNAME, "")!!
|
||||||
|
val phToken =
|
||||||
|
MMKV.defaultMMKV().decodeString(BZYConstants.MMKV_KEY_PH_TOKEN, "")!!
|
||||||
|
val userId = MMKV.defaultMMKV().decodeString(BZYConstants.MMKV_KEY_USER_ID)!!
|
||||||
|
viewModel.getPhRechargeInfo(username, phToken, userId)
|
||||||
|
} else {
|
||||||
|
// super.switchFinshSet?.clear()
|
||||||
|
}
|
||||||
|
|
||||||
Logger.d("获取充值续费信息异常${httpStatus.msg}")
|
Logger.d("获取充值续费信息异常${httpStatus.msg}")
|
||||||
swipeLayout.isRefreshing = false
|
swipeLayout.isRefreshing = false
|
||||||
RxToast.error(resources.getString(R.string.DataError))
|
RxToast.error(resources.getString(R.string.DataError))
|
||||||
|
|
|
||||||
|
|
@ -128,8 +128,8 @@ class NewMainActivity : BaseActivity() {
|
||||||
|
|
||||||
// private var profile: ProfileManager? = null
|
// private var profile: ProfileManager? = null
|
||||||
// private var clashManager: ClashManager? = null
|
// private var clashManager: ClashManager? = null
|
||||||
var clashBinder: IClashManager? = null
|
private var clashBinder: IClashManager? = null
|
||||||
var profileBinder: IProfileManager? = null
|
private var profileBinder: IProfileManager? = null
|
||||||
var newMainActGlo: Boolean = false
|
var newMainActGlo: Boolean = false
|
||||||
var isUpload: Boolean = false
|
var isUpload: Boolean = false
|
||||||
var hostsMem: ArrayList<String> = ArrayList()
|
var hostsMem: ArrayList<String> = ArrayList()
|
||||||
|
|
@ -1187,6 +1187,7 @@ class NewMainActivity : BaseActivity() {
|
||||||
|
|
||||||
|
|
||||||
suspend fun createMyProfile(pm: IProfileManager, url: String) {
|
suspend fun createMyProfile(pm: IProfileManager, url: String) {
|
||||||
|
Log.d("createMyProfile")
|
||||||
var uuid: UUID = pm.create(
|
var uuid: UUID = pm.create(
|
||||||
Profile.Type.Url, Conf.getClashConfName(this@NewMainActivity.applicationContext)
|
Profile.Type.Url, Conf.getClashConfName(this@NewMainActivity.applicationContext)
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -110,7 +110,7 @@ class SettingActivity : BaseActivity() {
|
||||||
showLoading(resources.getString(R.string.UnderRepair), this@SettingActivity)
|
showLoading(resources.getString(R.string.UnderRepair), this@SettingActivity)
|
||||||
|
|
||||||
launch(Dispatchers.IO) {
|
launch(Dispatchers.IO) {
|
||||||
NewMainActivity.profileBinder?.let { pm ->
|
UIMainActivity.profileBinder?.let { pm ->
|
||||||
pm.queryAll().forEach { profile ->
|
pm.queryAll().forEach { profile ->
|
||||||
Log.d("setting profile delete ==>${profile.name}")
|
Log.d("setting profile delete ==>${profile.name}")
|
||||||
pm.delete(profile.uuid)
|
pm.delete(profile.uuid)
|
||||||
|
|
|
||||||
|
|
@ -21,9 +21,9 @@ class SplashHelper(private val splashAtyVM: PublicViewMode) {
|
||||||
third: (AsyncCallback) -> Unit,
|
third: (AsyncCallback) -> Unit,
|
||||||
callback: (Boolean) -> Unit
|
callback: (Boolean) -> Unit
|
||||||
) {
|
) {
|
||||||
first(createCallback("getHost method success", "getHostByGithub method failed", callback) {
|
first(createCallback("getHost method success", "getHost method failed", callback) {
|
||||||
second(createCallback("getHostByAWS method success", "getHostByAWS method failed", callback) {
|
second(createCallback("getHostByAWS method success", "getHostByAWS method failed", callback) {
|
||||||
third(createCallback("getHost method success", "getHost methods failed", callback) {
|
third(createCallback("getHostByGithub method success", "getHostByGithub methods failed", callback) {
|
||||||
callback(false) // 所有方法都失败
|
callback(false) // 所有方法都失败
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -239,6 +239,11 @@ class SplashActivity : BaseActivity() {
|
||||||
com.cncat.vpn.common.log.Log.d("si==>${si}, ss1==>${ss1}, ss2==>${ss2}")
|
com.cncat.vpn.common.log.Log.d("si==>${si}, ss1==>${ss1}, ss2==>${ss2}")
|
||||||
MainApplication.KEY2 = ss1
|
MainApplication.KEY2 = ss1
|
||||||
MainApplication.IV2 = ss2
|
MainApplication.IV2 = ss2
|
||||||
|
|
||||||
|
|
||||||
|
// val byteArrayToHexStr =
|
||||||
|
// AESUtil.byteArrayToHexStr(AESUtil.encrypt("https://api.kuaifei.net+https://api.wfvpnpro.com+https://wf.jimao.xyz+https://api.msljsqpro.com+https://api.mashanglianjsq.com"))
|
||||||
|
// android.util.Log.i("AAAAAAAAAAAAAAAA","data::"+byteArrayToHexStr+"::")
|
||||||
// 太子
|
// 太子
|
||||||
// com.cncat.vpn.common.log.Log.d("tz encrypt:"+ AESUtil.byteArrayToHexStr(AESUtil.encrypt("")))
|
// com.cncat.vpn.common.log.Log.d("tz encrypt:"+ AESUtil.byteArrayToHexStr(AESUtil.encrypt("")))
|
||||||
// 八爪鱼 com.cncat.vpn.common.log.Log.d("bzy encrypt:"+ AESUtil.byteArrayToHexStr(AESUtil.encrypt("")))
|
// 八爪鱼 com.cncat.vpn.common.log.Log.d("bzy encrypt:"+ AESUtil.byteArrayToHexStr(AESUtil.encrypt("")))
|
||||||
|
|
@ -817,6 +822,7 @@ class SplashActivity : BaseActivity() {
|
||||||
val expired = checkLoginRsp.data?.expired
|
val expired = checkLoginRsp.data?.expired
|
||||||
val isPerfect = checkLoginRsp.data?.isPerfect
|
val isPerfect = checkLoginRsp.data?.isPerfect
|
||||||
val userCommand = checkLoginRsp.data?.userCommand
|
val userCommand = checkLoginRsp.data?.userCommand
|
||||||
|
val logSwitch = checkLoginRsp.data?.logSwitch
|
||||||
val mmkv = MMKV.defaultMMKV()
|
val mmkv = MMKV.defaultMMKV()
|
||||||
mmkv.encode(BZYConstants.MMKV_KEY_VPN_EXPIRED, expired ?: true)
|
mmkv.encode(BZYConstants.MMKV_KEY_VPN_EXPIRED, expired ?: true)
|
||||||
mmkv.encode(
|
mmkv.encode(
|
||||||
|
|
@ -825,11 +831,8 @@ class SplashActivity : BaseActivity() {
|
||||||
)
|
)
|
||||||
mmkv.encode(BZYConstants.MMKV_KEY_IS_PERFECT, isPerfect ?: true)
|
mmkv.encode(BZYConstants.MMKV_KEY_IS_PERFECT, isPerfect ?: true)
|
||||||
mmkv.encode(BZYConstants.MMKV_KEY_VPN_UserCommand, userCommand ?: "")
|
mmkv.encode(BZYConstants.MMKV_KEY_VPN_UserCommand, userCommand ?: "")
|
||||||
|
mmkv.encode(BZYConstants.MMKV_KEY_VPN_LogSwitch, logSwitch ?: "")
|
||||||
|
|
||||||
toMainPage()
|
toMainPage()
|
||||||
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
toLoginPage()
|
toLoginPage()
|
||||||
}
|
}
|
||||||
|
|
@ -903,56 +906,56 @@ class SplashActivity : BaseActivity() {
|
||||||
rlPb.visibility = View.GONE
|
rlPb.visibility = View.GONE
|
||||||
pb_web?.visibility = View.INVISIBLE
|
pb_web?.visibility = View.INVISIBLE
|
||||||
com.cncat.vpn.common.log.Log.d("httpFailure HttpReqType.REGISTER")
|
com.cncat.vpn.common.log.Log.d("httpFailure HttpReqType.REGISTER")
|
||||||
try {
|
// try {
|
||||||
RxToast.error("检测到网络异常,请尝试切换其他地址.")
|
// RxToast.error("检测到网络异常,请尝试切换其他地址.")
|
||||||
if (dialogDoMainChoose == null) {
|
// if (dialogDoMainChoose == null) {
|
||||||
dialogDoMainChoose = DialogDoMainChoose(this@SplashActivity)
|
// dialogDoMainChoose = DialogDoMainChoose(this@SplashActivity)
|
||||||
}
|
// }
|
||||||
if (dialogDoMainChoose?.isShowing == false) {
|
// if (dialogDoMainChoose?.isShowing == false) {
|
||||||
dialogDoMainChoose?.setOnTryButtonListener(object :
|
// dialogDoMainChoose?.setOnTryButtonListener(object :
|
||||||
DialogDoMainChoose.OnTryButtonListener {
|
// DialogDoMainChoose.OnTryButtonListener {
|
||||||
override fun tryButton() {
|
// override fun tryButton() {
|
||||||
var currentHost = MMKV.defaultMMKV()
|
// var currentHost = MMKV.defaultMMKV()
|
||||||
.decodeString(BZYConstants.MMKV_KEY_CURRENT_HOST, "")
|
// .decodeString(BZYConstants.MMKV_KEY_CURRENT_HOST, "")
|
||||||
// com.cncat.vpn.common.log.Log.d("tryButton currentHost==>${currentHost}")
|
//// 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?.setOnListItemListener(object :
|
|
||||||
DialogDoMainChoose.OnListItemListener {
|
|
||||||
override fun listItemClick() {
|
|
||||||
doRegisterByEncryption()
|
|
||||||
dialogDoMainChoose?.dismiss()
|
|
||||||
}
|
|
||||||
|
|
||||||
})
|
|
||||||
dialogDoMainChoose?.show()
|
|
||||||
}
|
|
||||||
} catch (e: Exception) {
|
|
||||||
e.printStackTrace()
|
|
||||||
}
|
|
||||||
// if (super.switchServer()) {//切换服务器并直接重试
|
|
||||||
//// doRegister()
|
|
||||||
// doRegisterByEncryption()
|
|
||||||
// } else {
|
|
||||||
// MaterialDialog(this@SplashActivity).show {
|
|
||||||
// message(text = initErrMsg)
|
|
||||||
// positiveButton(R.string.retry) {
|
|
||||||
//// doRegister()
|
|
||||||
// doRegisterByEncryption()
|
// doRegisterByEncryption()
|
||||||
// }
|
// }
|
||||||
// negativeButton(R.string.cancel) {
|
//
|
||||||
// it.dismiss()
|
// override fun cancel() {
|
||||||
// finish()
|
// com.cncat.vpn.common.log.Log.d("tryButton REGISTER cancel")
|
||||||
|
// dialogDoMainChoose?.dismiss()
|
||||||
|
// dialogDoMainChoose = null
|
||||||
// }
|
// }
|
||||||
|
// })
|
||||||
|
// dialogDoMainChoose?.setOnListItemListener(object :
|
||||||
|
// DialogDoMainChoose.OnListItemListener {
|
||||||
|
// override fun listItemClick() {
|
||||||
|
// doRegisterByEncryption()
|
||||||
|
// dialogDoMainChoose?.dismiss()
|
||||||
// }
|
// }
|
||||||
|
//
|
||||||
|
// })
|
||||||
|
// dialogDoMainChoose?.show()
|
||||||
// }
|
// }
|
||||||
|
// } catch (e: Exception) {
|
||||||
|
// e.printStackTrace()
|
||||||
|
// }
|
||||||
|
if (super.switchServer2()) {//切换服务器并直接重试
|
||||||
|
// doRegister()
|
||||||
|
doRegisterByEncryption()
|
||||||
|
} else {
|
||||||
|
MaterialDialog(this@SplashActivity).show {
|
||||||
|
message(text = initErrMsg)
|
||||||
|
positiveButton(R.string.retry) {
|
||||||
|
// doRegister()
|
||||||
|
doRegisterByEncryption()
|
||||||
|
}
|
||||||
|
negativeButton(R.string.cancel) {
|
||||||
|
it.dismiss()
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
HttpReqType.LOGIN -> {
|
HttpReqType.LOGIN -> {
|
||||||
|
|
|
||||||
|
|
@ -94,6 +94,7 @@ class UIMainActivity : BaseActivity() {
|
||||||
private var newMainActGlo: Boolean = false
|
private var newMainActGlo: Boolean = false
|
||||||
private var homeFragment: HomeFragment? = null
|
private var homeFragment: HomeFragment? = null
|
||||||
private var settingFragment: SettingFragment? = null
|
private var settingFragment: SettingFragment? = null
|
||||||
|
|
||||||
@SuppressLint("SimpleDateFormat")
|
@SuppressLint("SimpleDateFormat")
|
||||||
private val dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
|
private val dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
|
||||||
private var activityDialog: ActivityViewDialog? = null
|
private var activityDialog: ActivityViewDialog? = null
|
||||||
|
|
@ -113,6 +114,69 @@ class UIMainActivity : BaseActivity() {
|
||||||
var hostsMem: ArrayList<String> = ArrayList()
|
var hostsMem: ArrayList<String> = ArrayList()
|
||||||
var isSubed = false
|
var isSubed = false
|
||||||
var newMainActGlo: Boolean = false
|
var newMainActGlo: Boolean = false
|
||||||
|
public suspend fun setSub2(url: String) {
|
||||||
|
profileBinder?.let { pm ->
|
||||||
|
pm.queryAll().forEach { itemPro ->
|
||||||
|
Log.d("uimain setSub2 itemPro.name==${itemPro.name}")
|
||||||
|
if (itemPro.name != Conf.getClashConfName(MainApplication.getApp()?.applicationContext)) {
|
||||||
|
Log.d("setSub2 delete ==>${itemPro.name}")
|
||||||
|
pm.delete(itemPro.uuid)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var mProfile = pm.queryAll().find {
|
||||||
|
it.name == Conf.getClashConfName(MainApplication.getApp()?.applicationContext)
|
||||||
|
}
|
||||||
|
|
||||||
|
mProfile?.let {
|
||||||
|
var actname = it.name
|
||||||
|
Log.d("new main actname==>" + actname)
|
||||||
|
Log.d("setSub2 pro 已存在 ==>")
|
||||||
|
pm.setActive(it)
|
||||||
|
delay(500)
|
||||||
|
//判断配置文件source
|
||||||
|
if (!TextUtils.isEmpty(mProfile.source)) {
|
||||||
|
Log.d("setSub2 pro.source==>${mProfile.source}, url==>${url}")
|
||||||
|
//订阅链接不同就更换
|
||||||
|
if (mProfile.source != url) {
|
||||||
|
pm.patch(
|
||||||
|
mProfile.uuid, mProfile.name,
|
||||||
|
url, 1800000L
|
||||||
|
)
|
||||||
|
pm.commit(mProfile.uuid) { status ->
|
||||||
|
android.util.Log.d(
|
||||||
|
Conf.TAG,
|
||||||
|
"new updateStatus: " + Gson().toJson(status.args) + ", pro==>" + status.progress
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pm.update(it.uuid)
|
||||||
|
newUuid = mProfile.uuid.toString()
|
||||||
|
isSubbed = true
|
||||||
|
} ?: run {
|
||||||
|
Log.d("setSub2 go create")
|
||||||
|
val uuid: UUID = pm.create(
|
||||||
|
Profile.Type.Url, Conf.getClashConfName(MainApplication.getApp()?.applicationContext)
|
||||||
|
)
|
||||||
|
delay(500)
|
||||||
|
pm.queryByUUID(uuid)?.let { qPro ->
|
||||||
|
pm.setActive(qPro)
|
||||||
|
pm.patch(
|
||||||
|
qPro.uuid, qPro.name,
|
||||||
|
url, 1800000L
|
||||||
|
)
|
||||||
|
pm.commit(qPro.uuid) { status ->
|
||||||
|
android.util.Log.d(
|
||||||
|
Conf.TAG,
|
||||||
|
"new updateStatus: " + Gson().toJson(status.args) + ", pro==>" + status.progress
|
||||||
|
)
|
||||||
|
}
|
||||||
|
newUuid = qPro.uuid.toString()
|
||||||
|
isSubbed = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
|
@ -148,6 +212,7 @@ class UIMainActivity : BaseActivity() {
|
||||||
if (homeFragment == null) homeFragment = HomeFragment()
|
if (homeFragment == null) homeFragment = HomeFragment()
|
||||||
showFragment(homeFragment!!)
|
showFragment(homeFragment!!)
|
||||||
}
|
}
|
||||||
|
|
||||||
R.id.navigation_setting -> {
|
R.id.navigation_setting -> {
|
||||||
if (settingFragment == null) settingFragment = SettingFragment()
|
if (settingFragment == null) settingFragment = SettingFragment()
|
||||||
showFragment(settingFragment!!)
|
showFragment(settingFragment!!)
|
||||||
|
|
@ -163,6 +228,7 @@ class UIMainActivity : BaseActivity() {
|
||||||
transaction.replace(R.id.fragmentContainer, fragment)
|
transaction.replace(R.id.fragmentContainer, fragment)
|
||||||
transaction.commit()
|
transaction.commit()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun showFragment(fragment: Fragment) {
|
private fun showFragment(fragment: Fragment) {
|
||||||
val fragmentManager = supportFragmentManager
|
val fragmentManager = supportFragmentManager
|
||||||
val transaction = fragmentManager.beginTransaction()
|
val transaction = fragmentManager.beginTransaction()
|
||||||
|
|
@ -179,6 +245,7 @@ class UIMainActivity : BaseActivity() {
|
||||||
}
|
}
|
||||||
transaction.commit()
|
transaction.commit()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun httpLoading(httpStatus: HttpStatus.Loading) {
|
override fun httpLoading(httpStatus: HttpStatus.Loading) {
|
||||||
if (httpStatus.reqType == HttpReqType.HEARTBEAT) {
|
if (httpStatus.reqType == HttpReqType.HEARTBEAT) {
|
||||||
Logger.d("心跳中")
|
Logger.d("心跳中")
|
||||||
|
|
@ -196,25 +263,26 @@ class UIMainActivity : BaseActivity() {
|
||||||
}
|
}
|
||||||
data.data.let { url ->
|
data.data.let { url ->
|
||||||
android.util.Log.e("Data", "机场URL:=${url}")
|
android.util.Log.e("Data", "机场URL:=${url}")
|
||||||
|
var url2="https://api.ymvpnpro11.cc:8700/7air2vr7ikiqzgvxz/api/v1/client/subscribe?token=22f3d75079ec6fa546c1862c4354e448"
|
||||||
// if (url.isNotEmpty()) {
|
// if (url.isNotEmpty()) {
|
||||||
// subUrl = url
|
// subUrl = url
|
||||||
// lifecycleScope.launch(Dispatchers.IO) {
|
// lifecycleScope.launch(Dispatchers.IO) {
|
||||||
// setSub2(url)
|
// setSub2(url)
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
if (url.isNotEmpty()) {
|
if (url2.isNotEmpty()) {
|
||||||
//todo 判断订阅地址是否修改过,未修改就用接口返回的地址反之使用本地修改的地址
|
//todo 判断订阅地址是否修改过,未修改就用接口返回的地址反之使用本地修改的地址
|
||||||
var pro_sub_url =
|
var pro_sub_url =
|
||||||
MMKV.defaultMMKV().decodeString(BZYConstants.PROFILE_SUB_URL, "")
|
MMKV.defaultMMKV().decodeString(BZYConstants.PROFILE_SUB_URL, "")
|
||||||
// Log.d("pro_sub_url==>${pro_sub_url}")
|
// Log.d("pro_sub_url==>${pro_sub_url}")
|
||||||
if (!TextUtils.isEmpty(pro_sub_url)) {
|
if (!TextUtils.isEmpty(pro_sub_url)) {
|
||||||
if (pro_sub_url == url) {
|
if (pro_sub_url == url2) {
|
||||||
subUrl = url
|
subUrl = url2
|
||||||
} else {
|
} else {
|
||||||
subUrl = pro_sub_url
|
subUrl = pro_sub_url
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
subUrl = url
|
subUrl = url2
|
||||||
}
|
}
|
||||||
lifecycleScope.launch(Dispatchers.IO) {
|
lifecycleScope.launch(Dispatchers.IO) {
|
||||||
// setSub(url)
|
// setSub(url)
|
||||||
|
|
@ -263,8 +331,10 @@ class UIMainActivity : BaseActivity() {
|
||||||
val expired = checkLoginRsp.data.expired
|
val expired = checkLoginRsp.data.expired
|
||||||
mmkv.encode(BZYConstants.MMKV_KEY_VPN_EXPIRED, expired ?: true)
|
mmkv.encode(BZYConstants.MMKV_KEY_VPN_EXPIRED, expired ?: true)
|
||||||
mmkv.encode(BZYConstants.MMKV_KEY_VPN_VALID_PERIOD, nowExpireTime)
|
mmkv.encode(BZYConstants.MMKV_KEY_VPN_VALID_PERIOD, nowExpireTime)
|
||||||
val hf = supportFragmentManager.findFragmentById(R.id.fragmentContainer) as? HomeFragment
|
val hf =
|
||||||
val sf = supportFragmentManager.findFragmentById(R.id.fragmentContainer) as? SettingFragment
|
supportFragmentManager.findFragmentById(R.id.fragmentContainer) as? HomeFragment
|
||||||
|
val sf =
|
||||||
|
supportFragmentManager.findFragmentById(R.id.fragmentContainer) as? SettingFragment
|
||||||
hf?.setExpireDate()
|
hf?.setExpireDate()
|
||||||
sf?.setExpireDate()
|
sf?.setExpireDate()
|
||||||
checkPayResultDia?.dismiss()
|
checkPayResultDia?.dismiss()
|
||||||
|
|
@ -343,6 +413,7 @@ class UIMainActivity : BaseActivity() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun showLoadingDialog(msg: String) {
|
private fun showLoadingDialog(msg: String) {
|
||||||
payResultLoading = RxDialogShapeLoading(this)
|
payResultLoading = RxDialogShapeLoading(this)
|
||||||
payResultLoading!!.setMessage(msg)
|
payResultLoading!!.setMessage(msg)
|
||||||
|
|
@ -356,7 +427,11 @@ class UIMainActivity : BaseActivity() {
|
||||||
MMKV.defaultMMKV().removeValueForKey(BZYConstants.NODE_SELECTED_NAME_KEY)
|
MMKV.defaultMMKV().removeValueForKey(BZYConstants.NODE_SELECTED_NAME_KEY)
|
||||||
MMKV.defaultMMKV().removeValueForKey(BZYConstants.MMKV_KEY_VPN_UserCommand)
|
MMKV.defaultMMKV().removeValueForKey(BZYConstants.MMKV_KEY_VPN_UserCommand)
|
||||||
MMKV.defaultMMKV().removeValueForKey(BZYConstants.NODE_All_ITEM_NAME_KEY)
|
MMKV.defaultMMKV().removeValueForKey(BZYConstants.NODE_All_ITEM_NAME_KEY)
|
||||||
|
MMKV.defaultMMKV().removeValueForKey(BZYConstants.PROFILE_SUB_URL)
|
||||||
|
MMKV.defaultMMKV().removeValueForKey(BZYConstants.MMKV_KEY_Switch_Finsh_Set)
|
||||||
Log.d("cleanUserInfo clashRunning==>${clashRunning}")
|
Log.d("cleanUserInfo clashRunning==>${clashRunning}")
|
||||||
|
//清除源切换记录
|
||||||
|
|
||||||
if (clashRunning) {
|
if (clashRunning) {
|
||||||
fragments.filterIsInstance<HomeFragment>().forEach { it.stopClash() }
|
fragments.filterIsInstance<HomeFragment>().forEach { it.stopClash() }
|
||||||
}
|
}
|
||||||
|
|
@ -401,61 +476,7 @@ class UIMainActivity : BaseActivity() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun setSub2(url: String) {
|
|
||||||
profileBinder?.let { pm ->
|
|
||||||
pm.queryAll().forEach { itemPro ->
|
|
||||||
if (itemPro.name != Conf.getClashConfName(this@UIMainActivity.applicationContext)) {
|
|
||||||
pm.delete(itemPro.uuid)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
val pro = pm.queryActive()
|
|
||||||
|
|
||||||
pro?.let {
|
|
||||||
pm.setActive(it)
|
|
||||||
delay(500)
|
|
||||||
//判断配置文件source
|
|
||||||
if (!TextUtils.isEmpty(pro.source)) {
|
|
||||||
Log.d("setSub2 pro.source==>${pro.source}, url==>${url}")
|
|
||||||
//订阅链接不同就更换
|
|
||||||
if (pro.source != url) {
|
|
||||||
pm.patch(
|
|
||||||
pro.uuid, pro.name,
|
|
||||||
url, 1800000L
|
|
||||||
)
|
|
||||||
pm.commit(pro.uuid) { status ->
|
|
||||||
android.util.Log.d(
|
|
||||||
Conf.TAG,
|
|
||||||
"new updateStatus: " + Gson().toJson(status.args) + ", pro==>" + status.progress
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pm.update(it.uuid)
|
|
||||||
newUuid = pro.uuid.toString()
|
|
||||||
isSubbed = true
|
|
||||||
} ?: run {
|
|
||||||
val uuid: UUID = pm.create(
|
|
||||||
Profile.Type.Url, Conf.getClashConfName(this@UIMainActivity.applicationContext)
|
|
||||||
)
|
|
||||||
delay(500)
|
|
||||||
pm.queryByUUID(uuid)?.let { qPro ->
|
|
||||||
pm.setActive(qPro)
|
|
||||||
pm.patch(
|
|
||||||
qPro.uuid, qPro.name,
|
|
||||||
url, 1800000L
|
|
||||||
)
|
|
||||||
pm.commit(qPro.uuid) { status ->
|
|
||||||
android.util.Log.d(
|
|
||||||
Conf.TAG,
|
|
||||||
"new updateStatus: " + Gson().toJson(status.args) + ", pro==>" + status.progress
|
|
||||||
)
|
|
||||||
}
|
|
||||||
newUuid = qPro.uuid.toString()
|
|
||||||
isSubbed = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun startLog() {
|
private fun startLog() {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
package com.yingmao.clash.app
|
package com.yingmao.clash.app
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.app.Application
|
import android.app.Application
|
||||||
import android.app.NotificationChannel
|
import android.app.NotificationChannel
|
||||||
|
|
@ -10,7 +9,6 @@ import android.content.Intent
|
||||||
import android.content.res.Configuration
|
import android.content.res.Configuration
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import androidx.annotation.RequiresApi
|
import androidx.annotation.RequiresApi
|
||||||
import androidx.core.content.ContextCompat.getString
|
|
||||||
import androidx.core.content.getSystemService
|
import androidx.core.content.getSystemService
|
||||||
import com.cncat.vpn.common.Global
|
import com.cncat.vpn.common.Global
|
||||||
import com.cncat.vpn.common.compat.currentProcessName
|
import com.cncat.vpn.common.compat.currentProcessName
|
||||||
|
|
@ -18,7 +16,6 @@ import com.cncat.vpn.common.log.Log
|
||||||
import com.github.gzuliyujiang.oaid.DeviceID
|
import com.github.gzuliyujiang.oaid.DeviceID
|
||||||
import com.github.gzuliyujiang.oaid.DeviceIdentifier
|
import com.github.gzuliyujiang.oaid.DeviceIdentifier
|
||||||
import com.github.gzuliyujiang.oaid.IGetter
|
import com.github.gzuliyujiang.oaid.IGetter
|
||||||
|
|
||||||
import com.jakewharton.processphoenix.ProcessPhoenix
|
import com.jakewharton.processphoenix.ProcessPhoenix
|
||||||
import com.orhanobut.logger.Logger
|
import com.orhanobut.logger.Logger
|
||||||
import com.stripe.android.PaymentConfiguration
|
import com.stripe.android.PaymentConfiguration
|
||||||
|
|
@ -29,14 +26,16 @@ import com.yingmao.clash.conf.BZYConstants
|
||||||
import com.yingmao.clash.entity.UserData
|
import com.yingmao.clash.entity.UserData
|
||||||
import com.yingmao.clash.util.CrashCatchHandler
|
import com.yingmao.clash.util.CrashCatchHandler
|
||||||
import com.yingmao.clash.util.clashDir
|
import com.yingmao.clash.util.clashDir
|
||||||
import com.yingmao.clash.view.RxToast
|
|
||||||
import com.yingmao.clash.view.dialog.DialogDoMainChoose
|
|
||||||
import com.yingmao.clash.view.dialog.DialogSureRestartChoose
|
import com.yingmao.clash.view.dialog.DialogSureRestartChoose
|
||||||
import kotlinx.coroutines.MainScope
|
import kotlinx.coroutines.MainScope
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.FileOutputStream
|
import java.io.FileOutputStream
|
||||||
|
import java.io.PrintWriter
|
||||||
|
import java.io.StringWriter
|
||||||
|
import java.text.SimpleDateFormat
|
||||||
|
import java.util.Date
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -154,10 +153,27 @@ class MainApplication : Application() {
|
||||||
// if (privacyPolicyAgreed) {
|
// if (privacyPolicyAgreed) {
|
||||||
|
|
||||||
// }
|
// }
|
||||||
|
// Thread.setDefaultUncaughtExceptionHandler { thread, throwable ->
|
||||||
|
// logException(throwable)
|
||||||
|
// // 可选择上报到服务器或写入本地文件
|
||||||
|
// }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
fun logException(e: Throwable) {
|
||||||
|
val log = StringWriter().also { e.printStackTrace(PrintWriter(it)) }.toString()
|
||||||
|
Log.d("MainApplication logException==>${log}")
|
||||||
|
|
||||||
|
// val directory: File? = applicationContext.getExternalFilesDir("CrashLog")
|
||||||
|
// if (directory != null) {
|
||||||
|
// if (!directory.isDirectory) {
|
||||||
|
// directory.delete()
|
||||||
|
// }
|
||||||
|
// if (!directory.exists()) {
|
||||||
|
// directory.mkdirs()
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// File(directory, "crash_${System.currentTimeMillis()}.log").writeText(log)
|
||||||
|
}
|
||||||
fun updateActivity(language: String, locale: Locale) {
|
fun updateActivity(language: String, locale: Locale) {
|
||||||
MMKV.defaultMMKV().encode(BZYConstants.languageInfo, language)
|
MMKV.defaultMMKV().encode(BZYConstants.languageInfo, language)
|
||||||
val resources = this.resources
|
val resources = this.resources
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,9 @@ import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.pm.ActivityInfo
|
import android.content.pm.ActivityInfo
|
||||||
import android.content.res.Configuration
|
import android.content.res.Configuration
|
||||||
|
import android.net.ConnectivityManager
|
||||||
|
import android.net.NetworkCapabilities
|
||||||
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.text.TextUtils
|
import android.text.TextUtils
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
|
|
@ -13,7 +16,9 @@ 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.*
|
||||||
|
import androidx.annotation.RequiresApi
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import androidx.collection.arraySetOf
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import com.orhanobut.logger.Logger
|
import com.orhanobut.logger.Logger
|
||||||
import com.tencent.mmkv.MMKV
|
import com.tencent.mmkv.MMKV
|
||||||
|
|
@ -55,6 +60,10 @@ open class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope(), Br
|
||||||
var baseLoading: RxDialogShapeLoading? = null
|
var baseLoading: RxDialogShapeLoading? = null
|
||||||
val serStore by lazy { ServiceStore(this) }
|
val serStore by lazy { ServiceStore(this) }
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
// var switchFinshSet: MutableSet<String>? = null
|
||||||
|
}
|
||||||
|
|
||||||
sealed class RequestTunnel {
|
sealed class RequestTunnel {
|
||||||
object ReloadAll : RequestTunnel()
|
object ReloadAll : RequestTunnel()
|
||||||
object ReLaunch : RequestTunnel()
|
object ReLaunch : RequestTunnel()
|
||||||
|
|
@ -265,6 +274,7 @@ open class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope(), Br
|
||||||
val mmkv = MMKV.defaultMMKV()
|
val mmkv = MMKV.defaultMMKV()
|
||||||
val routerHost = mmkv.decodeStringSet(BZYConstants.MMKV_KEY_ROUTER_HOST, HashSet())
|
val routerHost = mmkv.decodeStringSet(BZYConstants.MMKV_KEY_ROUTER_HOST, HashSet())
|
||||||
}
|
}
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
fun switchServer(): Boolean {
|
fun switchServer(): Boolean {
|
||||||
var isChange = false
|
var isChange = false
|
||||||
|
|
@ -303,4 +313,95 @@ open class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope(), Br
|
||||||
|
|
||||||
return isChange
|
return isChange
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@RequiresApi(Build.VERSION_CODES.M)
|
||||||
|
fun isNetworkAvailable(context: Context): Boolean {
|
||||||
|
val connectivityManager =
|
||||||
|
context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
|
||||||
|
|
||||||
|
val network = connectivityManager.activeNetwork ?: return false
|
||||||
|
val capabilities = connectivityManager.getNetworkCapabilities(network) ?: return false
|
||||||
|
|
||||||
|
return capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Synchronized
|
||||||
|
fun switchServer2(): Boolean {
|
||||||
|
var isChange = false
|
||||||
|
val mmkv = MMKV.defaultMMKV()
|
||||||
|
val originalUrl =
|
||||||
|
mmkv.decodeString(BZYConstants.MMKV_KEY_CURRENT_HOST, BuildConfig.service_url)
|
||||||
|
var newUrlString = originalUrl
|
||||||
|
val routerHost = mmkv.decodeStringSet(BZYConstants.MMKV_KEY_ROUTER_HOST, HashSet())
|
||||||
|
var switchFinshSet = mmkv.decodeStringSet(BZYConstants.MMKV_KEY_Switch_Finsh_Set, HashSet())
|
||||||
|
routerHost?.let {
|
||||||
|
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
|
// if (!isNetworkAvailable(this@BaseActivity)){
|
||||||
|
// return isChange
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
if (it.isEmpty()) {
|
||||||
|
Log.d(Conf.TAG, "routerHost isEmpty")
|
||||||
|
return isChange
|
||||||
|
}
|
||||||
|
com.cncat.vpn.common.log.Log.d("switchFinshSet.size==>${switchFinshSet?.size!!} , routerHost.size==>${routerHost.size}")
|
||||||
|
//次数已满
|
||||||
|
if (switchFinshSet?.size!! >= routerHost.size) {
|
||||||
|
return isChange
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.d(Conf.TAG, "routerHost not empty")
|
||||||
|
// val iterator = it.iterator()
|
||||||
|
// while (iterator.hasNext()) {
|
||||||
|
// val newUrl = iterator.next()
|
||||||
|
// Log.e(
|
||||||
|
// "Data",
|
||||||
|
// "遍历备用的url:$newUrl, contains==>${switchFinshSet?.contains(newUrl)}"
|
||||||
|
// )
|
||||||
|
// if (newUrl == originalUrl) {
|
||||||
|
// switchFinshSet?.add(newUrl)
|
||||||
|
// iterator.remove()
|
||||||
|
// continue
|
||||||
|
// }
|
||||||
|
// if (switchFinshSet?.contains(newUrl) == true) {
|
||||||
|
// iterator.remove()
|
||||||
|
// } else {
|
||||||
|
// Log.e("Retry", "切换到新url:$newUrl")
|
||||||
|
// isChange = true
|
||||||
|
// newUrlString = newUrl
|
||||||
|
// iterator.remove()
|
||||||
|
// if (originalUrl != null) {
|
||||||
|
// switchFinshSet?.add(originalUrl)
|
||||||
|
// mmkv.encode(BZYConstants.MMKV_KEY_OLD_CURRENT_HOST, originalUrl)
|
||||||
|
// }
|
||||||
|
// break
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
for (url in it) {
|
||||||
|
|
||||||
|
if (url == originalUrl) {
|
||||||
|
switchFinshSet?.add(url)
|
||||||
|
mmkv.encode(BZYConstants.MMKV_KEY_Switch_Finsh_Set, switchFinshSet)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if (switchFinshSet?.contains(url) == true) {
|
||||||
|
continue
|
||||||
|
} else {
|
||||||
|
isChange = true
|
||||||
|
android.util.Log.e("Retry", "切换到新url:$url")
|
||||||
|
newUrlString = url
|
||||||
|
switchFinshSet?.add(newUrlString)
|
||||||
|
mmkv.encode(BZYConstants.MMKV_KEY_Switch_Finsh_Set, switchFinshSet)
|
||||||
|
// mmkv.encode(BZYConstants.MMKV_KEY_OLD_CURRENT_HOST, newUrlString)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// mmkv.encode(BZYConstants.MMKV_KEY_ROUTER_HOST, routerHost)
|
||||||
|
mmkv.encode(BZYConstants.MMKV_KEY_CURRENT_HOST, newUrlString)
|
||||||
|
}
|
||||||
|
|
||||||
|
return isChange
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,20 +1,37 @@
|
||||||
package com.yingmao.clash.base
|
package com.yingmao.clash.base
|
||||||
|
|
||||||
|
import android.os.Build
|
||||||
import android.text.TextUtils
|
import android.text.TextUtils
|
||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.google.gson.Gson
|
|
||||||
import com.cncat.vpn.common.log.Log
|
import com.cncat.vpn.common.log.Log
|
||||||
|
import com.google.gson.Gson
|
||||||
|
import com.tencent.mmkv.MMKV
|
||||||
|
import com.yingmao.clash.BuildConfig
|
||||||
|
import com.yingmao.clash.app.MainApplication
|
||||||
|
import com.yingmao.clash.conf.BZYConstants
|
||||||
|
import com.yingmao.clash.net.http.HttpApi
|
||||||
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.HttpStatusDownLoad
|
import com.yingmao.clash.net.http.HttpStatusDownLoad
|
||||||
|
import com.yingmao.clash.net.http.NetService
|
||||||
import com.yingmao.clash.net.http.entity.BaseRsp
|
import com.yingmao.clash.net.http.entity.BaseRsp
|
||||||
import com.yingmao.clash.util.AESUtil
|
import com.yingmao.clash.util.AESUtil
|
||||||
import kotlinx.coroutines.CoroutineExceptionHandler
|
import kotlinx.coroutines.CoroutineExceptionHandler
|
||||||
import kotlinx.coroutines.async
|
import kotlinx.coroutines.async
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import okhttp3.MediaType.Companion.toMediaType
|
||||||
|
import okhttp3.RequestBody
|
||||||
|
import okhttp3.RequestBody.Companion.toRequestBody
|
||||||
|
import org.json.JSONArray
|
||||||
|
import org.json.JSONObject
|
||||||
|
import java.io.File
|
||||||
|
import java.io.PrintWriter
|
||||||
|
import java.io.StringWriter
|
||||||
|
import java.text.SimpleDateFormat
|
||||||
|
import java.util.Locale
|
||||||
|
|
||||||
open class BaseViewMode : ViewModel() {
|
open class BaseViewMode : ViewModel() {
|
||||||
|
|
||||||
|
|
@ -24,9 +41,13 @@ open class BaseViewMode : ViewModel() {
|
||||||
|
|
||||||
fun doAsync(reqType: HttpReqType, doInAsync: suspend () -> Any) {
|
fun doAsync(reqType: HttpReqType, doInAsync: suspend () -> Any) {
|
||||||
viewModelScope.launch(
|
viewModelScope.launch(
|
||||||
CoroutineExceptionHandler { _,
|
CoroutineExceptionHandler {
|
||||||
exception ->
|
_,
|
||||||
Log.e("BaseViewMode_doAsync:${exception.toString()}", exception)
|
exception,
|
||||||
|
->
|
||||||
|
Log.e("BaseViewMode_doAsync:${exception.localizedMessage}", exception)
|
||||||
|
|
||||||
|
logException(exception)
|
||||||
statusData.value =
|
statusData.value =
|
||||||
if (exception.message.isNullOrBlank()) HttpStatus.Failure(
|
if (exception.message.isNullOrBlank()) HttpStatus.Failure(
|
||||||
reqType,
|
reqType,
|
||||||
|
|
@ -52,10 +73,80 @@ open class BaseViewMode : ViewModel() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun doAsync2(reqType: HttpReqType, doInAsync: suspend () -> Any) {
|
fun logException(e: Throwable) {
|
||||||
|
var logSwitch = MMKV.defaultMMKV().decodeString(BZYConstants.MMKV_KEY_VPN_LogSwitch, "")
|
||||||
|
if ("on" == logSwitch) {
|
||||||
|
val log = StringWriter().also { e.printStackTrace(PrintWriter(it)) }.toString()
|
||||||
|
Log.d("logException==>${log}")
|
||||||
|
val username =
|
||||||
|
MMKV.defaultMMKV().decodeString(BZYConstants.MMKV_KEY_REMEMBER_USERNAME, "")!!
|
||||||
|
var json = JSONObject()
|
||||||
|
val androidVersion = Build.VERSION.RELEASE // 系统版本号,例如 "13"
|
||||||
|
val sdkInt = Build.VERSION.SDK_INT // SDK 级别,例如 33
|
||||||
|
val manufacturer = Build.MANUFACTURER // 厂商,例如 "Xiaomi"
|
||||||
|
val model = Build.MODEL // 机型,例如 "MI 11"
|
||||||
|
val brand = Build.BRAND // 品牌,例如 "Xiaomi"
|
||||||
|
val device = Build.DEVICE // 设备代号,例如 "venus"
|
||||||
|
val hardware = Build.HARDWARE // 硬件名称,例如 "qcom"
|
||||||
|
|
||||||
|
// val nowTime = SimpleDateFormat("yyyy年MM月dd日HH时mm分ss秒E", Locale.getDefault())
|
||||||
|
var ja_streams = JSONArray()
|
||||||
|
var jo_streams_item = JSONObject()
|
||||||
|
var jo_stream = JSONObject()
|
||||||
|
var ja_values = JSONArray()
|
||||||
|
jo_stream.put("phoneNumber", username)
|
||||||
|
jo_stream.put("appVersion", BuildConfig.VERSION_NAME)
|
||||||
|
jo_stream.put("androidVersion", androidVersion)
|
||||||
|
jo_stream.put("sdkInt", sdkInt)
|
||||||
|
jo_stream.put("manufacturer", manufacturer)
|
||||||
|
jo_stream.put("model", model)
|
||||||
|
jo_stream.put("brand", brand)
|
||||||
|
jo_stream.put("device", device)
|
||||||
|
jo_stream.put("hardware", hardware)
|
||||||
|
|
||||||
|
ja_values.put(0, System.currentTimeMillis().toString() + "000000")
|
||||||
|
//错误信息
|
||||||
|
ja_values.put(1, log)
|
||||||
|
jo_streams_item.put("stream", jo_stream)
|
||||||
|
var ja_values_item = JSONArray()
|
||||||
|
ja_values_item.put(0, ja_values)
|
||||||
|
jo_streams_item.put("values", ja_values_item)
|
||||||
|
ja_streams.put(0, jo_streams_item)
|
||||||
|
json.put("streams", ja_streams)
|
||||||
|
|
||||||
|
Log.d("json==>${json}")
|
||||||
|
val httpApi = NetService.instances.createHttps(HttpApi::class.java)
|
||||||
|
val requestBody: RequestBody = json.toString().toRequestBody("application/json; charset=utf-8".toMediaType())
|
||||||
|
doAsync2(HttpReqType.APPSHAREINFO) {
|
||||||
|
httpApi.postErrLog(requestBody)
|
||||||
|
}
|
||||||
|
// val directory: File? = MainApplication.getApp()?.applicationContext?.getExternalFilesDir("CrashLog")
|
||||||
|
// if (directory != null) {
|
||||||
|
// if (!directory.isDirectory) {
|
||||||
|
// directory.delete()
|
||||||
|
// }
|
||||||
|
// if (!directory.exists()) {
|
||||||
|
// directory.mkdirs()
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// File(directory, "crash_${System.currentTimeMillis()}.log").writeText(json.toString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fun postErrLog(phone: String) {
|
||||||
|
|
||||||
|
val phToken = MMKV.defaultMMKV().decodeString(BZYConstants.MMKV_KEY_PH_TOKEN,"")!!
|
||||||
|
val params = mutableMapOf(
|
||||||
|
"phoneNumber" to phone,
|
||||||
|
"phToken" to phToken
|
||||||
|
)
|
||||||
|
|
||||||
|
}
|
||||||
|
fun doAsync2(reqType: HttpReqType, doInAsync: suspend () -> Any?) {
|
||||||
viewModelScope.launch(
|
viewModelScope.launch(
|
||||||
CoroutineExceptionHandler { _,
|
CoroutineExceptionHandler {
|
||||||
exception ->
|
_,
|
||||||
|
exception,
|
||||||
|
->
|
||||||
Log.e("BaseViewMode_doAsync:${exception.toString()}", exception)
|
Log.e("BaseViewMode_doAsync:${exception.toString()}", exception)
|
||||||
statusData.value =
|
statusData.value =
|
||||||
if (exception.message.isNullOrBlank()) HttpStatus.Failure(
|
if (exception.message.isNullOrBlank()) HttpStatus.Failure(
|
||||||
|
|
@ -114,11 +205,13 @@ open class BaseViewMode : ViewModel() {
|
||||||
fun doAsyncDelay(
|
fun doAsyncDelay(
|
||||||
reqType: HttpReqType,
|
reqType: HttpReqType,
|
||||||
delayTimeMillis: Long,
|
delayTimeMillis: Long,
|
||||||
doInAsync: suspend () -> BaseRsp
|
doInAsync: suspend () -> BaseRsp,
|
||||||
) {
|
) {
|
||||||
viewModelScope.launch(
|
viewModelScope.launch(
|
||||||
CoroutineExceptionHandler { _,
|
CoroutineExceptionHandler {
|
||||||
exception ->
|
_,
|
||||||
|
exception,
|
||||||
|
->
|
||||||
Log.e("BaseViewMode_doAsyncDelay:${exception.toString()}", exception)
|
Log.e("BaseViewMode_doAsyncDelay:${exception.toString()}", exception)
|
||||||
statusData.value =
|
statusData.value =
|
||||||
if (exception.message.isNullOrBlank()) HttpStatus.Failure(
|
if (exception.message.isNullOrBlank()) HttpStatus.Failure(
|
||||||
|
|
@ -149,8 +242,10 @@ open class BaseViewMode : ViewModel() {
|
||||||
|
|
||||||
fun doAsyncStrResult(reqType: HttpReqType, doInAsync: suspend () -> String) {
|
fun doAsyncStrResult(reqType: HttpReqType, doInAsync: suspend () -> String) {
|
||||||
viewModelScope.launch(
|
viewModelScope.launch(
|
||||||
CoroutineExceptionHandler { _,
|
CoroutineExceptionHandler {
|
||||||
exception ->
|
_,
|
||||||
|
exception,
|
||||||
|
->
|
||||||
Log.e("BaseViewMode_doAsyncStrResult:${exception.toString()}", exception)
|
Log.e("BaseViewMode_doAsyncStrResult:${exception.toString()}", exception)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -170,11 +265,13 @@ open class BaseViewMode : ViewModel() {
|
||||||
fun doAsyncEncodeStr(
|
fun doAsyncEncodeStr(
|
||||||
reqType: HttpReqType,
|
reqType: HttpReqType,
|
||||||
classOfT: Class<out BaseRsp>,
|
classOfT: Class<out BaseRsp>,
|
||||||
doInAsync: suspend () -> String
|
doInAsync: suspend () -> String,
|
||||||
) {
|
) {
|
||||||
viewModelScope.launch(
|
viewModelScope.launch(
|
||||||
CoroutineExceptionHandler() { _,
|
CoroutineExceptionHandler() {
|
||||||
exception ->
|
_,
|
||||||
|
exception,
|
||||||
|
->
|
||||||
Log.e("BaseViewMode_doAsyncEncodeStr:${exception.toString()}", exception)
|
Log.e("BaseViewMode_doAsyncEncodeStr:${exception.toString()}", exception)
|
||||||
statusData.value =
|
statusData.value =
|
||||||
if (exception.message.isNullOrBlank()) HttpStatus.Failure(
|
if (exception.message.isNullOrBlank()) HttpStatus.Failure(
|
||||||
|
|
@ -191,8 +288,6 @@ open class BaseViewMode : ViewModel() {
|
||||||
val result = async { doInAsync() }
|
val result = async { doInAsync() }
|
||||||
val rspStr = result.await()
|
val rspStr = result.await()
|
||||||
Log.i("doAsyncEncodeStr 加密请求结果:$rspStr")
|
Log.i("doAsyncEncodeStr 加密请求结果:$rspStr")
|
||||||
|
|
||||||
|
|
||||||
if (!TextUtils.isEmpty(rspStr)) {
|
if (!TextUtils.isEmpty(rspStr)) {
|
||||||
var decodeRspStr = AESUtil.decrypt(rspStr)
|
var decodeRspStr = AESUtil.decrypt(rspStr)
|
||||||
Log.d("doAsyncEncodeStr 请求结果:$decodeRspStr")
|
Log.d("doAsyncEncodeStr 请求结果:$decodeRspStr")
|
||||||
|
|
@ -213,11 +308,13 @@ open class BaseViewMode : ViewModel() {
|
||||||
|
|
||||||
suspend fun doAsyncEncodeStrBg(
|
suspend fun doAsyncEncodeStrBg(
|
||||||
classOfT: Class<out BaseRsp>,
|
classOfT: Class<out BaseRsp>,
|
||||||
doInAsync: suspend () -> String
|
doInAsync: suspend () -> String,
|
||||||
): BaseRsp? {
|
): BaseRsp? {
|
||||||
return viewModelScope.async(
|
return viewModelScope.async(
|
||||||
CoroutineExceptionHandler() { _,
|
CoroutineExceptionHandler() {
|
||||||
exception ->
|
_,
|
||||||
|
exception,
|
||||||
|
->
|
||||||
Log.e("BaseViewMode_doAsyncEncodeStrBg:${exception.toString()}", exception)
|
Log.e("BaseViewMode_doAsyncEncodeStrBg:${exception.toString()}", exception)
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -33,11 +33,11 @@ open class PublicViewMode : BaseViewMode() {
|
||||||
try { //TODO bug 会引起崩溃
|
try { //TODO bug 会引起崩溃
|
||||||
val host = when {
|
val host = when {
|
||||||
BuildConfig.is_ym -> {
|
BuildConfig.is_ym -> {
|
||||||
rt.getHostGithub()
|
rt.getHost()
|
||||||
}
|
}
|
||||||
|
|
||||||
BuildConfig.is_tz -> {
|
BuildConfig.is_tz -> {
|
||||||
rt.getTzHostGithub()
|
rt.getTzHostTZ()
|
||||||
}
|
}
|
||||||
|
|
||||||
BuildConfig.is_yunti -> {
|
BuildConfig.is_yunti -> {
|
||||||
|
|
@ -45,7 +45,7 @@ open class PublicViewMode : BaseViewMode() {
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
rt.getBzyHostGithub()
|
rt.getBzyHostDef()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Log.e("data", "2:$host")
|
// Log.e("data", "2:$host")
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@ class BZYConstants {
|
||||||
const val MMKV_KEY_OLD_CURRENT_HOST = "old_current_host"
|
const val MMKV_KEY_OLD_CURRENT_HOST = "old_current_host"
|
||||||
//备用地址
|
//备用地址
|
||||||
const val MMKV_KEY_ROUTER_HOST ="router_host"
|
const val MMKV_KEY_ROUTER_HOST ="router_host"
|
||||||
|
const val MMKV_KEY_Switch_Finsh_Set ="MMKV_KEY_Switch_Finsh_Set"
|
||||||
const val MMKV_KEY_FIRST_HOST ="first_host"
|
const val MMKV_KEY_FIRST_HOST ="first_host"
|
||||||
const val MMKV_KEY_Airport_Base64 ="airport_base64"
|
const val MMKV_KEY_Airport_Base64 ="airport_base64"
|
||||||
//注册地址
|
//注册地址
|
||||||
|
|
@ -47,6 +48,7 @@ class BZYConstants {
|
||||||
const val MMKV_KEY_VPN_EXPIRED = "expired"
|
const val MMKV_KEY_VPN_EXPIRED = "expired"
|
||||||
|
|
||||||
const val MMKV_KEY_VPN_UserCommand = "userCommand"
|
const val MMKV_KEY_VPN_UserCommand = "userCommand"
|
||||||
|
const val MMKV_KEY_VPN_LogSwitch = "logSwitch"
|
||||||
|
|
||||||
//vpn过期时间
|
//vpn过期时间
|
||||||
const val MMKV_KEY_VPN_VALID_PERIOD = "vpn_valid_period"
|
const val MMKV_KEY_VPN_VALID_PERIOD = "vpn_valid_period"
|
||||||
|
|
|
||||||
|
|
@ -79,6 +79,9 @@ data class UserData(
|
||||||
@field:SerializedName("userCommand")
|
@field:SerializedName("userCommand")
|
||||||
val userCommand: String? = null,
|
val userCommand: String? = null,
|
||||||
|
|
||||||
|
@field:SerializedName("logSwitch")
|
||||||
|
val logSwitch: String? = null,
|
||||||
|
|
||||||
@field:SerializedName("intervalTime")
|
@field:SerializedName("intervalTime")
|
||||||
val intervalTime: Int? = null,
|
val intervalTime: Int? = null,
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package com.yingmao.clash.fragment
|
package com.yingmao.clash.fragment
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.util.Log
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
|
@ -9,9 +10,14 @@ import android.widget.ImageView
|
||||||
import android.widget.RelativeLayout
|
import android.widget.RelativeLayout
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
|
import com.tencent.mmkv.MMKV
|
||||||
|
import com.yingmao.clash.BuildConfig
|
||||||
import com.yingmao.clash.R
|
import com.yingmao.clash.R
|
||||||
import com.yingmao.clash.base.BaseViewMode
|
import com.yingmao.clash.base.BaseViewMode
|
||||||
|
import com.yingmao.clash.conf.BZYConstants
|
||||||
|
import com.yingmao.clash.conf.Conf
|
||||||
import com.yingmao.clash.net.http.HttpStatus
|
import com.yingmao.clash.net.http.HttpStatus
|
||||||
|
import java.util.HashSet
|
||||||
|
|
||||||
|
|
||||||
abstract class BaseFragment :Fragment() {
|
abstract class BaseFragment :Fragment() {
|
||||||
|
|
@ -58,4 +64,44 @@ abstract class BaseFragment :Fragment() {
|
||||||
open fun httpSuccess(httpStatus: HttpStatus.Success){}
|
open fun httpSuccess(httpStatus: HttpStatus.Success){}
|
||||||
|
|
||||||
open fun httpFailure(httpStatus: HttpStatus.Failure){}
|
open fun httpFailure(httpStatus: HttpStatus.Failure){}
|
||||||
|
|
||||||
|
@Synchronized
|
||||||
|
fun switchServer(): Boolean {
|
||||||
|
var isChange = false
|
||||||
|
val mmkv = MMKV.defaultMMKV()
|
||||||
|
val originalUrl =
|
||||||
|
mmkv.decodeString(BZYConstants.MMKV_KEY_CURRENT_HOST, BuildConfig.service_url)
|
||||||
|
var newUrlString = originalUrl
|
||||||
|
val routerHost = mmkv.decodeStringSet(BZYConstants.MMKV_KEY_ROUTER_HOST, HashSet())
|
||||||
|
routerHost?.let {
|
||||||
|
// it.forEach { url ->
|
||||||
|
// com.cncat.vpn.common.log.Log.d("url==>$url")
|
||||||
|
// }
|
||||||
|
if (it.isEmpty()) {
|
||||||
|
Log.d(Conf.TAG, "routerHost isEmpty")
|
||||||
|
return isChange
|
||||||
|
}
|
||||||
|
Log.d(Conf.TAG, "routerHost not empty")
|
||||||
|
val iterator = it.iterator()
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
val newUrl = iterator.next()
|
||||||
|
Log.e("Data", "遍历备用的url:$newUrl")
|
||||||
|
if (newUrl == originalUrl) {
|
||||||
|
iterator.remove()
|
||||||
|
} else {
|
||||||
|
Log.e("Retry", "切换到新url:$newUrl")
|
||||||
|
mmkv.encode(BZYConstants.MMKV_KEY_OLD_CURRENT_HOST, originalUrl)
|
||||||
|
isChange = true
|
||||||
|
newUrlString = newUrl
|
||||||
|
iterator.remove()
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// mmkv.encode(BZYConstants.MMKV_KEY_ROUTER_HOST, routerHost)
|
||||||
|
mmkv.encode(BZYConstants.MMKV_KEY_CURRENT_HOST, newUrlString)
|
||||||
|
}
|
||||||
|
|
||||||
|
return isChange
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -33,6 +33,7 @@ import com.yingmao.clash.act.NewMainActivity
|
||||||
import com.yingmao.clash.act.NewMainActivity.Companion.isSubed
|
import com.yingmao.clash.act.NewMainActivity.Companion.isSubed
|
||||||
import com.yingmao.clash.act.NewMainActivity.Companion.newUuid
|
import com.yingmao.clash.act.NewMainActivity.Companion.newUuid
|
||||||
import com.yingmao.clash.act.ProxyModeActivity
|
import com.yingmao.clash.act.ProxyModeActivity
|
||||||
|
import com.yingmao.clash.act.UIMainActivity
|
||||||
import com.yingmao.clash.conf.BZYConstants
|
import com.yingmao.clash.conf.BZYConstants
|
||||||
import com.yingmao.clash.conf.Conf
|
import com.yingmao.clash.conf.Conf
|
||||||
import com.yingmao.clash.entity.ClashNodebBean
|
import com.yingmao.clash.entity.ClashNodebBean
|
||||||
|
|
@ -294,7 +295,7 @@ class NewAccFragment : BaseFragment(), CoroutineScope by CoroutineScope(Dispatch
|
||||||
// return
|
// return
|
||||||
// }
|
// }
|
||||||
launch {
|
launch {
|
||||||
NewMainActivity.profileBinder?.let { pm ->
|
UIMainActivity.profileBinder?.let { pm ->
|
||||||
val active = pm.queryActive()
|
val active = pm.queryActive()
|
||||||
if (active == null) {
|
if (active == null) {
|
||||||
com.cncat.vpn.common.log.Log.d("startClash: 未选择")
|
com.cncat.vpn.common.log.Log.d("startClash: 未选择")
|
||||||
|
|
@ -707,7 +708,7 @@ class NewAccFragment : BaseFragment(), CoroutineScope by CoroutineScope(Dispatch
|
||||||
} else {
|
} else {
|
||||||
if (clashRunning) {
|
if (clashRunning) {
|
||||||
delay(1000)
|
delay(1000)
|
||||||
NewMainActivity.clashBinder?.let { cm ->
|
UIMainActivity.clashBinder?.let { cm ->
|
||||||
val names = cm.queryProxyGroupNames(false)
|
val names = cm.queryProxyGroupNames(false)
|
||||||
Log.i("checkGlo names==>${names}")
|
Log.i("checkGlo names==>${names}")
|
||||||
if (names.isNotEmpty()) {
|
if (names.isNotEmpty()) {
|
||||||
|
|
@ -771,7 +772,7 @@ class NewAccFragment : BaseFragment(), CoroutineScope by CoroutineScope(Dispatch
|
||||||
var nodeName = proListItem[0].name
|
var nodeName = proListItem[0].name
|
||||||
if (!TextUtils.isEmpty(nodeName)) {
|
if (!TextUtils.isEmpty(nodeName)) {
|
||||||
launch(Dispatchers.IO) {
|
launch(Dispatchers.IO) {
|
||||||
NewMainActivity.clashBinder?.let { cm ->
|
UIMainActivity.clashBinder?.let { cm ->
|
||||||
|
|
||||||
val o = cm.queryOverride(Clash.OverrideSlot.Session)
|
val o = cm.queryOverride(Clash.OverrideSlot.Session)
|
||||||
o.mode = TunnelState.Mode.Global
|
o.mode = TunnelState.Mode.Global
|
||||||
|
|
@ -812,7 +813,7 @@ class NewAccFragment : BaseFragment(), CoroutineScope by CoroutineScope(Dispatch
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
NewMainActivity.clashBinder?.let { cm ->
|
UIMainActivity.clashBinder?.let { cm ->
|
||||||
val o = cm.queryOverride(Clash.OverrideSlot.Session)
|
val o = cm.queryOverride(Clash.OverrideSlot.Session)
|
||||||
o.mode = TunnelState.Mode.Global
|
o.mode = TunnelState.Mode.Global
|
||||||
cm.patchOverride(Clash.OverrideSlot.Session, o)
|
cm.patchOverride(Clash.OverrideSlot.Session, o)
|
||||||
|
|
|
||||||
|
|
@ -628,104 +628,7 @@ class RechargeFragment : BaseFragment() {
|
||||||
noVerticalPadding = true,
|
noVerticalPadding = true,
|
||||||
horizontalPadding = false
|
horizontalPadding = false
|
||||||
)
|
)
|
||||||
// for (index in data.payType!!) {
|
|
||||||
// if (index.payModel == 10) {
|
|
||||||
// findViewById<LinearLayout>(R.id.llAggregatePayment).visibility =
|
|
||||||
// View.VISIBLE
|
|
||||||
// val JUhePay = findViewById<TextView>(R.id.JUhePay)
|
|
||||||
// JUhePay.visibility = View.VISIBLE
|
|
||||||
// JUhePay.text = index.payChannel
|
|
||||||
// if (index.payType == 1) {
|
|
||||||
// val ivAlipay = findViewById<AppCompatImageView>(R.id.ivAlipay)
|
|
||||||
// ivAlipay.visibility = View.VISIBLE
|
|
||||||
// ivAlipay.setOnClickListener {
|
|
||||||
// val payModel = index.payModel
|
|
||||||
// val payType = index.payType
|
|
||||||
// val payParam = index.payParam
|
|
||||||
// if (payModel != null && payType != null && payParam != null) {
|
|
||||||
// viewModel.orderPayment(data, payModel, payType, payParam)
|
|
||||||
// } else {
|
|
||||||
// viewModel.orderPayment(data, 10, 1, "ip@影猫充值")
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// } else if (index.payType == 2) {
|
|
||||||
// val ivWechatPay = findViewById<AppCompatImageView>(R.id.ivWechatPay)
|
|
||||||
// ivWechatPay.visibility = View.VISIBLE
|
|
||||||
// ivWechatPay.setOnClickListener {
|
|
||||||
// val payModel = index.payModel
|
|
||||||
// val payType = index.payType
|
|
||||||
// val payParam = index.payParam
|
|
||||||
// if (payModel != null && payType != null && payParam != null) {
|
|
||||||
// viewModel.orderPayment(data, payModel, payType, payParam)
|
|
||||||
// } else {
|
|
||||||
// viewModel.orderPayment(data, 10, 2, "ip@影猫充值")
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// } else if (index.payModel == 11) {
|
|
||||||
// findViewById<LinearLayout>(R.id.llQuickPayment).visibility =
|
|
||||||
// View.VISIBLE
|
|
||||||
// val KJPay = findViewById<TextView>(R.id.KJPay)
|
|
||||||
// KJPay.visibility = View.VISIBLE
|
|
||||||
// KJPay.text = index.payChannel
|
|
||||||
// if (index.payType == 1) {
|
|
||||||
// val ivQuickPayment =
|
|
||||||
// findViewById<AppCompatImageView>(R.id.ivQuickPayment)
|
|
||||||
// ivQuickPayment.visibility = View.VISIBLE
|
|
||||||
// ivQuickPayment.setOnClickListener {
|
|
||||||
// val payModel = index.payModel
|
|
||||||
// val payType = index.payType
|
|
||||||
// val payParam = index.payParam
|
|
||||||
// if (payModel != null && payType != null && payParam != null) {
|
|
||||||
// viewModel.orderPayment(data, payModel, payType, payParam)
|
|
||||||
// } else {
|
|
||||||
// viewModel.orderPayment(data, 11, 1, "ip@影猫充值")
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// } else if (index.payType == 2) {
|
|
||||||
// val ivQPWechatPay =
|
|
||||||
// findViewById<AppCompatImageView>(R.id.ivQPWechatPay)
|
|
||||||
// ivQPWechatPay.visibility = View.VISIBLE
|
|
||||||
// ivQPWechatPay.setOnClickListener {
|
|
||||||
// val payModel = index.payModel
|
|
||||||
// val payType = index.payType
|
|
||||||
// val payParam = index.payParam
|
|
||||||
// if (payModel != null && payType != null && payParam != null) {
|
|
||||||
// viewModel.orderPayment(data, payModel, payType, payParam)
|
|
||||||
// } else {
|
|
||||||
// viewModel.orderPayment(data, 11, 1, "ip@影喵充值")
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// } else if (index.payModel == 7) {
|
|
||||||
// findViewById<LinearLayout>(R.id.llStripe).visibility = View.VISIBLE
|
|
||||||
// findViewById<LinearLayout>(R.id.llStripePay).visibility = View.VISIBLE
|
|
||||||
// var payinfo = findViewById<TextView>(R.id.tvStripePay)
|
|
||||||
// payinfo.visibility = View.VISIBLE
|
|
||||||
//
|
|
||||||
// payinfo.text = index.payChannel
|
|
||||||
// findViewById<AppCompatImageView>(R.id.ivStripeAlipay).visibility =
|
|
||||||
// View.VISIBLE
|
|
||||||
// findViewById<AppCompatImageView>(R.id.ivStripeAlipay).setOnClickListener {
|
|
||||||
// if (selectedGradeID != 0) {
|
|
||||||
// if (!PayUtils.isAlipayInstalled(requireActivity())) {
|
|
||||||
// RxToast.error(resources.getString(R.string.AlipayNotInstalled))
|
|
||||||
// return@setOnClickListener
|
|
||||||
// }
|
|
||||||
// dismiss()
|
|
||||||
// showLoading(
|
|
||||||
// resources.getString(R.string.PaymentIn),
|
|
||||||
// requireActivity()
|
|
||||||
// )
|
|
||||||
// Log.i("PayGradeID:", "PayGradeID:${selectedGradeID}")
|
|
||||||
// viewModel.getPayClientSecret(selectedGradeID)
|
|
||||||
// } else {
|
|
||||||
// RxToast.info(getString(R.string.NoPaymentReceipt))
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
getCustomView().findViewById<AppCompatImageView>(R.id.ivBack)
|
getCustomView().findViewById<AppCompatImageView>(R.id.ivBack)
|
||||||
.setOnClickListener {
|
.setOnClickListener {
|
||||||
dismiss()
|
dismiss()
|
||||||
|
|
@ -735,76 +638,7 @@ class RechargeFragment : BaseFragment() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// private fun goWebViewStartPayClient(rsp: BaseRsp, isPayWeb: Boolean) {
|
|
||||||
// (rsp as BiLaiNormalRsp).let {
|
|
||||||
// if (it.code != "1000") {
|
|
||||||
// RxToast.error(if (it.message.isNullOrBlank()) "获取支付信息失败(${it.code})" else "${it.code}:${it.message}")
|
|
||||||
// } else {
|
|
||||||
// if (isPayWeb) {
|
|
||||||
// activity?.let {
|
|
||||||
// if (rsp.data != null) {
|
|
||||||
//// goWebPay(it, rsp.data!!)
|
|
||||||
//// goWebPay(it, newUrl)
|
|
||||||
// } else {
|
|
||||||
// RxToast.error("未能获取到支付信息,请联系客服")
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// val gson = Gson().fromJson(it.data!!, BiLaiRsp::class.java)
|
|
||||||
// Logger.d("跳转支付宝支付页面:" + gson.payurl)
|
|
||||||
// var realPayUrl = ""
|
|
||||||
// var isNeedScan = false
|
|
||||||
// if (gson.payurl != null) {
|
|
||||||
// realPayUrl = gson.payurl!!
|
|
||||||
// isNeedScan = false
|
|
||||||
// } else if (gson.qrcode != null) {
|
|
||||||
// realPayUrl = gson.qrcode!!
|
|
||||||
// isNeedScan = true
|
|
||||||
// } else {
|
|
||||||
// realPayUrl = gson.urlscheme!!
|
|
||||||
// isNeedScan = true
|
|
||||||
// }
|
|
||||||
// // Log.e("data==", "html:" + realPayUrl);
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// activity?.let {
|
|
||||||
// if (!isNeedScan) {
|
|
||||||
//// goWebPay(it, newUrl)
|
|
||||||
// } else {
|
|
||||||
// //二维码支付
|
|
||||||
// qrPayDialog = MaterialDialog(it).show {
|
|
||||||
// this.cancelable(false)
|
|
||||||
// cornerRadius(res = R.dimen.dp_10)
|
|
||||||
// customView(R.layout.qrpay_dialog_layout, scrollable = false, noVerticalPadding = true, horizontalPadding = false)
|
|
||||||
// getCustomView().findViewById<TextView>(R.id.tv_qr_pay_note).setText(R.string.qr_pay_note_wx)
|
|
||||||
//
|
|
||||||
// val ivQr = getCustomView().findViewById<ImageView>(R.id.iv_qr)
|
|
||||||
//
|
|
||||||
// val writer = MultiFormatWriter()
|
|
||||||
// val matrix = writer.encode(realPayUrl, BarcodeFormat.QR_CODE, 300, 300)
|
|
||||||
// val encoder = BarcodeEncoder()
|
|
||||||
// val bitmap = encoder.createBitmap(matrix)
|
|
||||||
// ivQr.setImageBitmap(bitmap)
|
|
||||||
//
|
|
||||||
// getCustomView().findViewById<TextView>(R.id.tv_pay_finish).setOnClickListener {
|
|
||||||
// showLoadingDialog("正在查询支付结果...")
|
|
||||||
// viewModel.codePayStatus(outTradeNo)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// getCustomView().findViewById<TextView>(R.id.tv_pay_cancle).setOnClickListener {
|
|
||||||
// if (bitmap != null && !bitmap.isRecycled) {
|
|
||||||
// bitmap.recycle()
|
|
||||||
// dismiss()
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }/
|
|
||||||
|
|
||||||
fun goWebPay(it: Activity, realPayUrl: String) {
|
fun goWebPay(it: Activity, realPayUrl: String) {
|
||||||
val intent = Intent(context, BZYWebViewNormal::class.java)
|
val intent = Intent(context, BZYWebViewNormal::class.java)
|
||||||
|
|
|
||||||
|
|
@ -62,6 +62,7 @@ import com.yingmao.clash.act.UIMainActivity.Companion.newUuid
|
||||||
import com.yingmao.clash.act.UIMainActivity.Companion.profileBinder
|
import com.yingmao.clash.act.UIMainActivity.Companion.profileBinder
|
||||||
import com.yingmao.clash.act.UIMainActivity.Companion.subUrl
|
import com.yingmao.clash.act.UIMainActivity.Companion.subUrl
|
||||||
import com.yingmao.clash.app.MainApplication
|
import com.yingmao.clash.app.MainApplication
|
||||||
|
import com.yingmao.clash.base.BaseActivity
|
||||||
import com.yingmao.clash.conf.BZYConstants
|
import com.yingmao.clash.conf.BZYConstants
|
||||||
import com.yingmao.clash.conf.Conf
|
import com.yingmao.clash.conf.Conf
|
||||||
import com.yingmao.clash.entity.CheckLoginRsp
|
import com.yingmao.clash.entity.CheckLoginRsp
|
||||||
|
|
@ -636,6 +637,10 @@ class SettingFragment : BaseFragment(), CoroutineScope by CoroutineScope(Dispatc
|
||||||
MMKV.defaultMMKV().removeValueForKey(BZYConstants.MMKV_KEY_VPN_UserCommand)
|
MMKV.defaultMMKV().removeValueForKey(BZYConstants.MMKV_KEY_VPN_UserCommand)
|
||||||
MMKV.defaultMMKV().removeValueForKey(BZYConstants.NODE_All_ITEM_NAME_KEY)
|
MMKV.defaultMMKV().removeValueForKey(BZYConstants.NODE_All_ITEM_NAME_KEY)
|
||||||
MMKV.defaultMMKV().removeValueForKey(BZYConstants.PROFILE_SUB_URL)
|
MMKV.defaultMMKV().removeValueForKey(BZYConstants.PROFILE_SUB_URL)
|
||||||
|
MMKV.defaultMMKV().removeValueForKey(BZYConstants.MMKV_KEY_Switch_Finsh_Set)
|
||||||
|
|
||||||
|
//清除源切换记录
|
||||||
|
|
||||||
Log.d("cleanUserInfo clashRunning==>${clashRunning}")
|
Log.d("cleanUserInfo clashRunning==>${clashRunning}")
|
||||||
if (clashRunning) {
|
if (clashRunning) {
|
||||||
fragments.filterIsInstance<HomeFragment>().forEach { it.stopClash() }
|
fragments.filterIsInstance<HomeFragment>().forEach { it.stopClash() }
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,7 @@ import com.yingmao.clash.net.http.entity.UploadParamData
|
||||||
import com.yingmao.clash.net.http.entity.VipSignRsp
|
import com.yingmao.clash.net.http.entity.VipSignRsp
|
||||||
import okhttp3.RequestBody
|
import okhttp3.RequestBody
|
||||||
import retrofit2.Call
|
import retrofit2.Call
|
||||||
|
import retrofit2.Response
|
||||||
import retrofit2.http.Body
|
import retrofit2.http.Body
|
||||||
import retrofit2.http.GET
|
import retrofit2.http.GET
|
||||||
import retrofit2.http.Header
|
import retrofit2.http.Header
|
||||||
|
|
@ -75,6 +76,7 @@ interface HttpApi {
|
||||||
@POST("/netbarcloud/vpn/octopusRegister.do")
|
@POST("/netbarcloud/vpn/octopusRegister.do")
|
||||||
suspend fun register(@QueryMap params: Map<String, String>): RegisterRsp
|
suspend fun register(@QueryMap params: Map<String, String>): RegisterRsp
|
||||||
|
|
||||||
|
|
||||||
//加密注册
|
//加密注册
|
||||||
@Headers(
|
@Headers(
|
||||||
"User-Agent: Octopus_Android"
|
"User-Agent: Octopus_Android"
|
||||||
|
|
@ -94,7 +96,6 @@ interface HttpApi {
|
||||||
): RegisterRsp
|
): RegisterRsp
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//显示赠送时长 :
|
//显示赠送时长 :
|
||||||
@Headers(
|
@Headers(
|
||||||
"User-Agent: Octopus_Android"
|
"User-Agent: Octopus_Android"
|
||||||
|
|
@ -218,8 +219,10 @@ interface HttpApi {
|
||||||
|
|
||||||
@GET("/taiziregister.txt")
|
@GET("/taiziregister.txt")
|
||||||
suspend fun getTzRegister(): String
|
suspend fun getTzRegister(): String
|
||||||
|
|
||||||
@GET("/taiziregister_182269.txt")
|
@GET("/taiziregister_182269.txt")
|
||||||
suspend fun getTz182269Register(): String
|
suspend fun getTz182269Register(): String
|
||||||
|
|
||||||
@GET("/bzyregister.txt")
|
@GET("/bzyregister.txt")
|
||||||
suspend fun getBzyRegister(): String
|
suspend fun getBzyRegister(): String
|
||||||
|
|
||||||
|
|
@ -631,4 +634,16 @@ interface HttpApi {
|
||||||
BZYConstants.MMKV_KEY_TOKEN
|
BZYConstants.MMKV_KEY_TOKEN
|
||||||
).toString(),
|
).toString(),
|
||||||
): AppStopStatus
|
): AppStopStatus
|
||||||
|
|
||||||
|
@Headers(
|
||||||
|
"User-Agent: Octopus_Android",
|
||||||
|
"Authorization: Basic Z20yMXdvcGc6eDVjZXlzbTY="
|
||||||
|
)
|
||||||
|
@POST("/netbarcloud/api/v1/push")
|
||||||
|
suspend fun postErrLog(
|
||||||
|
@Body requestBody: RequestBody,
|
||||||
|
@Header("token") string: String = MMKV.defaultMMKV().decodeString(
|
||||||
|
BZYConstants.MMKV_KEY_TOKEN
|
||||||
|
).toString(),
|
||||||
|
): Response<NormalRsp>
|
||||||
}
|
}
|
||||||
|
|
@ -16,6 +16,7 @@ import okhttp3.Callback
|
||||||
import okhttp3.Cookie
|
import okhttp3.Cookie
|
||||||
import okhttp3.CookieJar
|
import okhttp3.CookieJar
|
||||||
import okhttp3.HttpUrl
|
import okhttp3.HttpUrl
|
||||||
|
import okhttp3.Interceptor
|
||||||
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
import okhttp3.Request
|
import okhttp3.Request
|
||||||
|
|
@ -72,6 +73,37 @@ class NetService private constructor() : INetService {
|
||||||
var httpClient: OkHttpClient? = null;
|
var httpClient: OkHttpClient? = null;
|
||||||
var downHttpClient: OkHttpClient? = null;
|
var downHttpClient: OkHttpClient? = null;
|
||||||
|
|
||||||
|
class ExceptionLoggingInterceptor : Interceptor {
|
||||||
|
override fun intercept(chain: Interceptor.Chain): Response {
|
||||||
|
val request = chain.request()
|
||||||
|
return try {
|
||||||
|
val response = chain.proceed(request)
|
||||||
|
// 如果需要也可记录非 2xx 的响应
|
||||||
|
if (!response.isSuccessful) {
|
||||||
|
logHttpError(request, response.code, null)
|
||||||
|
}
|
||||||
|
response
|
||||||
|
} catch (e: Exception) {
|
||||||
|
logHttpError(request, null, e)
|
||||||
|
throw e // 抛出异常让上层处理
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun logHttpError(request: Request, code: Int?, e: Exception?) {
|
||||||
|
val log = buildString {
|
||||||
|
append("URL: ${request.url}\n")
|
||||||
|
append("Method: ${request.method}\n")
|
||||||
|
append("Headers: ${request.headers}\n")
|
||||||
|
append("Body: ${request.body}\n")
|
||||||
|
code?.let { append("Response Code: $code\n") }
|
||||||
|
e?.let { append("Exception: ${e.message}\n${e.stackTraceToString()}") }
|
||||||
|
}
|
||||||
|
|
||||||
|
// 这里可以上传到服务端,或者保存到本地文件
|
||||||
|
println("❌ 网络请求异常:\n$log")
|
||||||
|
// FirebaseCrashlytics.getInstance().recordException(e) // 如果用了 Firebase
|
||||||
|
}
|
||||||
|
}
|
||||||
override fun httpsClient(connTO:Long,readTO:Long,writeTO:Long): OkHttpClient {
|
override fun httpsClient(connTO:Long,readTO:Long,writeTO:Long): OkHttpClient {
|
||||||
|
|
||||||
var loggingInterceptor = HttpLoggingInterceptor(
|
var loggingInterceptor = HttpLoggingInterceptor(
|
||||||
|
|
@ -79,8 +111,10 @@ class NetService private constructor() : INetService {
|
||||||
override fun log(message: String) {
|
override fun log(message: String) {
|
||||||
Log.d("loggingInterceptor==>$message")
|
Log.d("loggingInterceptor==>$message")
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
loggingInterceptor.level = HttpLoggingInterceptor.Level.BODY
|
loggingInterceptor.level = HttpLoggingInterceptor.Level.BODY
|
||||||
var builder = OkHttpClient.Builder()
|
var builder = OkHttpClient.Builder()
|
||||||
.retryOnConnectionFailure(true)
|
.retryOnConnectionFailure(true)
|
||||||
|
|
@ -95,6 +129,7 @@ class NetService private constructor() : INetService {
|
||||||
.hostnameVerifier(getHostnameVerifier()!!)
|
.hostnameVerifier(getHostnameVerifier()!!)
|
||||||
if (BuildConfig.DEBUG) {
|
if (BuildConfig.DEBUG) {
|
||||||
builder.addInterceptor(loggingInterceptor)
|
builder.addInterceptor(loggingInterceptor)
|
||||||
|
// builder.addInterceptor(ExceptionLoggingInterceptor())
|
||||||
}
|
}
|
||||||
// builder.addInterceptor(loggingInterceptor)
|
// builder.addInterceptor(loggingInterceptor)
|
||||||
return builder.build()
|
return builder.build()
|
||||||
|
|
@ -161,6 +196,7 @@ class NetService private constructor() : INetService {
|
||||||
.addConverterFactory(ScalarsConverterFactory.create())//json解析器Gson
|
.addConverterFactory(ScalarsConverterFactory.create())//json解析器Gson
|
||||||
.baseUrl(baseUrl) //设置BaseURL需以'/'结尾
|
.baseUrl(baseUrl) //设置BaseURL需以'/'结尾
|
||||||
.build() //创建Retrofit对象
|
.build() //创建Retrofit对象
|
||||||
|
|
||||||
return retrofit.create(HttpApi::class.java)
|
return retrofit.create(HttpApi::class.java)
|
||||||
}
|
}
|
||||||
fun createFreeBaseUrl2(): HttpApi {
|
fun createFreeBaseUrl2(): HttpApi {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,112 @@
|
||||||
|
package com.yingmao.clash.view.dialog
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.app.Activity
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.DialogInterface
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.widget.TextView
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import com.tencent.mmkv.MMKV
|
||||||
|
import com.yingmao.clash.BuildConfig
|
||||||
|
import com.yingmao.clash.R
|
||||||
|
import com.yingmao.clash.conf.BZYConstants
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author tamsiree
|
||||||
|
* @date 2016/7/19
|
||||||
|
* 确认 取消 Dialog
|
||||||
|
*/
|
||||||
|
open class DialogAutoDoMainChoose : RxDialog {
|
||||||
|
lateinit var titleView: TextView
|
||||||
|
private set
|
||||||
|
lateinit var but_try: TextView
|
||||||
|
private set
|
||||||
|
lateinit var but_cancel: TextView
|
||||||
|
private set
|
||||||
|
lateinit var domainRecyclerView: RecyclerView
|
||||||
|
private set
|
||||||
|
lateinit var onTryListener: OnTryButtonListener
|
||||||
|
|
||||||
|
lateinit var onDomainListItemListener: OnListItemListener
|
||||||
|
|
||||||
|
var domainFininshSet = mutableSetOf<String>();
|
||||||
|
|
||||||
|
constructor(context: Context?, themeResId: Int) : super(context!!, themeResId) {
|
||||||
|
initView()
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
context: Context?,
|
||||||
|
cancelable: Boolean,
|
||||||
|
cancelListener: DialogInterface.OnCancelListener?,
|
||||||
|
) : super(context!!, cancelable, cancelListener) {
|
||||||
|
initView()
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(context: Context?) : super(context!!) {
|
||||||
|
initView()
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(context: Activity?) : super(context!!) {
|
||||||
|
initView()
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(context: Context?, alpha: Float, gravity: Int) : super(context, alpha, gravity) {
|
||||||
|
initView()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun initView() {
|
||||||
|
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() }
|
||||||
|
|
||||||
|
setContentView(dialogView)
|
||||||
|
setCancelable(false)
|
||||||
|
window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
|
||||||
|
setNewData()
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("NotifyDataSetChanged")
|
||||||
|
private fun setNewData() {
|
||||||
|
var mmkv = MMKV.defaultMMKV()
|
||||||
|
val originalUrl =
|
||||||
|
mmkv.decodeString(BZYConstants.MMKV_KEY_CURRENT_HOST, BuildConfig.service_url)
|
||||||
|
var newUrlString = originalUrl
|
||||||
|
|
||||||
|
val routerHost = mmkv.decodeStringSet(BZYConstants.MMKV_KEY_ROUTER_HOST, HashSet())
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setOnTryButtonListener(listener: OnTryButtonListener) {
|
||||||
|
this.onTryListener = listener
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun changeSubUrl(originalUrl: String, newUrl: String): String {
|
||||||
|
return originalUrl.replace(Regex("https://[^/]+/"), "$newUrl/")
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
interface OnTryButtonListener {
|
||||||
|
fun tryButton()
|
||||||
|
fun cancel()
|
||||||
|
}
|
||||||
|
|
||||||
|
interface OnListItemListener {
|
||||||
|
fun listItemClick()
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -106,7 +106,6 @@ open class DialogDoMainChoose : RxDialog {
|
||||||
}
|
}
|
||||||
domainListAdapter.notifyDataSetChanged()
|
domainListAdapter.notifyDataSetChanged()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setOnTryButtonListener(listener: OnTryButtonListener) {
|
fun setOnTryButtonListener(listener: OnTryButtonListener) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue