1.添加节点测速 2.添加太子定制节点页面 3.修复部分界面选择备用源异常bug
This commit is contained in:
parent
65f17fba52
commit
6402e1793e
|
|
@ -165,6 +165,10 @@
|
|||
android:name=".act.ChangeNodeActivity"
|
||||
android:process=":background"
|
||||
android:screenOrientation="portrait" />
|
||||
<activity
|
||||
android:name=".act.ChangeNodeTzActivity"
|
||||
android:process=":background"
|
||||
android:screenOrientation="portrait" />
|
||||
<activity
|
||||
android:name=".act.ForGetPwdActivity"
|
||||
android:process=":background"
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ import com.cncat.vpn.service.model.Profile
|
|||
import com.cncat.vpn.service.remote.IProfileManager
|
||||
import com.cncat.vpn.service.remote.IRemoteService
|
||||
import com.yingmao.clash.app.MainApplication
|
||||
import com.yingmao.clash.fragment.home.HomeFragment
|
||||
import com.yingmao.clash.util.Utils
|
||||
import com.yingmao.clash.view.RxToast
|
||||
import com.yingmao.clash.view.adapter.NodeListAdapter
|
||||
|
|
@ -66,6 +67,7 @@ class ChangeNodeActivity : BaseActivity(), View.OnClickListener {
|
|||
private lateinit var swipeLayout: SwipeRefreshLayout
|
||||
private lateinit var changeNodeVM: ChangeNodeVM
|
||||
private lateinit var nodeListRv: RecyclerView
|
||||
private lateinit var nodeItemTest: TextView
|
||||
private var names: List<String>? = null
|
||||
private lateinit var aiBack: AppCompatImageView
|
||||
private var broadcastReceiver: BroadcastReceiver? = null
|
||||
|
|
@ -123,6 +125,8 @@ class ChangeNodeActivity : BaseActivity(), View.OnClickListener {
|
|||
@SuppressLint("SetTextI18n")
|
||||
private fun initViews() {
|
||||
aiBack = findViewById(R.id.aiBack)
|
||||
nodeItemTest = findViewById(R.id.node_item_test)
|
||||
nodeItemTest.setOnClickListener(this@ChangeNodeActivity)
|
||||
aiBack.setOnClickListener {
|
||||
onBackPressed()
|
||||
}
|
||||
|
|
@ -329,13 +333,19 @@ class ChangeNodeActivity : BaseActivity(), View.OnClickListener {
|
|||
}
|
||||
|
||||
private fun changeSubUrl(originalUrl: String, newUrl: String) {
|
||||
nowSubUrl = originalUrl.replace(Regex("https://[^/]+/"), "$newUrl/")
|
||||
MMKV.defaultMMKV().encode(BZYConstants.PROFILE_SUB_URL, nowSubUrl)
|
||||
if (!originalUrl.isNullOrEmpty() && !newUrl.isNullOrEmpty()) {
|
||||
nowSubUrl = originalUrl.replace(Regex("https://[^/]+/"), "$newUrl/")
|
||||
MMKV.defaultMMKV().encode(BZYConstants.PROFILE_SUB_URL, nowSubUrl)
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateTestBut(str: String) {
|
||||
nodeItemTest.text=str
|
||||
}
|
||||
|
||||
val reloadLock = Semaphore(10)
|
||||
private fun setPing() {
|
||||
if (!NewAccFragment.clashRunning) {
|
||||
if (!HomeFragment.clashRunning) {
|
||||
RxToast.info("请先开启加速后,再进行测试.");
|
||||
return
|
||||
}
|
||||
|
|
@ -344,20 +354,23 @@ class ChangeNodeActivity : BaseActivity(), View.OnClickListener {
|
|||
return
|
||||
}
|
||||
testRuning = true
|
||||
updateMoreBar("测速中")
|
||||
// updateMoreBar("测速中")
|
||||
updateTestBut("测速中")
|
||||
launch(Dispatchers.IO) {
|
||||
var group = reloadLock.withPermit {
|
||||
UIMainActivity.clashBinder?.let { cb ->
|
||||
var names = cb.queryProxyGroupNames(false)
|
||||
if (names.isNotEmpty()) {
|
||||
cb.healthCheck(names[0])
|
||||
delay(1000)
|
||||
cb.queryProxyGroup(names[0], uiStore.proxySort);
|
||||
} else {
|
||||
null
|
||||
}
|
||||
delay(1000)
|
||||
cb.queryProxyGroup(names[0], uiStore.proxySort);
|
||||
}
|
||||
}
|
||||
testRuning = false
|
||||
runOnUiThread { updateMoreBar("线路测速") }
|
||||
runOnUiThread { updateTestBut("线路测速") }
|
||||
var newDatas = mutableListOf<ClashNodebBean>();
|
||||
group?.proxies?.forEach { proxy ->
|
||||
Log.d("node==>${proxy}")
|
||||
|
|
@ -590,7 +603,7 @@ class ChangeNodeActivity : BaseActivity(), View.OnClickListener {
|
|||
|
||||
override fun onClick(p0: View?) {
|
||||
when (p0?.id) {
|
||||
R.id.tv_more -> {
|
||||
R.id.node_item_test -> {
|
||||
setPing()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,606 @@
|
|||
package com.yingmao.clash.act
|
||||
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.IntentFilter
|
||||
import android.graphics.Color
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.text.TextUtils
|
||||
import android.view.View
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import androidx.appcompat.widget.AppCompatImageView
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout.OnRefreshListener
|
||||
|
||||
import com.chad.library.adapter.base.BaseQuickAdapter
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.JsonParser
|
||||
import com.tencent.mmkv.MMKV
|
||||
import com.yingmao.clash.R
|
||||
import com.yingmao.clash.base.BaseActivity
|
||||
import com.cncat.vpn.common.constants.Intents
|
||||
import com.cncat.vpn.common.log.Log
|
||||
import com.yingmao.clash.conf.BZYConstants
|
||||
import com.yingmao.clash.conf.Conf
|
||||
import com.yingmao.clash.entity.ClashNodebBean
|
||||
import com.yingmao.clash.fragment.NewAccFragment
|
||||
import com.yingmao.clash.fragment.NewAccFragment.Companion.CHECK_NODE_RESULT_CODE
|
||||
import com.yingmao.clash.remote.Resource
|
||||
import com.cncat.vpn.service.model.Profile
|
||||
import com.cncat.vpn.service.remote.IProfileManager
|
||||
import com.cncat.vpn.service.remote.IRemoteService
|
||||
import com.yingmao.clash.app.MainApplication
|
||||
import com.yingmao.clash.util.Utils
|
||||
import com.yingmao.clash.view.RxToast
|
||||
import com.yingmao.clash.view.adapter.NodeListAdapter
|
||||
import com.yingmao.clash.view.adapter.NodeTzListAdapter
|
||||
import com.yingmao.clash.view.dialog.DialogDoMainChoose
|
||||
import com.yingmao.clash.view.dialog.DialogSureRestartChoose
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.MainScope
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.sync.Semaphore
|
||||
import kotlinx.coroutines.sync.withPermit
|
||||
import java.util.Timer
|
||||
import java.util.TimerTask
|
||||
import java.util.UUID
|
||||
|
||||
class ChangeNodeTzActivity : BaseActivity(), View.OnClickListener {
|
||||
|
||||
companion object {
|
||||
private var currentNode: MutableList<ClashNodebBean> = mutableListOf()
|
||||
|
||||
// var clash: ClashManager? = null
|
||||
}
|
||||
|
||||
private lateinit var swipeLayout: SwipeRefreshLayout
|
||||
private lateinit var changeNodeVM: ChangeNodeVM
|
||||
private lateinit var nodeListRv: RecyclerView
|
||||
private var names: List<String>? = null
|
||||
private lateinit var aiBack: AppCompatImageView
|
||||
private var broadcastReceiver: BroadcastReceiver? = null
|
||||
private var cacheNodeStr: String? = ""
|
||||
|
||||
// private var checkedNode: ClashNodebBean? = null
|
||||
private var uuid: UUID? = null
|
||||
|
||||
private var testRuning = false
|
||||
// var cprofile: ProfileManager? = null
|
||||
// private var currentNode: Profile? = null
|
||||
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_change_node)
|
||||
setMoreBar("线路测速", this)
|
||||
changeNodeVM = ViewModelProvider(this).get(ChangeNodeVM::class.java)
|
||||
initData()
|
||||
initViews()
|
||||
|
||||
// cprofile = ProfileManager(this)
|
||||
}
|
||||
|
||||
override fun onBackPressed() {
|
||||
intent.putExtra(BZYConstants.EXTRA_KEY_IS_RUNING, is_runing)
|
||||
setResult(CHECK_NODE_RESULT_CODE, intent)
|
||||
super.onBackPressed()
|
||||
}
|
||||
|
||||
private fun initData() {
|
||||
// clash = MainApplication.getApp()?.let { ClashManager(it) }
|
||||
cacheNodeStr = MMKV.defaultMMKV().decodeString(BZYConstants.NODE_All_ITEM_NAME_KEY, "");
|
||||
|
||||
val intentFilter = IntentFilter(Intents.ACTION_NODE_LIST)
|
||||
broadcastReceiver = NodeListBR()
|
||||
if (Build.VERSION.SDK_INT >= 34 && applicationInfo.targetSdkVersion >= 34) {
|
||||
registerReceiver(
|
||||
broadcastReceiver,
|
||||
intentFilter,
|
||||
Context.RECEIVER_EXPORTED
|
||||
)
|
||||
} else {
|
||||
registerReceiver(
|
||||
broadcastReceiver,
|
||||
intentFilter
|
||||
)
|
||||
}
|
||||
// registerReceiver(
|
||||
// broadcastReceiver,
|
||||
// intentFilter
|
||||
// )
|
||||
}
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
private fun initViews() {
|
||||
aiBack = findViewById(R.id.aiBack)
|
||||
aiBack.setOnClickListener {
|
||||
onBackPressed()
|
||||
}
|
||||
swipeLayout = findViewById(R.id.swipeLayout)
|
||||
initRefreshLayout()
|
||||
nodeListRv = findViewById(R.id.rv_node_list)
|
||||
var userTrafficTv: TextView = findViewById(R.id.node_user_traffic)
|
||||
|
||||
findViewById<ImageView>(R.id.iv_back).setOnClickListener {
|
||||
onBackPressed()
|
||||
}
|
||||
initAdapter()
|
||||
// Log.d("initViews cacheNodeStr==>${cacheNodeStr}")
|
||||
if (!TextUtils.isEmpty(cacheNodeStr)) {
|
||||
currentNode = getNodesInfo(cacheNodeStr!!)
|
||||
setNewData(currentNode)
|
||||
}
|
||||
|
||||
// if (!TextUtils.isEmpty(serStore.userTraffic)) {
|
||||
// userTrafficTv.visibility=View.VISIBLE
|
||||
// var jo = JsonParser.parseString(serStore.userTraffic).asJsonObject
|
||||
// var t = jo.get("total")
|
||||
// var d = jo.get("download").asLong
|
||||
// var u = jo.get("upload").asLong
|
||||
// val trafficUsedInGB = String.format("%.2f", (d + u) / 1024.0 / 1024.0 / 1024.0)
|
||||
// userTrafficTv.text="已用流量:${trafficUsedInGB}GB"
|
||||
// }
|
||||
}
|
||||
|
||||
private fun getNodesInfo(json: String): MutableList<ClashNodebBean> {
|
||||
var mList: MutableList<ClashNodebBean> = mutableListOf()
|
||||
if (TextUtils.isEmpty(json)) {
|
||||
return mList
|
||||
}
|
||||
val gson = Gson()
|
||||
var ja = JsonParser.parseString(json).asJsonArray
|
||||
|
||||
var cnb = ClashNodebBean("自动选择", "", "", 1, "", "", 0, true);
|
||||
mList.add(cnb)
|
||||
for (i in 0 until ja.size()) {
|
||||
var bean = gson.fromJson(ja.get(i).asString, ClashNodebBean::class.java)
|
||||
bean.delay = Utils.generateRandomTwoDigitNumber(10, 60)
|
||||
mList.add(bean)
|
||||
}
|
||||
return mList
|
||||
}
|
||||
|
||||
inner class NodeListBR : BroadcastReceiver() {
|
||||
override fun onReceive(context: Context?, intent: Intent?) {
|
||||
when (intent?.action) {
|
||||
Intents.ACTION_NODE_LIST -> {
|
||||
Log.d("ACTION_NODE_LIST ACTION_NODE_LIST")
|
||||
// val parcelableArrayListExtra = intent.getParcelableArrayListExtra<Map<String,Any>>("")
|
||||
hideLoading()
|
||||
// stopTimer()
|
||||
timerJob?.cancel()
|
||||
dialogDoMainChoose?.dismiss()
|
||||
// var json = intent.getStringExtra("node_list")
|
||||
// Log.d("onReceive: $json")
|
||||
// currNodeJsonA = json
|
||||
var json = serStore.nodes
|
||||
// Log.d("serStore.nodes: $json")
|
||||
if (TextUtils.isEmpty(json)) {
|
||||
return
|
||||
}
|
||||
//缓存订阅地址
|
||||
UIMainActivity.subUrl = nowSubUrl
|
||||
MMKV.defaultMMKV().encode(BZYConstants.PROFILE_SUB_URL, nowSubUrl)
|
||||
//缓存节点
|
||||
MMKV.defaultMMKV().encode(BZYConstants.NODE_All_ITEM_NAME_KEY, json)
|
||||
currentNode = getNodesInfo(json)
|
||||
// val listType = object : TypeToken<MutableList<ClashNodebBean>>() {}.type
|
||||
// currentNode = gson.fromJson(json, listType)
|
||||
setNewData(currentNode)
|
||||
swipeLayout.isRefreshing = false
|
||||
}
|
||||
|
||||
else -> {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
broadcastReceiver?.let {
|
||||
unregisterReceiver(it)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
// uuid = intent.getStringExtra(BZYConstants.MMKV_KEY_CURRENT_NODE)
|
||||
// com.cncat.vpn.common.log.Log.d("ChangeNode uuid==>$uuid")
|
||||
is_runing = intent.getBooleanExtra(BZYConstants.EXTRA_KEY_IS_RUNING, false)
|
||||
}
|
||||
|
||||
val remote = Resource<IRemoteService>()
|
||||
var GetNodeTimeOutNum = 5;
|
||||
var is_runing = false
|
||||
private var timer: Timer? = null
|
||||
private var timerTask: TimerTask? = null
|
||||
var nowSubUrl: String = ""
|
||||
private fun updateProfile(isDelete: Boolean) {
|
||||
// showLoading("正在获取...", this@ChangeNodeActivity)
|
||||
|
||||
try {
|
||||
|
||||
|
||||
launch(Dispatchers.IO) {
|
||||
UIMainActivity.profileBinder?.let { profileManager ->
|
||||
var mProfile = profileManager.queryAll().find {
|
||||
it.name == Conf.getClashConfName(this@ChangeNodeTzActivity.applicationContext)
|
||||
}
|
||||
|
||||
if (mProfile == null) {
|
||||
//为空的情况下选择第一个
|
||||
profileManager.queryAll().forEach { profile ->
|
||||
mProfile = profile
|
||||
return@forEach
|
||||
}
|
||||
}
|
||||
|
||||
mProfile?.let { profile ->
|
||||
uuid = profile.uuid
|
||||
Log.d("ChangeNode22 uuid==>${profile.uuid}")
|
||||
if (isDelete) {
|
||||
Log.d("gogogogogo isDelete")
|
||||
profileManager.delete(profile.uuid)
|
||||
MMKV.defaultMMKV()
|
||||
.removeValueForKey(BZYConstants.NODE_All_ITEM_NAME_KEY)
|
||||
setSub2(profileManager, nowSubUrl)
|
||||
} else {
|
||||
Log.d("gogogogogo update")
|
||||
profileManager.setActive(profile)
|
||||
delay(500)
|
||||
if (!TextUtils.isEmpty(profile.source)) {
|
||||
// Log.d("updateProfile pro.source==>${profile.source}, url==>${nowSubUrl}")
|
||||
if (profile.source != nowSubUrl) {
|
||||
Log.d("updateProfile patch")
|
||||
profileManager.patch(
|
||||
profile.uuid,
|
||||
profile.name,
|
||||
nowSubUrl,
|
||||
1800000L
|
||||
)
|
||||
Log.d("updateProfile patch 1")
|
||||
profileManager.commit(profile.uuid) { status ->
|
||||
Log.d("updateProfile updateStatus: " + Gson().toJson(status.args) + ", pro==>" + status.progress)
|
||||
}
|
||||
Log.d("updateProfile patch 2")
|
||||
}
|
||||
}
|
||||
Log.d("updateProfile go update")
|
||||
profileManager.update(profile.uuid)
|
||||
}
|
||||
Log.d("gogogogogo end")
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
|
||||
private fun initRefreshLayout() {
|
||||
swipeLayout.setColorSchemeColors(Color.rgb(47, 223, 189))
|
||||
swipeLayout.setOnRefreshListener(object : OnRefreshListener {
|
||||
override fun onRefresh() {
|
||||
if (testRuning) {
|
||||
RxToast.info("正在测速中.");
|
||||
swipeLayout.isRefreshing = false
|
||||
return
|
||||
}
|
||||
com.cncat.vpn.common.log.Log.d("onRefresh")
|
||||
// getNodesStatus();
|
||||
// changeNodeVM.getAirNodes()
|
||||
swipeLayout.isRefreshing = true
|
||||
updateProfile(false)
|
||||
com.cncat.vpn.common.log.Log.d("onRefresh end")
|
||||
swipeLayout.isRefreshing = false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
UIMainActivity.subUrl?.let {
|
||||
nowSubUrl = it
|
||||
}
|
||||
doProfile()
|
||||
|
||||
}
|
||||
|
||||
fun doProfile() {
|
||||
if (TextUtils.isEmpty(cacheNodeStr)) {
|
||||
|
||||
}
|
||||
showLoading("正在获取...", this@ChangeNodeTzActivity)
|
||||
startTimer()
|
||||
updateProfile(false)
|
||||
|
||||
}
|
||||
|
||||
private fun changeSubUrl(originalUrl: String, newUrl: String) {
|
||||
if(!originalUrl.isNullOrEmpty()&&!newUrl.isNullOrEmpty()){
|
||||
nowSubUrl = originalUrl.replace(Regex("https://[^/]+/"), "$newUrl/")
|
||||
MMKV.defaultMMKV().encode(BZYConstants.PROFILE_SUB_URL, nowSubUrl)
|
||||
}
|
||||
}
|
||||
|
||||
val reloadLock = Semaphore(10)
|
||||
private fun setPing() {
|
||||
if (!NewAccFragment.clashRunning) {
|
||||
RxToast.info("请先开启加速后,再进行测试.");
|
||||
return
|
||||
}
|
||||
if (testRuning) {
|
||||
RxToast.info("正在测速中.");
|
||||
return
|
||||
}
|
||||
testRuning = true
|
||||
updateMoreBar("测速中")
|
||||
launch(Dispatchers.IO) {
|
||||
var group = reloadLock.withPermit {
|
||||
UIMainActivity.clashBinder?.let { cb ->
|
||||
var names = cb.queryProxyGroupNames(false)
|
||||
if (names.isNotEmpty()) {
|
||||
cb.healthCheck(names[0])
|
||||
}
|
||||
delay(1000)
|
||||
cb.queryProxyGroup(names[0], uiStore.proxySort);
|
||||
}
|
||||
}
|
||||
testRuning = false
|
||||
runOnUiThread { updateMoreBar("线路测速") }
|
||||
var newDatas = mutableListOf<ClashNodebBean>();
|
||||
group?.proxies?.forEach { proxy ->
|
||||
Log.d("node==>${proxy}")
|
||||
if (currentNode?.isNotEmpty() == true) {
|
||||
for (nodeItem: ClashNodebBean in currentNode!!) {
|
||||
if (nodeItem.name == proxy.name) {
|
||||
if (proxy.name != "自动选择") {
|
||||
nodeItem.delay = proxy.delay;
|
||||
}
|
||||
Log.d("nodeItem==>${nodeItem}")
|
||||
newDatas.add(nodeItem)
|
||||
return@forEach
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (newDatas.isNotEmpty()) {
|
||||
setNewData(newDatas)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun setNewData(nodes: MutableList<ClashNodebBean>?) {
|
||||
runOnUiThread {
|
||||
if (nodes != null) {
|
||||
nodeListAdapter.setNewInstance(nodes)
|
||||
var selected_name =
|
||||
MMKV.defaultMMKV().decodeString(BZYConstants.NODE_SELECTED_NAME_KEY, "");
|
||||
for ((index, node) in nodes.withIndex()) {
|
||||
if (node.name == selected_name) {
|
||||
nodeListAdapter.selectedPosition = index
|
||||
// checkedNode = node
|
||||
}
|
||||
}
|
||||
nodeListAdapter.notifyDataSetChanged()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var nodeListAdapter: NodeTzListAdapter = NodeTzListAdapter(R.layout.node_tz_list_item_layout)
|
||||
private fun initAdapter() {
|
||||
nodeListRv.layoutManager = LinearLayoutManager(this)
|
||||
nodeListRv.adapter = nodeListAdapter
|
||||
nodeListAdapter.selectedPosition
|
||||
nodeListAdapter.setOnItemClickListener { baseQuickAdapter: BaseQuickAdapter<*, *>, view: View, position: Int ->
|
||||
(baseQuickAdapter.getItem(position) as ClashNodebBean).let { profile ->
|
||||
com.cncat.vpn.common.log.Log.i("select_node : ${profile.name}")
|
||||
// checkedNode = profile
|
||||
MMKV.defaultMMKV().encode(BZYConstants.NODE_SELECTED_NAME_KEY, profile.name)
|
||||
nodeListAdapter.notifyItemChanged(nodeListAdapter.selectedPosition)
|
||||
nodeListAdapter.selectedPosition =
|
||||
if (nodeListAdapter.selectedPosition == position) -1 else position
|
||||
nodeListAdapter.notifyItemChanged(position)
|
||||
// launch {
|
||||
// withClash {
|
||||
// val names = queryProxyGroupNames(false)
|
||||
// val mode = queryOverride(Clash.OverrideSlot.Session).mode
|
||||
// com.cncat.vpn.common.log.Log.d("names 222==>${names}, mode==>$mode")
|
||||
// names?.let { ns ->
|
||||
// if (ns.isNotEmpty()) {
|
||||
// patchSelector(ns[0], profile.name)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
launch(Dispatchers.IO) {
|
||||
val intent = Intent()
|
||||
intent.putExtra(BZYConstants.MMKV_KEY_SELECT_NODE_NAME, "自动选择")
|
||||
intent.putExtra(BZYConstants.EXTRA_KEY_IS_RUNING, is_runing)
|
||||
setResult(CHECK_NODE_RESULT_CODE, intent)
|
||||
finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun createProfile() {
|
||||
launch(Dispatchers.IO) {
|
||||
UIMainActivity.profileBinder?.let { pro ->
|
||||
uuid?.let { uu ->
|
||||
pro.delete(uu)
|
||||
delay(500)
|
||||
setSub2(pro, UIMainActivity.subUrl)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public suspend fun setSub2(pm: IProfileManager, url: String?) {
|
||||
// com.cncat.vpn.common.log.Log.d("setSub2.... url==>$url")
|
||||
if (TextUtils.isEmpty(url)) {
|
||||
com.cncat.vpn.common.log.Log.d("setSub2 url isEmpty")
|
||||
return
|
||||
}
|
||||
|
||||
com.cncat.vpn.common.log.Log.d("setSub2 2")
|
||||
|
||||
|
||||
com.cncat.vpn.common.log.Log.d("setSub2 3")
|
||||
val pro = pm.queryAll().find {
|
||||
it.name == Conf.getClashConfName(this@ChangeNodeTzActivity.applicationContext)
|
||||
}
|
||||
com.cncat.vpn.common.log.Log.d("setSub2 4")
|
||||
pro?.let {
|
||||
com.cncat.vpn.common.log.Log.d("setSub2 pro 已存在 ==>")
|
||||
// pm.setActive(it)
|
||||
|
||||
com.cncat.vpn.common.log.Log.d("setSub2 setActive end")
|
||||
} ?: run {
|
||||
var uuid: UUID = pm.create(
|
||||
Profile.Type.Url,
|
||||
Conf.getClashConfName(this@ChangeNodeTzActivity.applicationContext)
|
||||
)
|
||||
delay(500)
|
||||
pm.queryByUUID(uuid)?.let { qPro ->
|
||||
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",
|
||||
url!!,
|
||||
1800000L
|
||||
)
|
||||
// coroutineScope {
|
||||
pm.commit(qPro.uuid) { status ->
|
||||
android.util.Log.d(
|
||||
Conf.TAG,
|
||||
"new updateStatus: " + Gson().toJson(status.args) + ", pro==>" + status.progress
|
||||
)
|
||||
}
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var isCreate: Boolean = false
|
||||
private var timerJob: Job? = null
|
||||
private fun startTimer() {
|
||||
GetNodeTimeOutNum = 15
|
||||
timerJob = launch {
|
||||
repeat(16) {
|
||||
Log.d("GetNodeTimeOutNum==>$GetNodeTimeOutNum")
|
||||
if (GetNodeTimeOutNum == 0) {
|
||||
hideLoading()
|
||||
Log.d("stopTimer...")
|
||||
RxToast.error("获取节点失败...请尝试切换其他地址")
|
||||
showDomainList()
|
||||
timerJob?.cancel()
|
||||
// delay(1000)
|
||||
// this@ChangeNodeActivity.finish()
|
||||
|
||||
}
|
||||
GetNodeTimeOutNum--
|
||||
delay(1000)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var dialogDoMainChoose: DialogDoMainChoose? = null
|
||||
private fun showDomainList() {
|
||||
try {
|
||||
SplashHelper(changeNodeVM).getHostWithFallback { success ->
|
||||
MainScope().launch {
|
||||
|
||||
if (success) {
|
||||
if (dialogDoMainChoose == null) {
|
||||
dialogDoMainChoose = DialogDoMainChoose(this@ChangeNodeTzActivity)
|
||||
}
|
||||
if (dialogDoMainChoose?.isShowing == false) {
|
||||
dialogDoMainChoose?.setOnTryButtonListener(object :
|
||||
DialogDoMainChoose.OnTryButtonListener {
|
||||
override fun tryButton() {
|
||||
saveSubUrl()
|
||||
doProfile()
|
||||
dialogDoMainChoose?.dismiss()
|
||||
}
|
||||
|
||||
override fun cancel() {
|
||||
com.cncat.vpn.common.log.Log.d("tryButton CHECK_LOGIN cancel")
|
||||
|
||||
dialogDoMainChoose?.dismiss()
|
||||
}
|
||||
})
|
||||
dialogDoMainChoose?.setOnListItemListener(object :
|
||||
DialogDoMainChoose.OnListItemListener {
|
||||
override fun listItemClick() {
|
||||
saveSubUrl()
|
||||
MainApplication.restartApp(this@ChangeNodeTzActivity, object :
|
||||
MainApplication.OnRestartButtonListener {
|
||||
|
||||
override fun enterButton() {
|
||||
|
||||
}
|
||||
|
||||
override fun cancelButton() {
|
||||
doProfile()
|
||||
dialogDoMainChoose?.dismiss()
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
})
|
||||
dialogDoMainChoose?.show()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
|
||||
private fun saveSubUrl() {
|
||||
var currentHost = MMKV.defaultMMKV()
|
||||
.decodeString(BZYConstants.MMKV_KEY_CURRENT_HOST, "")
|
||||
// com.cncat.vpn.common.log.Log.d("tryButton currentHost==>${currentHost}")
|
||||
var oldUrl = nowSubUrl
|
||||
currentHost?.let { changeSubUrl(oldUrl, it) }
|
||||
}
|
||||
|
||||
private fun stopTimer() {
|
||||
timerTask?.cancel()
|
||||
timer?.purge()
|
||||
timer?.cancel()
|
||||
timerTask = null
|
||||
timer = null
|
||||
}
|
||||
|
||||
override fun onClick(p0: View?) {
|
||||
when (p0?.id) {
|
||||
R.id.tv_more -> {
|
||||
setPing()
|
||||
}
|
||||
|
||||
else -> {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -206,6 +206,14 @@ class LoginActivity : BaseActivity(), View.OnClickListener {
|
|||
dialogDoMainChoose?.dismiss()
|
||||
}
|
||||
})
|
||||
dialogDoMainChoose?.setOnListItemListener(object :
|
||||
DialogDoMainChoose.OnListItemListener {
|
||||
override fun listItemClick() {
|
||||
loginViewMode.login(username_encrypt, password_encrypt,user_oaid)
|
||||
|
||||
}
|
||||
|
||||
})
|
||||
dialogDoMainChoose?.show()
|
||||
}
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -32,9 +32,6 @@ import com.bumptech.glide.request.transition.Transition
|
|||
import com.cncat.vpn.service.ClashManager
|
||||
import com.cncat.vpn.service.remote.IClashManager
|
||||
import com.cncat.vpn.service.remote.wrap
|
||||
import com.fm.openinstall.OpenInstall
|
||||
import com.fm.openinstall.listener.AppWakeUpAdapter
|
||||
import com.fm.openinstall.model.AppData
|
||||
import com.google.gson.JsonObject
|
||||
import com.orhanobut.logger.Logger
|
||||
import com.tencent.mmkv.MMKV
|
||||
|
|
@ -254,35 +251,35 @@ class SplashActivity : BaseActivity() {
|
|||
// println("Sgtr==>$Sgtr")
|
||||
|
||||
|
||||
OpenInstall.getWakeUp(intent, wakeUpAdapter)
|
||||
OpenInstall.getInstall { appData, error ->
|
||||
var appData = appData
|
||||
if (error != null && error.shouldRetry()) {
|
||||
// 获取数据异常,可以尝试重新获取
|
||||
} else {
|
||||
if (appData == null) appData = AppData()
|
||||
val channelCode = appData.getChannel() // 获取渠道编号参数
|
||||
val bindData = appData.getData() // 获取自定义参数
|
||||
Log.d("OpenInstall", "getInstall : channelCode = $channelCode"+"bindData::"+bindData)
|
||||
}
|
||||
}
|
||||
}
|
||||
private var wakeUpAdapter: AppWakeUpAdapter = object : AppWakeUpAdapter() {
|
||||
override fun onWakeUp(appData: AppData) {
|
||||
// 打印数据便于调试
|
||||
Log.d("OpenInstall", "getWakeUp : wakeupData = $appData")
|
||||
// 获取渠道编号参数
|
||||
val channelCode = appData.getChannel()
|
||||
// 获取自定义参数
|
||||
val bindData = appData.getData()
|
||||
Log.d("OpenInstall", "channelCode : bindData = $channelCode"+"bindData::"+bindData)
|
||||
}
|
||||
// OpenInstall.getWakeUp(intent, wakeUpAdapter)
|
||||
// OpenInstall.getInstall { appData, error ->
|
||||
// var appData = appData
|
||||
// if (error != null && error.shouldRetry()) {
|
||||
// // 获取数据异常,可以尝试重新获取
|
||||
// } else {
|
||||
// if (appData == null) appData = AppData()
|
||||
// val channelCode = appData.getChannel() // 获取渠道编号参数
|
||||
// val bindData = appData.getData() // 获取自定义参数
|
||||
// Log.d("OpenInstall", "getInstall : channelCode = $channelCode"+"bindData::"+bindData)
|
||||
// }
|
||||
// }
|
||||
}
|
||||
// private var wakeUpAdapter: AppWakeUpAdapter = object : AppWakeUpAdapter() {
|
||||
// override fun onWakeUp(appData: AppData) {
|
||||
// // 打印数据便于调试
|
||||
// Log.d("OpenInstall", "getWakeUp : wakeupData = $appData")
|
||||
// // 获取渠道编号参数
|
||||
// val channelCode = appData.getChannel()
|
||||
// // 获取自定义参数
|
||||
// val bindData = appData.getData()
|
||||
// Log.d("OpenInstall", "channelCode : bindData = $channelCode"+"bindData::"+bindData)
|
||||
// }
|
||||
// }
|
||||
|
||||
override fun onNewIntent(intent: Intent?) {
|
||||
super.onNewIntent(intent)
|
||||
// 此处要调用,否则App在后台运行时,会无法获取
|
||||
OpenInstall.getWakeUp(intent, wakeUpAdapter)
|
||||
// OpenInstall.getWakeUp(intent, wakeUpAdapter)
|
||||
}
|
||||
private fun setLocalLanguage() {
|
||||
var defLan = ""
|
||||
|
|
@ -763,6 +760,14 @@ class SplashActivity : BaseActivity() {
|
|||
dialogDoMainChoose=null
|
||||
}
|
||||
})
|
||||
dialogDoMainChoose?.setOnListItemListener(object :
|
||||
DialogDoMainChoose.OnListItemListener {
|
||||
override fun listItemClick() {
|
||||
doRegisterByEncryption()
|
||||
dialogDoMainChoose?.dismiss()
|
||||
}
|
||||
|
||||
})
|
||||
dialogDoMainChoose?.show()
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
|
|
@ -830,6 +835,14 @@ class SplashActivity : BaseActivity() {
|
|||
dialogDoMainChoose?.dismiss()
|
||||
}
|
||||
})
|
||||
dialogDoMainChoose?.setOnListItemListener(object :
|
||||
DialogDoMainChoose.OnListItemListener {
|
||||
override fun listItemClick() {
|
||||
splashAtyVM.checkLogin()
|
||||
|
||||
}
|
||||
|
||||
})
|
||||
dialogDoMainChoose?.show()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -150,8 +150,8 @@ class MainApplication : Application() {
|
|||
applicationContext,
|
||||
"pk_live_51Nkl6vLWP3xWXY4LfXtdMtXzHazv6pav2rH1p1BfICeh5meGGjglExiw4GgmSzWO7NptEM1c549Fe11zRy9nCfxs009zEwLpXP"
|
||||
)
|
||||
OpenInstall.preInit(applicationContext)
|
||||
OpenInstall.init(applicationContext)
|
||||
// OpenInstall.preInit(applicationContext)
|
||||
// OpenInstall.init(applicationContext)
|
||||
}
|
||||
|
||||
fun updateActivity(language: String, locale: Locale) {
|
||||
|
|
|
|||
|
|
@ -35,10 +35,12 @@ import com.cncat.vpn.core.Clash
|
|||
import com.cncat.vpn.core.model.TunnelState
|
||||
import com.orhanobut.logger.Logger
|
||||
import com.tencent.mmkv.MMKV
|
||||
import com.yingmao.clash.BuildConfig
|
||||
import com.yingmao.clash.R
|
||||
import com.yingmao.clash.act.ActivityActivity
|
||||
import com.yingmao.clash.act.BandPhoneActivity
|
||||
import com.yingmao.clash.act.ChangeNodeActivity
|
||||
import com.yingmao.clash.act.ChangeNodeTzActivity
|
||||
import com.yingmao.clash.act.ConnectionModeActivity
|
||||
import com.yingmao.clash.act.LoginActivity
|
||||
import com.yingmao.clash.act.UIMainActivity
|
||||
|
|
@ -207,7 +209,12 @@ class HomeFragment : BaseFragment(), CoroutineScope by CoroutineScope(Dispatcher
|
|||
}
|
||||
return@setOnClickListener
|
||||
}
|
||||
val intent = Intent(CommonUtils.getApp(), ChangeNodeActivity::class.java)
|
||||
var intent: Intent? = null
|
||||
if (BuildConfig.is_tz) {
|
||||
intent = Intent(CommonUtils.getApp(), ChangeNodeTzActivity::class.java)
|
||||
} else {
|
||||
intent = Intent(CommonUtils.getApp(), ChangeNodeActivity::class.java)
|
||||
}
|
||||
if (!TextUtils.isEmpty(newUuid)) {
|
||||
intent.putExtra(BZYConstants.MMKV_KEY_CURRENT_NODE, newUuid)
|
||||
intent.putExtra(BZYConstants.EXTRA_KEY_IS_RUNING, clashRunning)
|
||||
|
|
@ -265,10 +272,13 @@ class HomeFragment : BaseFragment(), CoroutineScope by CoroutineScope(Dispatcher
|
|||
setExpireDate()
|
||||
setProxyModeView(newMainActGlo)
|
||||
|
||||
|
||||
var selected_name =
|
||||
MMKV.defaultMMKV().decodeString(BZYConstants.NODE_SELECTED_NAME_KEY, "");
|
||||
if (!TextUtils.isEmpty(selected_name)) {
|
||||
setNodeNameAndImg(selected_name!!)
|
||||
if (!BuildConfig.is_tz){
|
||||
setNodeNameAndImg(selected_name!!)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -862,6 +862,21 @@ class RechargeFragment : BaseFragment() {
|
|||
dialogDoMainChoose?.dismiss()
|
||||
}
|
||||
})
|
||||
dialogDoMainChoose?.setOnListItemListener(object :
|
||||
DialogDoMainChoose.OnListItemListener {
|
||||
override fun listItemClick() {
|
||||
val username = MMKV.defaultMMKV()
|
||||
.decodeString(BZYConstants.MMKV_KEY_REMEMBER_USERNAME, "")!!
|
||||
|
||||
val phToken = MMKV.defaultMMKV()
|
||||
.decodeString(BZYConstants.MMKV_KEY_PH_TOKEN, "")!!
|
||||
// viewModel.getPointCardSurplus(username, phToken)
|
||||
val userId = MMKV.defaultMMKV()
|
||||
.decodeString(BZYConstants.MMKV_KEY_USER_ID)!!
|
||||
viewModel.getPhRechargeInfo(username, phToken, userId)
|
||||
}
|
||||
|
||||
})
|
||||
dialogDoMainChoose?.show()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -326,6 +326,7 @@ class SettingFragment : BaseFragment(), CoroutineScope by CoroutineScope(Dispatc
|
|||
if (TextUtils.isEmpty(subUrl)) {
|
||||
return@setOnClickListener
|
||||
}
|
||||
cleanNodeMmkv()
|
||||
showLoading(resources.getString(R.string.UnderRepair), requireActivity())
|
||||
|
||||
launch(Dispatchers.IO) {
|
||||
|
|
@ -485,7 +486,11 @@ class SettingFragment : BaseFragment(), CoroutineScope by CoroutineScope(Dispatc
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
private fun cleanNodeMmkv(){
|
||||
MMKV.defaultMMKV().removeValueForKey(BZYConstants.NODE_SELECTED_NAME_KEY)
|
||||
MMKV.defaultMMKV().removeValueForKey(BZYConstants.NODE_All_ITEM_NAME_KEY)
|
||||
MMKV.defaultMMKV().removeValueForKey(BZYConstants.PROFILE_SUB_URL)
|
||||
}
|
||||
|
||||
|
||||
var dialogDoMainChoose: DialogDoMainChoose? = null
|
||||
|
|
@ -617,6 +622,7 @@ class SettingFragment : BaseFragment(), CoroutineScope by CoroutineScope(Dispatc
|
|||
MMKV.defaultMMKV().removeValueForKey(BZYConstants.NODE_SELECTED_NAME_KEY)
|
||||
MMKV.defaultMMKV().removeValueForKey(BZYConstants.MMKV_KEY_VPN_UserCommand)
|
||||
MMKV.defaultMMKV().removeValueForKey(BZYConstants.NODE_All_ITEM_NAME_KEY)
|
||||
MMKV.defaultMMKV().removeValueForKey(BZYConstants.PROFILE_SUB_URL)
|
||||
Log.d("cleanUserInfo clashRunning==>${clashRunning}")
|
||||
if (clashRunning) {
|
||||
fragments.filterIsInstance<HomeFragment>().forEach { it.stopClash() }
|
||||
|
|
@ -876,7 +882,6 @@ class SettingFragment : BaseFragment(), CoroutineScope by CoroutineScope(Dispatc
|
|||
Log.d("setSub2 delete ==>${itemPro.name}")
|
||||
pm.delete(itemPro.uuid)
|
||||
}
|
||||
|
||||
}
|
||||
val pro = pm.queryActive()
|
||||
|
||||
|
|
|
|||
|
|
@ -38,11 +38,7 @@ class NodeListAdapter(layoutResId: Int) :
|
|||
nodeListItem.isSelected = false
|
||||
nodeCheckMrb.isSelected = false
|
||||
}
|
||||
// if (item.pingTime!! > 1) {
|
||||
// holder.setText(R.id.tv_ping_time, "${item.pingTime}ms")
|
||||
// } else {
|
||||
// holder.setText(R.id.tv_ping_time, "超时")
|
||||
// }
|
||||
|
||||
val nodeNameTv = holder.getView<TextView>(R.id.node_list_item_tv_node_name)
|
||||
nodeNameTv.text = item.name
|
||||
|
||||
|
|
@ -50,17 +46,21 @@ class NodeListAdapter(layoutResId: Int) :
|
|||
if(holder.layoutPosition==0){
|
||||
signal.visibility=View.GONE
|
||||
}else{
|
||||
|
||||
signal.visibility=View.VISIBLE
|
||||
if (item.delay > 0) {
|
||||
if (item.delay >= 65535) {
|
||||
item.delay = Utils.generateRandomTwoDigitNumber(99, 300)
|
||||
signal.setImageResource(R.drawable.ic_wifi_generally)
|
||||
holder.setText(R.id.tv_ping_time, "超时")
|
||||
} else {
|
||||
item.delay = Utils.generateRandomTwoDigitNumber(10, 60)
|
||||
signal.setImageResource(R.drawable.ic_wifi_powerful)
|
||||
holder.setText(R.id.tv_ping_time, "${item.delay}ms")
|
||||
}
|
||||
} else {
|
||||
signal.setImageResource(R.drawable.ic_wifi_week)
|
||||
holder.setText(R.id.tv_ping_time, "超时")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,66 @@
|
|||
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 androidx.appcompat.widget.AppCompatImageView
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
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.util.Utils
|
||||
|
||||
class NodeTzListAdapter(layoutResId: Int) :
|
||||
BaseQuickAdapter<ClashNodebBean, BaseViewHolder>(layoutResId), LoadMoreModule {
|
||||
|
||||
var selectedPosition: Int = 0
|
||||
var index:Int=1
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
override fun convert(holder: BaseViewHolder, item: ClashNodebBean) {
|
||||
|
||||
val nodeListItem = holder.getView<ConstraintLayout>(R.id.rl_node_list_item)
|
||||
val nodeCheckMrb = holder.getView<AppCompatImageView>(R.id.mrb_node_checked)
|
||||
if (holder.layoutPosition == selectedPosition) {
|
||||
nodeListItem.isSelected = true
|
||||
nodeCheckMrb.isSelected = true
|
||||
} else {
|
||||
nodeListItem.isSelected = false
|
||||
nodeCheckMrb.isSelected = false
|
||||
}
|
||||
val nodeNameTv = holder.getView<TextView>(R.id.node_list_item_tv_node_name)
|
||||
if (holder.layoutPosition==0){
|
||||
nodeNameTv.text = item.name
|
||||
}else {
|
||||
nodeNameTv.text = "线路${holder.layoutPosition + 1}"
|
||||
}
|
||||
val signal = holder.getView<ImageView>(R.id.ivWifi)
|
||||
if(holder.layoutPosition==0){
|
||||
signal.visibility=View.GONE
|
||||
}else{
|
||||
signal.visibility=View.VISIBLE
|
||||
if (item.delay > 0) {
|
||||
if (item.delay >= 65535) {
|
||||
item.delay = Utils.generateRandomTwoDigitNumber(99, 300)
|
||||
signal.setImageResource(R.drawable.ic_wifi_generally)
|
||||
} else {
|
||||
item.delay = Utils.generateRandomTwoDigitNumber(10, 60)
|
||||
signal.setImageResource(R.drawable.ic_wifi_powerful)
|
||||
}
|
||||
} else {
|
||||
signal.setImageResource(R.drawable.ic_wifi_week)
|
||||
}
|
||||
}
|
||||
index++
|
||||
}
|
||||
}
|
||||
|
|
@ -39,7 +39,19 @@
|
|||
android:text="@string/LineSwitching"
|
||||
android:textSize="18sp"
|
||||
/>
|
||||
<TextView
|
||||
android:id="@+id/node_item_test"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="@color/orange_FF9C00"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
android:text="@string/node_item_test"
|
||||
android:layout_marginEnd="@dimen/dp_10"
|
||||
android:textSize="18sp"
|
||||
|
||||
/>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
<TextView
|
||||
android:id="@+id/node_user_traffic"
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/rl_node_list_item"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
|
@ -18,12 +18,11 @@
|
|||
android:layout_marginStart="21dp"
|
||||
android:layout_marginTop="20dp"
|
||||
android:layout_marginBottom="20dp"
|
||||
tools:ignore="ContentDescription"
|
||||
android:src="@drawable/flag_china"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
android:src="@drawable/flag_china"
|
||||
/>
|
||||
tools:ignore="ContentDescription" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/node_list_item_tv_node_name"
|
||||
|
|
@ -32,22 +31,26 @@
|
|||
android:layout_centerVertical="true"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_toEndOf="@id/node_list_item_iv_country"
|
||||
android:text="直连香港"
|
||||
android:text=""
|
||||
android:textColor="#0136CB"
|
||||
android:textSize="16sp"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/node_list_item_iv_country"
|
||||
app:layout_constraintStart_toEndOf="@+id/node_list_item_iv_country"
|
||||
app:layout_constraintTop_toTopOf="@+id/node_list_item_iv_country" />
|
||||
|
||||
<!-- <TextView-->
|
||||
<!-- android:id="@+id/tv_ping_time"-->
|
||||
<!-- android:layout_width="wrap_content"-->
|
||||
<!-- android:layout_height="wrap_content"-->
|
||||
<!-- android:layout_centerVertical="true"-->
|
||||
<!-- android:layout_marginRight="@dimen/dp_10"-->
|
||||
<!-- android:layout_toLeftOf="@id/mrb_node_checked"-->
|
||||
<!-- android:textColor="@color/white"-->
|
||||
<!-- android:textSize="13sp" />-->
|
||||
<TextView
|
||||
android:id="@+id/tv_ping_time"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginEnd="@dimen/dp_15"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@+id/mrb_node_checked"
|
||||
android:textColor="#0136CB"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
android:textSize="13sp"
|
||||
tools:ignore="MissingConstraints" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/ivWifi"
|
||||
android:layout_width="wrap_content"
|
||||
|
|
@ -65,11 +68,11 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:background="@drawable/home_node_img_bg"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
android:layout_marginEnd="21dp"
|
||||
android:clickable="false" />
|
||||
android:background="@drawable/home_node_img_bg"
|
||||
android:clickable="false"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/rl_node_list_item"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:background="@drawable/home_node_bg"
|
||||
android:clickable="true"
|
||||
android:focusable="true">
|
||||
|
||||
|
||||
|
||||
<TextView
|
||||
android:id="@+id/node_list_item_tv_node_name"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerVertical="true"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
android:layout_marginStart="31dp"
|
||||
android:layout_marginTop="20dp"
|
||||
android:layout_marginBottom="20dp"
|
||||
android:text="线路1"
|
||||
android:textColor="#0136CB"
|
||||
android:textSize="16sp"
|
||||
/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/ivWifi"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="15dp"
|
||||
android:src="@drawable/ic_wifi_powerful"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/node_list_item_tv_node_name"
|
||||
app:layout_constraintStart_toEndOf="@+id/node_list_item_tv_node_name"
|
||||
app:layout_constraintTop_toTopOf="@+id/node_list_item_tv_node_name" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/mrb_node_checked"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:background="@drawable/home_node_img_bg"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
android:layout_marginEnd="21dp"
|
||||
android:clickable="false" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
|
@ -350,4 +350,5 @@ Service Description\n
|
|||
<string name="PopularApplicationsStr">Popular Application Navigation</string>
|
||||
<string name="sure_restart">Suggest restarting</string>
|
||||
<string name="restart">Restart</string>
|
||||
<string name="node_item_test">Speed test</string>
|
||||
</resources>
|
||||
|
|
@ -340,4 +340,5 @@
|
|||
<string name="PopularApplicationsStr">熱門應用導航</string>
|
||||
<string name="sure_restart">"建議重啓 "</string>
|
||||
<string name="restart">"重啓 "</string>
|
||||
<string name="node_item_test">線路測速</string>
|
||||
</resources>
|
||||
|
|
@ -339,4 +339,5 @@
|
|||
<string name="PopularApplicationsStr">熱門應用導航</string>
|
||||
<string name="sure_restart">"建議重啓 "</string>
|
||||
<string name="restart">"重啓 "</string>
|
||||
<string name="node_item_test">線路測速</string>
|
||||
</resources>
|
||||
|
|
@ -358,4 +358,5 @@
|
|||
<string name="PopularApplicationsStr">热门应用导航</string>
|
||||
<string name="sure_restart">建议重启</string>
|
||||
<string name="restart">重启</string>
|
||||
<string name="node_item_test">线路测速</string>
|
||||
</resources>
|
||||
|
|
@ -71,8 +71,8 @@ subprojects {
|
|||
minSdk = 21
|
||||
//noinspection ExpiredTargetSdkVersion
|
||||
targetSdk = 34
|
||||
versionName = "1.0.3.8"
|
||||
versionCode = 1038
|
||||
versionName = "1.0.3.9"
|
||||
versionCode = 1039
|
||||
resValue("string", "release_name", "v$versionName")
|
||||
resValue("integer", "release_code", "$versionCode")
|
||||
externalNativeBuild {
|
||||
|
|
|
|||
Loading…
Reference in New Issue