修改备用源逻辑,改用手动选择方式

修改api请求的超时时间
This commit is contained in:
cyh 2025-03-13 18:56:04 +08:00
parent 6f2b108068
commit 7b3351ebfd
17 changed files with 521 additions and 89 deletions

View File

@ -39,6 +39,7 @@ import com.cncat.vpn.service.remote.IRemoteService
import com.yingmao.clash.util.Utils
import com.yingmao.clash.view.RxToast
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.delay
@ -119,7 +120,7 @@ class ChangeNodeActivity : BaseActivity(), View.OnClickListener {
swipeLayout = findViewById(R.id.swipeLayout)
initRefreshLayout()
nodeListRv = findViewById(R.id.rv_node_list)
var userTrafficTv:TextView = findViewById(R.id.node_user_traffic)
var userTrafficTv: TextView = findViewById(R.id.node_user_traffic)
findViewById<ImageView>(R.id.iv_back).setOnClickListener {
onBackPressed()
@ -272,14 +273,17 @@ class ChangeNodeActivity : BaseActivity(), View.OnClickListener {
override fun onStart() {
super.onStart()
// getNodesStatus()
// changeNodeVM.getAirNodes()
doProfile()
}
fun doProfile() {
if (TextUtils.isEmpty(cacheNodeStr)) {
showLoading("正在获取...", this@ChangeNodeActivity)
startTimer()
}
updateProfile(false)
}
val reloadLock = Semaphore(10)
@ -462,7 +466,7 @@ class ChangeNodeActivity : BaseActivity(), View.OnClickListener {
createProfile()
} else {
Log.d("stopTimer...")
RxToast.error("获取节点失败...")
RxToast.error("获取节点失败...请尝试切换其他地址")
delay(1000)
this@ChangeNodeActivity.finish()
}
@ -470,39 +474,25 @@ class ChangeNodeActivity : BaseActivity(), View.OnClickListener {
delay(1000)
}
}
}
// timer = Timer()
// timerTask = object : TimerTask() {
// override fun run() {
// if (GetNodeTimeOutNum >= 0) {
// GetNodeTimeOutNum--
// Log.d("GetNodeTimeOutNum==>$GetNodeTimeOutNum")
// } else {
// GetNodeTimeOutNum = 5
// //超时后删除配置文件重新创建
// launch {
// hideLoading()
// }
// Log.d("isCreate==>$isCreate")
// if (!isCreate) {
// isCreate = true
//
// launch {
// showLoading("获取节点超时,正在重新配置...", this@ChangeNodeActivity)
// }
// createProfile()
// } else {
// Log.d("stopTimer...")
// stopTimer()
// launch {
// RxToast.error("获取节点失败...")
// }
// }
//
// }
// }
// }
// timer!!.schedule(timerTask, 0, 1000)
private fun showDomainList() {
try {
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()
}
})
dialogDoMainChoose.show()
} catch (e: Exception) {
e.printStackTrace()
}
}
private fun stopTimer() {

View File

@ -42,6 +42,8 @@ import com.cncat.vpn.service.remote.wrap
import com.yingmao.clash.util.AESUtil
import com.yingmao.clash.util.Utils
import com.yingmao.clash.view.RxToast
import com.yingmao.clash.view.dialog.DialogBandChoose
import com.yingmao.clash.view.dialog.DialogDoMainChoose
import com.yingmao.clash.view.dialog.RxDialogSureCancel
import com.yingmao.clash.vm.SplashAtyVM
import kotlinx.coroutines.MainScope
@ -80,9 +82,13 @@ class SplashActivity : BaseActivity() {
ll_action = findViewById(R.id.ll_action)
serStore.isYM = BuildConfig.is_ym
if (!BuildConfig.is_ym) {
serStore.isBZY = true
if (BuildConfig.is_tz) {
serStore.isTZ = true
} else {
serStore.isBZY = true
}
}
serStore.isTZ = BuildConfig.is_tz
// mPermissions.add(Manifest.permission.READ_PHONE_STATE)
// mPermissions.add(Manifest.permission.INTERNET)
@ -142,7 +148,6 @@ class SplashActivity : BaseActivity() {
registerKey = cb.getRegisterKey(si)
registerIV2 = cb.getRegisterKiv(si)
// com.cncat.vpn.common.log.Log.d("si==>${si}, ss1==>${ss1}, ss2==>${ss2}")
AESUtil.KEY2 = ss1
AESUtil.IV2 = ss2
// 太子
@ -151,29 +156,62 @@ class SplashActivity : BaseActivity() {
// 八爪鱼 2
// com.cncat.vpn.common.log.Log.d("bzy2 encrypt:"+ AESUtil.byteArrayToHexStr(AESUtil.encrypt("")))
// 影猫
// com.cncat.vpn.common.log.Log.d("ym encrypt:"+ AESUtil.byteArrayToHexStr(AESUtil.encrypt("")))
com.cncat.vpn.common.log.Log.d(
"ym encrypt:" +
AESUtil.byteArrayToHexStr(
AESUtil.encrypt(
"https://yingmaohot.org+https://yingmao888.net+" +
"https://ymsohot.com+https://ma.wztgyh.com+https://ymapi.yingmaox.cc"
)
)
)
val routerSet =
MMKV.defaultMMKV().decodeStringSet(BZYConstants.MMKV_KEY_ROUTER_HOST)
if (routerSet != null && routerSet.size > 0) {
isNeedRegister()
} else {
rlPb.visibility = View.VISIBLE
if (BuildConfig.is_back_cn == true) { //没有备用域名所以无需调用getHost
isNeedRegister()
} else {
splashAtyVM.getHost(object : AsyncCallback {
splashAtyVM.getHostByGithub(object : AsyncCallback {
override suspend fun suc() {
Log.e("data", "getHost suc")
Log.e("data", "getHostByGithub suc")
MainScope().launch {
isNeedRegister()
}
}
override fun err() {
Log.e("data", "getHost err")
//失败也注册
MainScope().launch {
isNeedRegister()
}
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()
}
}
})
}
})
}
})
}
@ -586,24 +624,41 @@ class SplashActivity : BaseActivity() {
override fun httpFailure(httpStatus: HttpStatus.Failure) {
when (httpStatus.reqType) {
HttpReqType.REGISTER -> {
rlPb.visibility=View.GONE
com.cncat.vpn.common.log.Log.d("httpFailure HttpReqType.REGISTER")
if (super.switchServer()) {//切换服务器并直接重试
// doRegister()
doRegisterByEncryption()
} else {
MaterialDialog(this@SplashActivity).show {
message(text = initErrMsg)
positiveButton(R.string.retry) {
// doRegister()
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()
}
negativeButton(R.string.cancel) {
it.dismiss()
finish()
}
}
})
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()
// }
// negativeButton(R.string.cancel) {
// it.dismiss()
// finish()
// }
// }
// }
}
HttpReqType.LOGIN -> {

View File

@ -285,11 +285,11 @@ open class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope(), Br
val iterator = it.iterator()
while (iterator.hasNext()) {
val newUrl = iterator.next()
//Log.e("Data", "遍历备用的url:$newUrl")
Log.e("Data", "遍历备用的url:$newUrl")
if (newUrl == originalUrl) {
iterator.remove()
} else {
//Log.e("Retry", "切换到新url:$newUrl")
Log.e("Retry", "切换到新url:$newUrl")
mmkv.encode(BZYConstants.MMKV_KEY_OLD_CURRENT_HOST, originalUrl)
isChange = true
newUrlString = newUrl
@ -297,7 +297,7 @@ open class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope(), Br
break
}
}
mmkv.encode(BZYConstants.MMKV_KEY_ROUTER_HOST, routerHost)
// mmkv.encode(BZYConstants.MMKV_KEY_ROUTER_HOST, routerHost)
mmkv.encode(BZYConstants.MMKV_KEY_CURRENT_HOST, newUrlString)
}

View File

@ -0,0 +1,11 @@
package com.yingmao.clash.entity
import android.os.Parcelable
import kotlinx.parcelize.Parcelize
import java.io.Serializable
@Parcelize
data class DomainItemBean(
val address: String,
) : Parcelable,Serializable

View File

@ -163,6 +163,10 @@ interface HttpApi {
//影猫
@GET("/host.txt")
suspend fun getHost(): String
@GET("/host_ym.txt")
suspend fun getHostAWS(): String
@GET("/ym-source/ym/main/host_ym.txt")
suspend fun getHostGithub(): String
//八爪鱼
@GET("/hostdef.txt")
suspend fun getHostDef(): String

View File

@ -4,6 +4,6 @@ import okhttp3.OkHttpClient
interface INetService{
fun httpClient():OkHttpClient
fun httpsClient():OkHttpClient
fun httpClient(connTO:Long,readTO:Long,writeTO:Long):OkHttpClient
fun httpsClient(connTO:Long,readTO:Long,writeTO:Long):OkHttpClient
}

View File

@ -42,9 +42,13 @@ import javax.net.ssl.*
class NetService private constructor() : INetService {
companion object {
private const val ConnectTimeOut = 15L
private const val ReadTimeOut = 60L
private const val WriteTimeOut = 60L
private const val ConnectTimeOut = 10L
private const val ReadTimeOut = 15L
private const val WriteTimeOut = 15L
private const val Down_ConnectTimeOut = 15L
private const val Down_ReadTimeOut = 60L
private const val Down_WriteTimeOut = 60L
// private var defaultUrl_domestic = getCurrentUrl()
val instances: NetService by lazy(LazyThreadSafetyMode.SYNCHRONIZED) { NetService() }
@ -66,7 +70,7 @@ class NetService private constructor() : INetService {
var httpClient: OkHttpClient? = null;
override fun httpsClient(): OkHttpClient {
override fun httpsClient(connTO:Long,readTO:Long,writeTO:Long): OkHttpClient {
var loggingInterceptor = HttpLoggingInterceptor(
object : HttpLoggingInterceptor.Logger {
@ -80,10 +84,10 @@ class NetService private constructor() : INetService {
.retryOnConnectionFailure(true)
// .addInterceptor(RetryAndChangeIpInterceptor())
// .proxy(java.net.Proxy.NO_PROXY)
.connectTimeout(ConnectTimeOut, TimeUnit.SECONDS)
.writeTimeout(WriteTimeOut, TimeUnit.SECONDS)
.readTimeout(ReadTimeOut, TimeUnit.SECONDS)
.callTimeout(240, TimeUnit.SECONDS)
.connectTimeout(connTO, TimeUnit.SECONDS)
.writeTimeout(readTO, TimeUnit.SECONDS)
.readTimeout(writeTO, TimeUnit.SECONDS)
.callTimeout(120, TimeUnit.SECONDS)
// .sslSocketFactory(getSSLSocketFactory(), CustomTrustManager())//信任所有证书
.sslSocketFactory(getSSLSocketFactory(), trustAllCerts[0] as X509TrustManager)
.hostnameVerifier(getHostnameVerifier()!!)
@ -95,15 +99,15 @@ class NetService private constructor() : INetService {
}
override fun httpClient(): OkHttpClient {
override fun httpClient(connTO:Long,readTO:Long,writeTO:Long): OkHttpClient {
return OkHttpClient.Builder()
// .retryOnConnectionFailure(true)
// .addInterceptor(RetryAndChangeIpInterceptor())
.connectTimeout(ConnectTimeOut, TimeUnit.SECONDS)
.writeTimeout(WriteTimeOut, TimeUnit.SECONDS)
.readTimeout(ReadTimeOut, TimeUnit.SECONDS)
// .sslSocketFactory(getSSLSocketFactory(), trustAllCerts[0] as X509TrustManager)//信任所有证书
.connectTimeout(connTO, TimeUnit.SECONDS)
.writeTimeout(readTO, TimeUnit.SECONDS)
.readTimeout(writeTO, TimeUnit.SECONDS)
.sslSocketFactory(getSSLSocketFactory(), trustAllCerts[0] as X509TrustManager)//信任所有证书
.build()
}
@ -111,7 +115,7 @@ class NetService private constructor() : INetService {
if (httpClient == null) {
synchronized(this) {
if (httpClient == null) {
httpClient = httpClient()
httpClient = httpsClient(ConnectTimeOut, ReadTimeOut, WriteTimeOut)
}
}
}
@ -122,7 +126,7 @@ class NetService private constructor() : INetService {
//创建Retrofit构建器
val builder = Retrofit.Builder()
if (httpClient == null) {
httpClient = httpsClient();
httpClient = getClient()
}
builder.client(httpClient)
builder.baseUrl(getCurrentUrl())
@ -138,7 +142,7 @@ class NetService private constructor() : INetService {
//创建Retrofit构建器
val builder = Retrofit.Builder()
if (httpClient == null) {
httpClient = httpsClient();
httpClient = getClient()
}
builder.client(httpClient)
//请求的服务器地址
@ -157,6 +161,12 @@ class NetService private constructor() : INetService {
.build() //创建Retrofit对象
return retrofit.create(HttpApi::class.java)
}
fun createFreeBaseUrl2(): HttpApi {
val retrofit = Retrofit.Builder()
.addConverterFactory(ScalarsConverterFactory.create())//json解析器Gson
.build() //创建Retrofit对象
return retrofit.create(HttpApi::class.java)
}
/**
* post请求异步方式提交数据是在子线程中执行的需要切换到主线程才能更新UI
@ -321,7 +331,7 @@ class NetService private constructor() : INetService {
fun downloadFile(url: String, downLoadListener: DownLoadListener) {
if (httpClient == null) {
httpClient = httpsClient();
httpClient = httpsClient(Down_ConnectTimeOut, Down_ReadTimeOut, Down_WriteTimeOut);
}
val request = Request.Builder().get().url(url).build()

View File

@ -0,0 +1,45 @@
package com.yingmao.clash.view.adapter
import android.annotation.SuppressLint
import android.text.TextUtils
import android.view.View
import android.widget.ImageView
import android.widget.RelativeLayout
import android.widget.TextView
import com.bumptech.glide.util.Util
import com.chad.library.adapter.base.BaseQuickAdapter
import com.chad.library.adapter.base.module.LoadMoreModule
import com.chad.library.adapter.base.viewholder.BaseViewHolder
import com.google.android.material.radiobutton.MaterialRadioButton
import com.yingmao.clash.R
import com.yingmao.clash.entity.ClashNodebBean
import com.cncat.vpn.service.model.Profile
import com.yingmao.clash.entity.DomainItemBean
import com.yingmao.clash.util.Utils
class DomainListAdapter(layoutResId: Int) :
BaseQuickAdapter<DomainItemBean, BaseViewHolder>(layoutResId), LoadMoreModule {
var selectedPosition: Int = -1
var addressIndex=1
override fun convert(holder: BaseViewHolder, item: DomainItemBean) {
val domainSelectedTv = holder.getView<TextView>(R.id.domain_selected_tv)
val nodeCheckMrb = holder.getView<MaterialRadioButton>(R.id.domain_item_checked)
if (holder.layoutPosition == selectedPosition) {
nodeCheckMrb.isChecked = true
domainSelectedTv.visibility = View.VISIBLE
} else {
nodeCheckMrb.isChecked = false
domainSelectedTv.visibility = View.INVISIBLE
}
val addressName = holder.getView<TextView>(R.id.domain_list_item_tv_address_name)
// addressName.text = item.address
addressName.text = "地址${addressIndex}"
addressIndex++
}
}

View File

@ -0,0 +1,138 @@
package com.yingmao.clash.view.dialog
import android.annotation.SuppressLint
import android.app.Activity
import android.content.Context
import android.content.DialogInterface
import android.content.Intent
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
import com.chad.library.adapter.base.BaseQuickAdapter
import com.cncat.vpn.common.log.Log
import com.tencent.mmkv.MMKV
import com.yingmao.clash.R
import com.yingmao.clash.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
* @date 2016/7/19
* 确认 取消 Dialog
*/
open class DialogDoMainChoose : RxDialog {
lateinit var titleView: TextView
private set
lateinit var but_try: Button
private set
lateinit var domainRecyclerView: RecyclerView
private set
lateinit var onTryListener: OnTryButtonListener
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)
domainRecyclerView = dialogView.findViewById(R.id.domian_list)
but_try.setOnClickListener {
onTryListener.tryButton()
}
initAdapter()
setContentView(dialogView)
setCancelable(false)
window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
var mmkv = MMKV.defaultMMKV()
val routerHost = mmkv.decodeStringSet(BZYConstants.MMKV_KEY_ROUTER_HOST, emptySet())
var domainList = routerHost?.mapTo(mutableListOf()) { DomainItemBean(it) }
setNewData(domainList)
}
@SuppressLint("NotifyDataSetChanged")
private fun setNewData(nodes: MutableList<DomainItemBean>?) {
if (nodes != null) {
domainListAdapter.setNewInstance(nodes)
var mmkv = MMKV.defaultMMKV()
var currentHost = mmkv.decodeString(BZYConstants.MMKV_KEY_CURRENT_HOST, "")
Log.d("currentHost==>${currentHost}")
for ((index, node) in nodes.withIndex()) {
if (node.address == currentHost) {
domainListAdapter.selectedPosition = index
}
}
domainListAdapter.notifyDataSetChanged()
}
}
fun setOnTryButtonListener(listener: OnTryButtonListener) {
this.onTryListener = listener
}
var domainListAdapter: DomainListAdapter = DomainListAdapter(R.layout.domain_list_item_layout)
private fun initAdapter() {
domainRecyclerView.layoutManager = LinearLayoutManager(context)
domainRecyclerView.adapter = domainListAdapter
domainListAdapter.selectedPosition
domainListAdapter.setOnItemClickListener { baseQuickAdapter: BaseQuickAdapter<*, *>, view: View, position: Int ->
(baseQuickAdapter.getItem(position) as DomainItemBean).let { bean ->
MMKV.defaultMMKV().encode(BZYConstants.MMKV_KEY_CURRENT_HOST, bean.address)
domainListAdapter.notifyItemChanged(domainListAdapter.selectedPosition)
domainListAdapter.selectedPosition =
if (domainListAdapter.selectedPosition == position) -1 else position
domainListAdapter.notifyItemChanged(position)
this.onTryListener.tryButton()
}
}
}
interface OnTryButtonListener {
fun tryButton()
}
}

View File

@ -38,7 +38,11 @@ open class DialogPayTypeChoose : RxDialog {
initView()
}
constructor(context: Context?, cancelable: Boolean, cancelListener: DialogInterface.OnCancelListener?) : super(context!!, cancelable, cancelListener) {
constructor(
context: Context?,
cancelable: Boolean,
cancelListener: DialogInterface.OnCancelListener?,
) : super(context!!, cancelable, cancelListener) {
initView()
}
@ -94,12 +98,12 @@ open class DialogPayTypeChoose : RxDialog {
}
fun setOnPayTypeCheckedListener(onPayTypeCheckedListener : OnPayTypeCheckedListener){
fun setOnPayTypeCheckedListener(onPayTypeCheckedListener: OnPayTypeCheckedListener) {
this.onPayTypeCheckedListener = onPayTypeCheckedListener
}
interface OnPayTypeCheckedListener{
fun onPayTypeChecked(payType :String)
interface OnPayTypeCheckedListener {
fun onPayTypeChecked(payType: String)
}
fun setTitle(titleStr: String) {

View File

@ -69,10 +69,9 @@ class SplashAtyVM : PublicViewMode() {
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 {
@ -94,6 +93,68 @@ class SplashAtyVM : PublicViewMode() {
}
}
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()
}
}
}
fun register(params: Map<String, String>) {
Log.e("data", "register ....")
val httpApi = NetService.instances.createHttps(HttpApi::class.java)

View File

@ -0,0 +1,63 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
>
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="@drawable/shape_round_white"
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
android:id="@+id/tv_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:layout_marginBottom="10dp"
android:gravity="center"
android:text="@string/domain_warn"
android:textColor="@color/white"
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:orientation="vertical">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/domian_list"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</androidx.recyclerview.widget.RecyclerView>
</LinearLayout>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,43 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
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:background="@drawable/node_list_item_bg_selector"
android:clickable="true"
android:focusable="true">
<TextView
android:id="@+id/domain_list_item_tv_address_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginStart="15dp"
android:text="地址1"
android:textColor="@color/white"
android:textSize="16sp" />
<TextView
android:id="@+id/domain_selected_tv"
android:text="@string/selected"
android:visibility="invisible"
android:layout_width="wrap_content"
android:textColor="@color/white"
android:layout_centerVertical="true"
android:paddingRight="10dp"
android:layout_toLeftOf="@+id/domain_item_checked"
android:layout_height="wrap_content">
</TextView>
<com.google.android.material.radiobutton.MaterialRadioButton
android:id="@+id/domain_item_checked"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:buttonTint="@color/white"
android:clickable="false" />
</RelativeLayout>

View File

@ -279,4 +279,6 @@
<string name="AlipayNotInstalled">Alipay is not installed</string>
<string name="quickPaymentMain">Quick payment (recommended)</string>
<string name="aggregatePaymentBase">Aggregate payment (backup)</string>
<string name="domain_warn">The current request is abnormal. Please try selecting an available address</string>
<string name="selected">Selected</string>
</resources>

View File

@ -271,4 +271,6 @@
<string name="AlipayNotInstalled">支付寶未安裝</string>
<string name="quickPaymentMain">快捷支付(推薦)</string>
<string name="aggregatePaymentBase">聚合支付(備用)</string>
<string name="domain_warn">當前請求异常,請嘗試選擇可用地址</string>
<string name="selected">當前選擇</string>
</resources>

View File

@ -270,4 +270,6 @@
<string name="AlipayNotInstalled">支付寶未安裝</string>
<string name="quickPaymentMain">快捷支付(推薦)</string>
<string name="aggregatePaymentBase">聚合支付(備用)</string>
<string name="domain_warn">當前請求异常,請嘗試選擇可用地址</string>
<string name="selected">當前選擇</string>
</resources>

View File

@ -286,4 +286,6 @@
<string name="AlipayNotInstalled">支付宝未安装</string>
<string name="quickPaymentMain">快捷支付(推荐)</string>
<string name="aggregatePaymentBase">聚合支付(备用)</string>
<string name="domain_warn">当前请求异常,请尝试选择可用地址</string>
<string name="selected">当前选择</string>
</resources>