合并提交
This commit is contained in:
parent
93ead85629
commit
e474d6bd57
|
|
@ -25,7 +25,7 @@ dependencies {
|
||||||
implementation(libs.rikkax.multiprocess)
|
implementation(libs.rikkax.multiprocess)
|
||||||
val commonAar = file("libs/common.aar")
|
val commonAar = file("libs/common.aar")
|
||||||
val coreAar = file("libs/core.aar")
|
val coreAar = file("libs/core.aar")
|
||||||
val hideawayEar = file("libs/hideapi.aar")
|
val hideapiAar = file("libs/hideapi.aar")
|
||||||
val serviceAar = file("libs/service.aar")
|
val serviceAar = file("libs/service.aar")
|
||||||
val oss = file("libs/oss-android-sdk-2.9.19.aar")
|
val oss = file("libs/oss-android-sdk-2.9.19.aar")
|
||||||
if (oss.exists()) {
|
if (oss.exists()) {
|
||||||
|
|
@ -45,8 +45,8 @@ dependencies {
|
||||||
println("core.aar does not exist")
|
println("core.aar does not exist")
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hideawayEar.exists()) {
|
if (hideapiAar.exists()) {
|
||||||
implementation(files(hideawayEar))
|
implementation(files(hideapiAar))
|
||||||
} else {
|
} else {
|
||||||
println("hideapi.aar does not exist")
|
println("hideapi.aar does not exist")
|
||||||
}
|
}
|
||||||
|
|
@ -58,14 +58,18 @@ dependencies {
|
||||||
|
|
||||||
implementation(libs.kotlin.coroutine)
|
implementation(libs.kotlin.coroutine)
|
||||||
implementation(libs.androidx.core)
|
implementation(libs.androidx.core)
|
||||||
|
// implementation(libs.androidx.activity)
|
||||||
|
// implementation(libs.androidx.fragment)
|
||||||
implementation(libs.androidx.appcompat)
|
implementation(libs.androidx.appcompat)
|
||||||
implementation(libs.androidx.coordinator)
|
implementation(libs.androidx.coordinator)
|
||||||
implementation(libs.androidx.recyclerview)
|
implementation(libs.androidx.recyclerview)
|
||||||
implementation(libs.google.material)
|
implementation(libs.google.material)
|
||||||
|
|
||||||
implementation("androidx.lifecycle:lifecycle-livedata-ktx:2.9.1")
|
implementation("androidx.lifecycle:lifecycle-livedata-ktx:2.5.1")
|
||||||
implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.9.1")
|
implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.5.1")
|
||||||
implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.9.1")
|
implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.5.1")
|
||||||
|
|
||||||
|
// https://mvnrepository.com/artifact/com.tencent/mmkv-static
|
||||||
implementation("com.tencent:mmkv-static:1.2.10")
|
implementation("com.tencent:mmkv-static:1.2.10")
|
||||||
|
|
||||||
implementation ("com.jakewharton:process-phoenix:3.0.0")
|
implementation ("com.jakewharton:process-phoenix:3.0.0")
|
||||||
|
|
@ -78,13 +82,29 @@ dependencies {
|
||||||
api("com.orhanobut:logger:2.2.0")
|
api("com.orhanobut:logger:2.2.0")
|
||||||
api("com.google.code.gson:gson:2.10.1")
|
api("com.google.code.gson:gson:2.10.1")
|
||||||
api(platform("com.squareup.okhttp3:okhttp-bom:4.10.0"))
|
api(platform("com.squareup.okhttp3:okhttp-bom:4.10.0"))
|
||||||
|
|
||||||
|
// define any required OkHttp artifacts without version
|
||||||
api("com.squareup.okhttp3:okhttp")
|
api("com.squareup.okhttp3:okhttp")
|
||||||
api("com.squareup.okhttp3:logging-interceptor")
|
api("com.squareup.okhttp3:logging-interceptor")
|
||||||
|
//// https://mvnrepository.com/artifact/com.google.code.gson/gson
|
||||||
|
// api("com.google.code.gson:gson:2.10.1")
|
||||||
api("org.yaml:snakeyaml:1.29")
|
api("org.yaml:snakeyaml:1.29")
|
||||||
|
|
||||||
|
// https://mvnrepository.com/artifact/com.alipay.sdk/alipaysdk-android
|
||||||
implementation("com.alipay.sdk:alipaysdk-android:15.8.17")
|
implementation("com.alipay.sdk:alipaysdk-android:15.8.17")
|
||||||
|
// https://mvnrepository.com/artifact/com.journeyapps/zxing-android-embedded
|
||||||
|
// implementation("com.journeyapps:zxing-android-embedded:3.6.0")
|
||||||
|
|
||||||
|
// https://mvnrepository.com/artifact/com.google.zxing/core
|
||||||
|
// implementation("com.google.zxing:core:3.5.3")
|
||||||
implementation("com.github.CymChad:BaseRecyclerViewAdapterHelper:3.0.4")
|
implementation("com.github.CymChad:BaseRecyclerViewAdapterHelper:3.0.4")
|
||||||
|
// https://mvnrepository.com/artifact/com.airbnb.android/lottie
|
||||||
implementation("com.airbnb.android:lottie:5.2.0")
|
implementation("com.airbnb.android:lottie:5.2.0")
|
||||||
implementation("com.github.bumptech.glide:glide:4.16.0")
|
// https://mvnrepository.com/artifact/com.github.bumptech.glide/glide
|
||||||
|
implementation("com.github.bumptech.glide:glide:4.13.2")
|
||||||
|
// implementation("com.luozm.captcha:captcha:1.1.2")
|
||||||
|
// implementation("com.aliyun.dpa:oss-android-sdk:2.9.19")
|
||||||
|
// implementation ("com.hihonor.mcs:ads-identifier:1.0.3.301")
|
||||||
implementation("com.github.gzu-liyujiang:Android_CN_OAID:4.2.8") {
|
implementation("com.github.gzu-liyujiang:Android_CN_OAID:4.2.8") {
|
||||||
exclude("com.hihonor.mcs", "ads-identifier")
|
exclude("com.hihonor.mcs", "ads-identifier")
|
||||||
exclude("com.huawei.hms", "ads-identifier")
|
exclude("com.huawei.hms", "ads-identifier")
|
||||||
|
|
@ -92,7 +112,9 @@ dependencies {
|
||||||
//stripe 支付
|
//stripe 支付
|
||||||
implementation("com.stripe:stripe-android:21.4.2")// 使用最新版本
|
implementation("com.stripe:stripe-android:21.4.2")// 使用最新版本
|
||||||
implementation("com.github.getActivity:XXPermissions:20.0")
|
implementation("com.github.getActivity:XXPermissions:20.0")
|
||||||
|
// 华为的最新版本广告标识服务SDK,参阅 https://developer.huawei.com/consumer/cn/doc/HMSCore-Guides/identifier-service-version-change-history-0000001050066927
|
||||||
api ("com.huawei.hms:ads-identifier:3.4.62.300")
|
api ("com.huawei.hms:ads-identifier:3.4.62.300")
|
||||||
|
// 荣耀的最新版本广告标识服务SDK,参阅 https://developer.hihonor.com/cn/kitdoc?kitId=11030&navigation=guides&docId=intergrate.md
|
||||||
api ("com.hihonor.mcs:ads-identifier:1.0.2.301")
|
api ("com.hihonor.mcs:ads-identifier:1.0.2.301")
|
||||||
implementation("com.android.installreferrer:installreferrer:2.2")// 使用最新版本
|
implementation("com.android.installreferrer:installreferrer:2.2")// 使用最新版本
|
||||||
|
|
||||||
|
|
@ -108,7 +130,9 @@ task("downloadGeoFiles") {
|
||||||
|
|
||||||
val geoFilesUrls = mapOf(
|
val geoFilesUrls = mapOf(
|
||||||
"https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/geoip.metadb" to "geoip.metadb",
|
"https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/geoip.metadb" to "geoip.metadb",
|
||||||
"https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/geosite.dat" to "geosite.dat")
|
"https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/geosite.dat" to "geosite.dat",
|
||||||
|
// "https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/country.mmdb" to "country.mmdb",
|
||||||
|
)
|
||||||
|
|
||||||
doLast {
|
doLast {
|
||||||
geoFilesUrls.forEach { (downloadUrl, outputFileName) ->
|
geoFilesUrls.forEach { (downloadUrl, outputFileName) ->
|
||||||
|
|
@ -159,6 +183,9 @@ android {
|
||||||
abiFilters.add("armeabi-v7a")
|
abiFilters.add("armeabi-v7a")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// sourceSets.all {
|
||||||
|
// jniLibs.srcDir("src/main/jniLibs")
|
||||||
|
// }
|
||||||
sourceSets.all {
|
sourceSets.all {
|
||||||
jniLibs.srcDir("src/main/jniLibs")
|
jniLibs.srcDir("src/main/jniLibs")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -166,6 +166,9 @@
|
||||||
<activity android:name=".webview.BZYWebViewNormal"
|
<activity android:name=".webview.BZYWebViewNormal"
|
||||||
android:process=":background"
|
android:process=":background"
|
||||||
/>
|
/>
|
||||||
|
<activity android:name=".webview.BZYWebViewKeFu"
|
||||||
|
android:process=":background"
|
||||||
|
/>
|
||||||
<service android:name=".service.ConnectionService"/>
|
<service android:name=".service.ConnectionService"/>
|
||||||
<provider
|
<provider
|
||||||
android:name="androidx.core.content.FileProvider"
|
android:name="androidx.core.content.FileProvider"
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,6 @@ import android.widget.Toast
|
||||||
import androidx.appcompat.widget.AppCompatImageView
|
import androidx.appcompat.widget.AppCompatImageView
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import androidx.lifecycle.observe
|
import androidx.lifecycle.observe
|
||||||
import com.baidu.mobads.action.ActionType
|
|
||||||
import com.baidu.mobads.action.BaiduAction
|
|
||||||
import com.yingmao.clash.view.dialog.RxDialogShapeLoading
|
import com.yingmao.clash.view.dialog.RxDialogShapeLoading
|
||||||
|
|
||||||
import com.tencent.mmkv.MMKV
|
import com.tencent.mmkv.MMKV
|
||||||
|
|
@ -146,9 +144,6 @@ class BandPhoneActivity : BaseActivity() {
|
||||||
MMKV.defaultMMKV().removeValueForKey(BZYConstants.MMKV_KEY_PH_TOKEN)
|
MMKV.defaultMMKV().removeValueForKey(BZYConstants.MMKV_KEY_PH_TOKEN)
|
||||||
MMKV.defaultMMKV().removeValueForKey(BZYConstants.MMKV_KEY_TOKEN)
|
MMKV.defaultMMKV().removeValueForKey(BZYConstants.MMKV_KEY_TOKEN)
|
||||||
MMKV.defaultMMKV().removeValueForKey(BZYConstants.MMKV_KEY_CURRENT_NODE)
|
MMKV.defaultMMKV().removeValueForKey(BZYConstants.MMKV_KEY_CURRENT_NODE)
|
||||||
|
|
||||||
//百度埋点完成注册
|
|
||||||
BaiduAction.logAction(ActionType.REGISTER)
|
|
||||||
var intent=Intent(CommonUtils.getApp(), LoginActivity::class.java)
|
var intent=Intent(CommonUtils.getApp(), LoginActivity::class.java)
|
||||||
|
|
||||||
intent.putExtra(BZYConstants.EXTRA_Bind_Account,phoneNumber)
|
intent.putExtra(BZYConstants.EXTRA_Bind_Account,phoneNumber)
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,6 @@ import com.cncat.vpn.service.remote.IRemoteService
|
||||||
import com.yingmao.clash.act.NewMainActivity.Companion.clashBinder
|
import com.yingmao.clash.act.NewMainActivity.Companion.clashBinder
|
||||||
import com.yingmao.clash.act.NewMainActivity.Companion.profileBinder
|
import com.yingmao.clash.act.NewMainActivity.Companion.profileBinder
|
||||||
import com.yingmao.clash.act.NewMainActivity.Companion.subUrl
|
import com.yingmao.clash.act.NewMainActivity.Companion.subUrl
|
||||||
import com.yingmao.clash.act.ProxyModeActivity.ProxyMode
|
|
||||||
import com.yingmao.clash.app.MainApplication
|
import com.yingmao.clash.app.MainApplication
|
||||||
import com.yingmao.clash.fragment.NewAccFragment.Companion.CHECK_NODE_REQUEST_CODE
|
import com.yingmao.clash.fragment.NewAccFragment.Companion.CHECK_NODE_REQUEST_CODE
|
||||||
import com.yingmao.clash.util.Utils
|
import com.yingmao.clash.util.Utils
|
||||||
|
|
@ -657,4 +656,7 @@ class ChangeNodeActivity : BaseActivity(), View.OnClickListener {
|
||||||
intent.setPackage(this.packageName)
|
intent.setPackage(this.packageName)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
enum class ProxyMode {
|
||||||
|
PAC, GLOBAL, PACKAGE
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,606 +0,0 @@
|
||||||
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.cncat.vpn.common.constants.Intents
|
|
||||||
import com.cncat.vpn.common.log.Log
|
|
||||||
import com.cncat.vpn.service.model.Profile
|
|
||||||
import com.cncat.vpn.service.remote.IProfileManager
|
|
||||||
import com.cncat.vpn.service.remote.IRemoteService
|
|
||||||
import com.google.gson.Gson
|
|
||||||
import com.google.gson.JsonParser
|
|
||||||
import com.tencent.mmkv.MMKV
|
|
||||||
import com.yingmao.clash.R
|
|
||||||
import com.yingmao.clash.act.NewMainActivity.Companion.clashBinder
|
|
||||||
import com.yingmao.clash.act.NewMainActivity.Companion.profileBinder
|
|
||||||
import com.yingmao.clash.act.NewMainActivity.Companion.subUrl
|
|
||||||
import com.yingmao.clash.app.MainApplication
|
|
||||||
import com.yingmao.clash.base.BaseActivity
|
|
||||||
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.yingmao.clash.util.Utils
|
|
||||||
import com.yingmao.clash.view.RxToast
|
|
||||||
import com.yingmao.clash.view.adapter.NodeTzListAdapter
|
|
||||||
import com.yingmao.clash.view.dialog.DialogDoMainChoose
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.Job
|
|
||||||
import kotlinx.coroutines.MainScope
|
|
||||||
import kotlinx.coroutines.delay
|
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import kotlinx.coroutines.sync.Semaphore
|
|
||||||
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(2, 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
|
|
||||||
}
|
|
||||||
//缓存订阅地址
|
|
||||||
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) {
|
|
||||||
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()
|
|
||||||
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 {
|
|
||||||
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) {
|
|
||||||
profileBinder?.let { pro ->
|
|
||||||
uuid?.let { uu ->
|
|
||||||
pro.delete(uu)
|
|
||||||
delay(500)
|
|
||||||
setSub2(pro, 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 -> {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -9,7 +9,7 @@ import com.yingmao.clash.net.http.HttpReqType
|
||||||
import com.yingmao.clash.net.http.NetService
|
import com.yingmao.clash.net.http.NetService
|
||||||
|
|
||||||
class ExpensesRecordVM: BaseViewMode() {
|
class ExpensesRecordVM: BaseViewMode() {
|
||||||
fun getExpensesRecord(page :PageInfo){
|
fun getExpensesRecord(page : ExpensesRecordActivity.PageInfo){
|
||||||
val httpApi = NetService.instances.createHttps(HttpApi::class.java)
|
val httpApi = NetService.instances.createHttps(HttpApi::class.java)
|
||||||
val username = MMKV.defaultMMKV().decodeString(BZYConstants.MMKV_KEY_REMEMBER_USERNAME,"")!!
|
val username = MMKV.defaultMMKV().decodeString(BZYConstants.MMKV_KEY_REMEMBER_USERNAME,"")!!
|
||||||
val phToken = MMKV.defaultMMKV().decodeString(BZYConstants.MMKV_KEY_PH_TOKEN,"")!!
|
val phToken = MMKV.defaultMMKV().decodeString(BZYConstants.MMKV_KEY_PH_TOKEN,"")!!
|
||||||
|
|
|
||||||
|
|
@ -79,6 +79,8 @@ import com.yingmao.clash.view.dialog.DialogBandChoose
|
||||||
import com.yingmao.clash.view.dialog.DialogNotice
|
import com.yingmao.clash.view.dialog.DialogNotice
|
||||||
import com.yingmao.clash.view.dialog.RxDialogShapeLoading
|
import com.yingmao.clash.view.dialog.RxDialogShapeLoading
|
||||||
import com.yingmao.clash.vm.MainAtyVM
|
import com.yingmao.clash.vm.MainAtyVM
|
||||||
|
import com.yingmao.clash.webview.BZYWebViewKeFu
|
||||||
|
import com.yingmao.clash.webview.BZYWebViewNormal
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.GlobalScope
|
import kotlinx.coroutines.GlobalScope
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
|
|
@ -776,7 +778,7 @@ class NewMainActivity : BaseActivity() {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun goCheckLogin() {
|
fun goCheckLogin() {
|
||||||
mainAtyVM.checkLogin()
|
mainAtyVM.checkLogin()
|
||||||
}
|
}
|
||||||
private fun showBindAccount() {
|
private fun showBindAccount() {
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,11 @@ package com.yingmao.clash.base
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
import android.content.pm.ActivityInfo
|
import android.content.pm.ActivityInfo
|
||||||
|
import android.content.res.Configuration
|
||||||
|
import android.net.ConnectivityManager
|
||||||
|
import android.net.NetworkCapabilities
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.text.TextUtils
|
import android.text.TextUtils
|
||||||
|
|
@ -14,14 +18,24 @@ import android.view.inputmethod.InputMethodManager
|
||||||
import android.widget.*
|
import android.widget.*
|
||||||
import androidx.annotation.RequiresApi
|
import androidx.annotation.RequiresApi
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import androidx.collection.arraySetOf
|
||||||
|
import androidx.lifecycle.ViewModelProvider
|
||||||
|
import com.orhanobut.logger.Logger
|
||||||
import com.tencent.mmkv.MMKV
|
import com.tencent.mmkv.MMKV
|
||||||
import com.yingmao.clash.BuildConfig
|
import com.yingmao.clash.BuildConfig
|
||||||
|
import com.yingmao.clash.R
|
||||||
import com.yingmao.clash.conf.BZYConstants
|
import com.yingmao.clash.conf.BZYConstants
|
||||||
import com.yingmao.clash.conf.Conf
|
import com.yingmao.clash.conf.Conf
|
||||||
|
import com.cncat.vpn.core.bridge.ClashException
|
||||||
|
import com.cncat.vpn.core.model.TunnelState
|
||||||
|
//import com.yingmao.clash.design.model.DarkMode
|
||||||
|
//import com.yingmao.clash.design.store.UiStore
|
||||||
|
//import com.yingmao.clash.design.ui.DayNight
|
||||||
import com.yingmao.clash.net.http.HttpStatus
|
import com.yingmao.clash.net.http.HttpStatus
|
||||||
import com.yingmao.clash.remote.Broadcasts
|
import com.yingmao.clash.remote.Broadcasts
|
||||||
import com.yingmao.clash.remote.Remote
|
import com.yingmao.clash.remote.Remote
|
||||||
import com.cncat.vpn.service.store.ServiceStore
|
import com.cncat.vpn.service.store.ServiceStore
|
||||||
|
import com.yingmao.clash.util.ApplicationObserver
|
||||||
import com.yingmao.clash.util.StatusBarUtils
|
import com.yingmao.clash.util.StatusBarUtils
|
||||||
import com.yingmao.clash.util.UiStore
|
import com.yingmao.clash.util.UiStore
|
||||||
import com.yingmao.clash.view.dialog.RxDialogShapeLoading
|
import com.yingmao.clash.view.dialog.RxDialogShapeLoading
|
||||||
|
|
@ -29,26 +43,59 @@ import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.MainScope
|
import kotlinx.coroutines.MainScope
|
||||||
import kotlinx.coroutines.cancel
|
import kotlinx.coroutines.cancel
|
||||||
import kotlinx.coroutines.channels.Channel
|
import kotlinx.coroutines.channels.Channel
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
|
|
||||||
@Suppress("DEPRECATION")
|
|
||||||
open class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope(), Broadcasts.Observer {
|
open class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope(), Broadcasts.Observer {
|
||||||
|
lateinit var titleBar: RelativeLayout
|
||||||
|
lateinit var backIv: ImageView
|
||||||
|
lateinit var title: TextView
|
||||||
|
lateinit var more_tv: TextView
|
||||||
protected val uiStore by lazy { UiStore(this) }
|
protected val uiStore by lazy { UiStore(this) }
|
||||||
protected val events = Channel<Event>(Channel.UNLIMITED)
|
protected val events = Channel<Event>(Channel.UNLIMITED)
|
||||||
private var baseLoading: RxDialogShapeLoading? = null
|
|
||||||
|
// private var dayNight: DayNight = DayNight.Day
|
||||||
|
var baseLoading: RxDialogShapeLoading? = null
|
||||||
val serStore by lazy { ServiceStore(this) }
|
val serStore by lazy { ServiceStore(this) }
|
||||||
|
|
||||||
@RequiresApi(Build.VERSION_CODES.M)
|
companion object {
|
||||||
|
// var switchFinshSet: MutableSet<String>? = null
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed class RequestTunnel {
|
||||||
|
object ReloadAll : RequestTunnel()
|
||||||
|
object ReLaunch : RequestTunnel()
|
||||||
|
|
||||||
|
data class PatchMode(val mode: TunnelState.Mode?) : RequestTunnel()
|
||||||
|
data class Reload(val index: Int) : RequestTunnel()
|
||||||
|
data class Select(val index: Int, val name: String) : RequestTunnel()
|
||||||
|
data class UrlTest(val index: Int) : RequestTunnel()
|
||||||
|
}
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; //竖屏
|
requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT; //竖屏
|
||||||
StatusBarUtils.with(this).init()
|
StatusBarUtils.with(this).init()
|
||||||
window.decorView.systemUiVisibility =
|
window.decorView.systemUiVisibility =
|
||||||
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
|
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun setContentView(layoutResID: Int) {
|
||||||
|
val baseView = View.inflate(this, R.layout.activity_base, null)
|
||||||
|
titleBar = baseView.findViewById(R.id.rl_title_bar)
|
||||||
|
backIv = baseView.findViewById(R.id.iv_back)
|
||||||
|
title = baseView.findViewById(R.id.tv_title)
|
||||||
|
more_tv = baseView.findViewById(R.id.tv_more)
|
||||||
|
val container = baseView.findViewById<FrameLayout>(R.id.fl_container)
|
||||||
|
val params = FrameLayout.LayoutParams(
|
||||||
|
FrameLayout.LayoutParams.MATCH_PARENT,
|
||||||
|
FrameLayout.LayoutParams.MATCH_PARENT
|
||||||
|
)
|
||||||
|
val view = View.inflate(this, layoutResID, null)
|
||||||
|
container.addView(view, params)
|
||||||
|
super.setContentView(baseView)
|
||||||
|
}
|
||||||
|
|
||||||
override fun onStart() {
|
override fun onStart() {
|
||||||
super.onStart()
|
super.onStart()
|
||||||
|
|
@ -67,6 +114,33 @@ open class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope(), Br
|
||||||
cancel()
|
cancel()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun showTitleBar(titleText: String) {
|
||||||
|
titleBar.visibility = View.VISIBLE
|
||||||
|
title.text = titleText
|
||||||
|
backIv.setOnClickListener {
|
||||||
|
onBackPressed()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun showTitleBar(titleText: String, intent: Intent) {
|
||||||
|
titleBar.visibility = View.VISIBLE
|
||||||
|
title.text = titleText
|
||||||
|
backIv.setOnClickListener {
|
||||||
|
onBackPressed()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setMoreBar(moreInfo: String, listener: View.OnClickListener) {
|
||||||
|
more_tv.visibility = View.VISIBLE
|
||||||
|
more_tv.text = moreInfo
|
||||||
|
more_tv.setOnClickListener(listener)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun updateMoreBar(moreInfo: String) {
|
||||||
|
more_tv.text = moreInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
open fun observe(activity: BaseActivity, viewMode: BaseViewMode) {
|
open fun observe(activity: BaseActivity, viewMode: BaseViewMode) {
|
||||||
viewMode.statusData.observe(activity) {
|
viewMode.statusData.observe(activity) {
|
||||||
when (it) {
|
when (it) {
|
||||||
|
|
@ -93,14 +167,16 @@ open class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope(), Br
|
||||||
|
|
||||||
@SuppressLint("ClickableViewAccessibility")
|
@SuppressLint("ClickableViewAccessibility")
|
||||||
open fun setupUI(view: View) {
|
open fun setupUI(view: View) {
|
||||||
|
// Set up touch listener for non-text box views to hide keyboard.
|
||||||
if (view !is EditText) view.setOnTouchListener { _, _ ->
|
if (view !is EditText) view.setOnTouchListener { _, _ ->
|
||||||
hideSoftKeyboard(this@BaseActivity)
|
hideSoftKeyboard(this@BaseActivity)
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//If a layout container, iterate over children and seed recursion.
|
||||||
if (view is ViewGroup) {
|
if (view is ViewGroup) {
|
||||||
for (i in 0 until view.childCount) {
|
for (i in 0 until (view as ViewGroup).childCount) {
|
||||||
val innerView: View = view.getChildAt(i)
|
val innerView: View = (view as ViewGroup).getChildAt(i)
|
||||||
setupUI(innerView)
|
setupUI(innerView)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -114,6 +190,24 @@ open class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope(), Br
|
||||||
activity.currentFocus!!.windowToken, 0
|
activity.currentFocus!!.windowToken, 0
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onConfigurationChanged(newConfig: Configuration) {
|
||||||
|
super.onConfigurationChanged(newConfig)
|
||||||
|
// if (queryDayNight(newConfig) != dayNight) {
|
||||||
|
// ApplicationObserver.createdActivities.forEach {
|
||||||
|
// it.recreate()
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
// private fun queryDayNight(config: Configuration = resources.configuration): DayNight {
|
||||||
|
// return when (uiStore.darkMode) {
|
||||||
|
// DarkMode.Auto -> if (config.uiMode and Configuration.UI_MODE_NIGHT_MASK == Configuration.UI_MODE_NIGHT_YES) DayNight.Night else DayNight.Day
|
||||||
|
// DarkMode.ForceLight -> DayNight.Day
|
||||||
|
// DarkMode.ForceDark -> DayNight.Night
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
override fun onProfileChanged() {
|
override fun onProfileChanged() {
|
||||||
events.trySend(Event.ProfileChanged)
|
events.trySend(Event.ProfileChanged)
|
||||||
}
|
}
|
||||||
|
|
@ -140,6 +234,12 @@ open class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope(), Br
|
||||||
|
|
||||||
override fun onStopped(cause: String?) {
|
override fun onStopped(cause: String?) {
|
||||||
events.trySend(Event.ClashStop)
|
events.trySend(Event.ClashStop)
|
||||||
|
|
||||||
|
// if (cause != null && activityStarted) {
|
||||||
|
// launch {
|
||||||
|
// design?.showExceptionToast(ClashException(cause))
|
||||||
|
// }
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class Event {
|
enum class Event {
|
||||||
|
|
@ -170,6 +270,63 @@ open class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope(), Br
|
||||||
baseLoading?.cancel()
|
baseLoading?.cancel()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun selectServer() {
|
||||||
|
val mmkv = MMKV.defaultMMKV()
|
||||||
|
val routerHost = mmkv.decodeStringSet(BZYConstants.MMKV_KEY_ROUTER_HOST, HashSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
@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
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@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
|
@Synchronized
|
||||||
fun switchServer2(): Boolean {
|
fun switchServer2(): Boolean {
|
||||||
var isChange = false
|
var isChange = false
|
||||||
|
|
@ -178,38 +335,71 @@ open class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope(), Br
|
||||||
mmkv.decodeString(BZYConstants.MMKV_KEY_CURRENT_HOST, BuildConfig.service_url)
|
mmkv.decodeString(BZYConstants.MMKV_KEY_CURRENT_HOST, BuildConfig.service_url)
|
||||||
var newUrlString = originalUrl
|
var newUrlString = originalUrl
|
||||||
val routerHost = mmkv.decodeStringSet(BZYConstants.MMKV_KEY_ROUTER_HOST, HashSet())
|
val routerHost = mmkv.decodeStringSet(BZYConstants.MMKV_KEY_ROUTER_HOST, HashSet())
|
||||||
val switchFinishSet = mmkv.decodeStringSet(BZYConstants.MMKV_KEY_Switch_Finsh_Set, HashSet())
|
var switchFinshSet = mmkv.decodeStringSet(BZYConstants.MMKV_KEY_Switch_Finsh_Set, HashSet())
|
||||||
routerHost?.let {
|
routerHost?.let {
|
||||||
|
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
|
// if (!isNetworkAvailable(this@BaseActivity)){
|
||||||
|
// return isChange
|
||||||
|
// }
|
||||||
|
// }
|
||||||
if (it.isEmpty()) {
|
if (it.isEmpty()) {
|
||||||
Log.d(Conf.TAG, "routerHost isEmpty")
|
Log.d(Conf.TAG, "routerHost isEmpty")
|
||||||
return false
|
return isChange
|
||||||
}
|
}
|
||||||
com.cncat.vpn.common.log.Log.d("switchFinshSet.size==>${switchFinishSet?.size!!} , routerHost.size==>${routerHost.size}")
|
com.cncat.vpn.common.log.Log.d("switchFinshSet.size==>${switchFinshSet?.size!!} , routerHost.size==>${routerHost.size}")
|
||||||
//次数已满
|
//次数已满
|
||||||
if (switchFinishSet.size >= routerHost.size) {
|
if (switchFinshSet?.size!! >= routerHost.size) {
|
||||||
return false
|
return isChange
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.d(Conf.TAG, "routerHost not empty")
|
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) {
|
for (url in it) {
|
||||||
|
|
||||||
if (url == originalUrl) {
|
if (url == originalUrl) {
|
||||||
switchFinishSet.add(url)
|
switchFinshSet?.add(url)
|
||||||
mmkv.encode(BZYConstants.MMKV_KEY_Switch_Finsh_Set, switchFinishSet)
|
mmkv.encode(BZYConstants.MMKV_KEY_Switch_Finsh_Set, switchFinshSet)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if (switchFinishSet.contains(url)) {
|
if (switchFinshSet?.contains(url) == true) {
|
||||||
continue
|
continue
|
||||||
} else {
|
} else {
|
||||||
isChange = true
|
isChange = true
|
||||||
Log.e("Retry", "切换到新url:$url")
|
android.util.Log.e("Retry", "切换到新url:$url")
|
||||||
newUrlString = url
|
newUrlString = url
|
||||||
switchFinishSet.add(newUrlString)
|
switchFinshSet?.add(newUrlString)
|
||||||
mmkv.encode(BZYConstants.MMKV_KEY_Switch_Finsh_Set, switchFinishSet)
|
mmkv.encode(BZYConstants.MMKV_KEY_Switch_Finsh_Set, switchFinshSet)
|
||||||
|
// mmkv.encode(BZYConstants.MMKV_KEY_OLD_CURRENT_HOST, newUrlString)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// mmkv.encode(BZYConstants.MMKV_KEY_ROUTER_HOST, routerHost)
|
||||||
mmkv.encode(BZYConstants.MMKV_KEY_CURRENT_HOST, newUrlString)
|
mmkv.encode(BZYConstants.MMKV_KEY_CURRENT_HOST, newUrlString)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ class Conf {
|
||||||
return context?.getString(R.string.app_name_taizi)!!
|
return context?.getString(R.string.app_name_taizi)!!
|
||||||
} else {
|
} else {
|
||||||
if (BuildConfig.is_ym) {
|
if (BuildConfig.is_ym) {
|
||||||
return context?.getString(R.string.WFApiPort)!!
|
return context?.getString(R.string.app_name_gz)!!
|
||||||
} else {
|
} else {
|
||||||
return context?.getString(R.string.app_name)!!
|
return context?.getString(R.string.app_name)!!
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ import com.yingmao.clash.R
|
||||||
import com.yingmao.clash.act.NewMainActivity
|
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.NewMainActivity.Companion.profileBinder
|
||||||
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
|
||||||
|
|
@ -43,6 +43,7 @@ import com.yingmao.clash.net.http.entity.AppStartupStatus
|
||||||
import com.yingmao.clash.service.ConnectionService
|
import com.yingmao.clash.service.ConnectionService
|
||||||
import com.yingmao.clash.util.ActivityResultLifecycle
|
import com.yingmao.clash.util.ActivityResultLifecycle
|
||||||
import com.yingmao.clash.util.CommonUtils
|
import com.yingmao.clash.util.CommonUtils
|
||||||
|
import com.yingmao.clash.util.Utils
|
||||||
import com.yingmao.clash.util.startClashService
|
import com.yingmao.clash.util.startClashService
|
||||||
import com.yingmao.clash.util.stopClashService
|
import com.yingmao.clash.util.stopClashService
|
||||||
import com.yingmao.clash.view.RxToast
|
import com.yingmao.clash.view.RxToast
|
||||||
|
|
@ -89,7 +90,7 @@ class NewAccFragment : BaseFragment(), CoroutineScope by CoroutineScope(Dispatch
|
||||||
// var currentNode: Profile? = null
|
// var currentNode: Profile? = null
|
||||||
private var reConnection = false
|
private var reConnection = false
|
||||||
private var connectId=-1
|
private var connectId=-1
|
||||||
|
private var baseLoading: RxDialogShapeLoading? = null
|
||||||
override fun init(
|
override fun init(
|
||||||
titleBarRl: RelativeLayout,
|
titleBarRl: RelativeLayout,
|
||||||
backIv: ImageView,
|
backIv: ImageView,
|
||||||
|
|
@ -182,7 +183,7 @@ class NewAccFragment : BaseFragment(), CoroutineScope by CoroutineScope(Dispatch
|
||||||
rxDialogSureCancel.show()
|
rxDialogSureCancel.show()
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
startClash()
|
startClash(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -220,25 +221,21 @@ class NewAccFragment : BaseFragment(), CoroutineScope by CoroutineScope(Dispatch
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun startClash() {
|
private fun startClash(isStart:Boolean) {
|
||||||
if (checkExpire()) {
|
|
||||||
if (isAdded) {
|
|
||||||
RxToast.info(resources.getString(R.string.AccountExpired))
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
launch {
|
launch {
|
||||||
NewMainActivity.profileBinder?.let { pm ->
|
if(isStart){
|
||||||
|
delay(2000)
|
||||||
|
}
|
||||||
|
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: 未选择")
|
Log.d("startClash: 未选择")
|
||||||
val pro = pm.queryAll().find {
|
val pro = pm.queryAll().find {
|
||||||
it.name == Conf.getClashConfName(this@NewAccFragment.context)
|
it.name == Conf.getClashConfName(this@NewAccFragment.context)
|
||||||
}
|
}
|
||||||
|
|
||||||
pro?.let { profile ->
|
pro?.let { profile ->
|
||||||
com.cncat.vpn.common.log.Log.d("new setactive name " + profile.name)
|
Log.d("new setactive name " + profile.name)
|
||||||
pm.setActive(profile)
|
pm.setActive(profile)
|
||||||
|
|
||||||
newUuid = profile.uuid.toString();
|
newUuid = profile.uuid.toString();
|
||||||
|
|
@ -267,7 +264,6 @@ class NewAccFragment : BaseFragment(), CoroutineScope by CoroutineScope(Dispatch
|
||||||
stateChanged(Clash_Starting, true)
|
stateChanged(Clash_Starting, true)
|
||||||
context?.startClashService()
|
context?.startClashService()
|
||||||
accelerateViewModel.appStartupStatus()
|
accelerateViewModel.appStartupStatus()
|
||||||
// clashRunning = true
|
|
||||||
}
|
}
|
||||||
launch(Dispatchers.Main){
|
launch(Dispatchers.Main){
|
||||||
lottieView.playAnimation()
|
lottieView.playAnimation()
|
||||||
|
|
@ -285,6 +281,9 @@ class NewAccFragment : BaseFragment(), CoroutineScope by CoroutineScope(Dispatch
|
||||||
stop_u_timer()
|
stop_u_timer()
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
}
|
}
|
||||||
|
withContext(Dispatchers.Main){
|
||||||
|
hideLoading()
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -340,7 +339,7 @@ class NewAccFragment : BaseFragment(), CoroutineScope by CoroutineScope(Dispatch
|
||||||
|
|
||||||
Intents.ACTION_CLASH_REQUEST_STOP -> {
|
Intents.ACTION_CLASH_REQUEST_STOP -> {
|
||||||
// clashRunning = false
|
// clashRunning = false
|
||||||
com.cncat.vpn.common.log.Log.d("ACTION_CLASH_REQUEST_STOP")
|
Log.d("ACTION_CLASH_REQUEST_STOP")
|
||||||
if (::rxDialogShapeLoading.isInitialized) {
|
if (::rxDialogShapeLoading.isInitialized) {
|
||||||
if (!rxDialogShapeLoading.isShowing) {
|
if (!rxDialogShapeLoading.isShowing) {
|
||||||
if (isAdded) {
|
if (isAdded) {
|
||||||
|
|
@ -431,7 +430,7 @@ class NewAccFragment : BaseFragment(), CoroutineScope by CoroutineScope(Dispatch
|
||||||
if (clashRunning) {
|
if (clashRunning) {
|
||||||
Log.d("clashRunning $clashRunning")
|
Log.d("clashRunning $clashRunning")
|
||||||
} else {
|
} else {
|
||||||
startClash()
|
startClash(false)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (::rxDialogShapeLoading.isInitialized || rxDialogShapeLoading.isShowing) {
|
if (::rxDialogShapeLoading.isInitialized || rxDialogShapeLoading.isShowing) {
|
||||||
|
|
@ -452,9 +451,7 @@ class NewAccFragment : BaseFragment(), CoroutineScope by CoroutineScope(Dispatch
|
||||||
checkGlo()
|
checkGlo()
|
||||||
}?.run {
|
}?.run {
|
||||||
if (is_runing == true && !clashRunning) {
|
if (is_runing == true && !clashRunning) {
|
||||||
startClash()
|
startClash(false)
|
||||||
} else {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (requestCode == Proxy_Mode_REQUEST_CODE) {
|
} else if (requestCode == Proxy_Mode_REQUEST_CODE) {
|
||||||
|
|
@ -528,7 +525,7 @@ class NewAccFragment : BaseFragment(), CoroutineScope by CoroutineScope(Dispatch
|
||||||
val validPeriod = MMKV.defaultMMKV().decodeLong(BZYConstants.MMKV_KEY_VPN_VALID_PERIOD)
|
val validPeriod = MMKV.defaultMMKV().decodeLong(BZYConstants.MMKV_KEY_VPN_VALID_PERIOD)
|
||||||
if (validPeriod > 0) {
|
if (validPeriod > 0) {
|
||||||
var nowTime = System.currentTimeMillis();
|
var nowTime = System.currentTimeMillis();
|
||||||
com.cncat.vpn.common.log.Log.d("validPeriod==>$validPeriod, nowTime==>$nowTime")
|
Log.d("validPeriod==>$validPeriod, nowTime==>$nowTime")
|
||||||
if (validPeriod >= nowTime) {
|
if (validPeriod >= nowTime) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
@ -757,12 +754,12 @@ class NewAccFragment : BaseFragment(), CoroutineScope by CoroutineScope(Dispatch
|
||||||
if (clashRunning) {
|
if (clashRunning) {
|
||||||
Log.d("clashRunning $clashRunning")
|
Log.d("clashRunning $clashRunning")
|
||||||
} else {
|
} else {
|
||||||
startClash()
|
startClash(false)
|
||||||
}
|
}
|
||||||
checkGlo()
|
checkGlo()
|
||||||
}?.run {
|
}?.run {
|
||||||
if (isRunning == true && !clashRunning) {
|
if (isRunning == true && !clashRunning) {
|
||||||
startClash()
|
startClash(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -791,10 +788,4 @@ class NewAccFragment : BaseFragment(), CoroutineScope by CoroutineScope(Dispatch
|
||||||
baseLoading?.cancel()
|
baseLoading?.cancel()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private fun goNewRecharge() {
|
|
||||||
if (activity != null) {
|
|
||||||
val newUiMain = activity as NewMainActivity
|
|
||||||
newUiMain.goBackupRechargeWeb()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
@ -389,18 +389,4 @@ class MainAtyVM : PublicViewMode() {
|
||||||
val requestBody: RequestBody = jsonString.toRequestBody("application/json; charset=utf-8".toMediaType())
|
val requestBody: RequestBody = jsonString.toRequestBody("application/json; charset=utf-8".toMediaType())
|
||||||
doAsync(HttpReqType.Report){httpApi.getReport(paramsToken,requestBody)}
|
doAsync(HttpReqType.Report){httpApi.getReport(paramsToken,requestBody)}
|
||||||
}
|
}
|
||||||
fun getExpensesRecord(page : NewMainActivity.PageInfo){
|
|
||||||
val httpApi = NetService.instances.createHttps(HttpApi::class.java)
|
|
||||||
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)!!
|
|
||||||
val params = hashMapOf<String,String>(
|
|
||||||
"phoneNumber" to username,
|
|
||||||
"userId" to userId,
|
|
||||||
"phToken" to phToken,
|
|
||||||
"pageno" to "${page.page}",
|
|
||||||
"pageSize" to "5",
|
|
||||||
)
|
|
||||||
doAsync(HttpReqType.EXPENSES_RECORD){httpApi.phOrderList(params)}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,307 @@
|
||||||
|
package com.yingmao.clash.webview
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
import android.content.Intent
|
||||||
|
import android.content.pm.ActivityInfo
|
||||||
|
import android.net.Uri
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.os.CountDownTimer
|
||||||
|
import android.text.TextUtils
|
||||||
|
import android.view.View
|
||||||
|
import android.webkit.WebChromeClient
|
||||||
|
import android.webkit.WebView
|
||||||
|
import android.webkit.WebViewClient
|
||||||
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import androidx.lifecycle.ViewModelProvider
|
||||||
|
import com.tencent.mmkv.MMKV
|
||||||
|
import com.yingmao.clash.BuildConfig
|
||||||
|
import com.yingmao.clash.R
|
||||||
|
import com.cncat.vpn.common.log.Log
|
||||||
|
import com.yingmao.clash.base.BaseActivity
|
||||||
|
import com.yingmao.clash.conf.BZYConstants
|
||||||
|
import com.yingmao.clash.listener.AsyncBodyCallback
|
||||||
|
import com.yingmao.clash.util.StatusBarUtils
|
||||||
|
import com.yingmao.clash.vm.LoginAtyVM
|
||||||
|
import com.yingmao.clash.vm.WebViewAtyVM
|
||||||
|
import java.net.URLDecoder
|
||||||
|
import java.net.URLEncoder
|
||||||
|
|
||||||
|
class BZYWebViewKeFu : BaseActivity() {
|
||||||
|
private lateinit var webView: WebView
|
||||||
|
private lateinit var webViewAtyVM: WebViewAtyVM
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
setContentView(R.layout.bzy_kefu_webview_layout)
|
||||||
|
|
||||||
|
// requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT; //竖屏
|
||||||
|
// StatusBarUtils.with(this).init()
|
||||||
|
webViewAtyVM = ViewModelProvider(this).get(WebViewAtyVM::class.java)
|
||||||
|
observe(this, webViewAtyVM)
|
||||||
|
|
||||||
|
initView()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun initView() {
|
||||||
|
findViewById<View>(R.id.iv_back).setOnClickListener { finish() }
|
||||||
|
webView = findViewById(R.id.webView)
|
||||||
|
setWebView()
|
||||||
|
countDown()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun countDown() {
|
||||||
|
val timer = object : CountDownTimer(5000, 1000) {
|
||||||
|
override fun onTick(millisUntilFinished: Long) {
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onFinish() {
|
||||||
|
Log.d("onFinish")
|
||||||
|
webView.evaluateJavascript("updateStatus()", null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
timer.start()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setWebView() {
|
||||||
|
Log.d("setWebView 1")
|
||||||
|
WebView.setWebContentsDebuggingEnabled(true)
|
||||||
|
Log.d("setWebView 2")
|
||||||
|
val settings = webView.settings
|
||||||
|
settings.javaScriptEnabled = true
|
||||||
|
settings.domStorageEnabled = true
|
||||||
|
settings.allowFileAccess = true
|
||||||
|
Log.d("setWebView 4")
|
||||||
|
webView.webViewClient = object : WebViewClient() {
|
||||||
|
override fun onLoadResource(view: WebView, url: String) {
|
||||||
|
if (url.contains("https://image.crisp.chat/avatar/website") || url.contains("https://client.crisp.chat/static/javascripts/locales")) {
|
||||||
|
webView.evaluateJavascript("updateStatus()", null);
|
||||||
|
}
|
||||||
|
// Log.e("data", "==$url")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Log.d("setWebView 5")
|
||||||
|
// webView.webChromeClient = object : WebChromeClient() {
|
||||||
|
// override fun onProgressChanged(view: WebView?, newProgress: Int) {
|
||||||
|
//// Log.e("data", "==$newProgress")
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
when {
|
||||||
|
BuildConfig.is_ym -> {
|
||||||
|
ymKefu()
|
||||||
|
}
|
||||||
|
|
||||||
|
BuildConfig.is_tz -> {
|
||||||
|
getTzKefu()
|
||||||
|
}
|
||||||
|
|
||||||
|
BuildConfig.is_yunti -> {
|
||||||
|
getYunTiKefu()
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> {
|
||||||
|
getBzyKefu()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private var kefuHost = ""
|
||||||
|
private fun ymKefu() {
|
||||||
|
val userName = MMKV.defaultMMKV().decodeString(BZYConstants.MMKV_KEY_REMEMBER_USERNAME, "")
|
||||||
|
var enNmae = URLEncoder.encode(userName, "UTF-8")
|
||||||
|
Log.d("enNmae==>${enNmae}")
|
||||||
|
if (TextUtils.isEmpty(kefuHost)) {
|
||||||
|
var mmkvHost = MMKV.defaultMMKV()
|
||||||
|
.decodeString(BZYConstants.MMKV_KEY_KEFU_HOST, "")
|
||||||
|
// com.cncat.vpn.common.log.Log.d("mmkvHost kf ==>${mmkvHost}")
|
||||||
|
webViewAtyVM.getYmKefuHost(object : AsyncBodyCallback {
|
||||||
|
override suspend fun suc(str: String) {
|
||||||
|
// com.cncat.vpn.common.log.Log.d("str==>${str}")
|
||||||
|
if (str != mmkvHost) {
|
||||||
|
MMKV.defaultMMKV()
|
||||||
|
.encode(BZYConstants.MMKV_KEY_KEFU_HOST, str)
|
||||||
|
}
|
||||||
|
// mmkvHost = str
|
||||||
|
kefuHost = str
|
||||||
|
startActivity(
|
||||||
|
Intent(
|
||||||
|
Intent.ACTION_VIEW,
|
||||||
|
Uri.parse(str + "&app_account=${enNmae}")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun err() {
|
||||||
|
if (!TextUtils.isEmpty(mmkvHost)) {
|
||||||
|
startActivity(
|
||||||
|
Intent(
|
||||||
|
Intent.ACTION_VIEW,
|
||||||
|
Uri.parse(mmkvHost + "&app_account=${enNmae}")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
startActivity(
|
||||||
|
Intent(
|
||||||
|
Intent.ACTION_VIEW,
|
||||||
|
Uri.parse(kefuHost + "&app_account=${enNmae}")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getBzyKefu() {
|
||||||
|
val userName = MMKV.defaultMMKV().decodeString(BZYConstants.MMKV_KEY_REMEMBER_USERNAME, "")
|
||||||
|
var enNmae = URLEncoder.encode(userName, "UTF-8")
|
||||||
|
Log.d("enNmae==>${enNmae}")
|
||||||
|
if (TextUtils.isEmpty(kefuHost)) {
|
||||||
|
var mmkvHost = MMKV.defaultMMKV()
|
||||||
|
.decodeString(BZYConstants.MMKV_KEY_KEFU_HOST, "")
|
||||||
|
// com.cncat.vpn.common.log.Log.d("mmkvHost kf ==>${mmkvHost}")
|
||||||
|
webViewAtyVM.getBzyKefuHost(object : AsyncBodyCallback {
|
||||||
|
override suspend fun suc(str: String) {
|
||||||
|
// com.cncat.vpn.common.log.Log.d("str==>${str}")
|
||||||
|
if (str != mmkvHost) {
|
||||||
|
MMKV.defaultMMKV()
|
||||||
|
.encode(BZYConstants.MMKV_KEY_KEFU_HOST, str)
|
||||||
|
}
|
||||||
|
// mmkvHost = str
|
||||||
|
kefuHost = str
|
||||||
|
startActivity(
|
||||||
|
Intent(
|
||||||
|
Intent.ACTION_VIEW,
|
||||||
|
Uri.parse(str + "&app_account=${enNmae}")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun err() {
|
||||||
|
if (!TextUtils.isEmpty(mmkvHost)) {
|
||||||
|
startActivity(
|
||||||
|
Intent(
|
||||||
|
Intent.ACTION_VIEW,
|
||||||
|
Uri.parse(mmkvHost + "&app_account=${enNmae}")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
startActivity(
|
||||||
|
Intent(
|
||||||
|
Intent.ACTION_VIEW,
|
||||||
|
Uri.parse(kefuHost + "&app_account=${enNmae}")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getTzKefu() {
|
||||||
|
val userName = MMKV.defaultMMKV().decodeString(BZYConstants.MMKV_KEY_REMEMBER_USERNAME, "")
|
||||||
|
var enNmae = URLEncoder.encode(userName, "UTF-8")
|
||||||
|
Log.d("enNmae==>${enNmae}")
|
||||||
|
if (TextUtils.isEmpty(kefuHost)) {
|
||||||
|
var mmkvHost = MMKV.defaultMMKV()
|
||||||
|
.decodeString(BZYConstants.MMKV_KEY_KEFU_HOST, "")
|
||||||
|
// com.cncat.vpn.common.log.Log.d("mmkvHost kf ==>${mmkvHost}")
|
||||||
|
webViewAtyVM.getTzKefuHost(object : AsyncBodyCallback {
|
||||||
|
override suspend fun suc(str: String) {
|
||||||
|
// com.cncat.vpn.common.log.Log.d("str==>${str}")
|
||||||
|
if (str != mmkvHost) {
|
||||||
|
MMKV.defaultMMKV()
|
||||||
|
.encode(BZYConstants.MMKV_KEY_KEFU_HOST, str)
|
||||||
|
}
|
||||||
|
// mmkvHost = str
|
||||||
|
kefuHost = str
|
||||||
|
startActivity(
|
||||||
|
Intent(
|
||||||
|
Intent.ACTION_VIEW,
|
||||||
|
Uri.parse(str + "&app_account=${enNmae}")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun err() {
|
||||||
|
if (!TextUtils.isEmpty(mmkvHost)) {
|
||||||
|
startActivity(
|
||||||
|
Intent(
|
||||||
|
Intent.ACTION_VIEW,
|
||||||
|
Uri.parse(mmkvHost + "&app_account=${enNmae}")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
startActivity(
|
||||||
|
Intent(
|
||||||
|
Intent.ACTION_VIEW,
|
||||||
|
Uri.parse(kefuHost + "&app_account=${enNmae}")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getYunTiKefu() {
|
||||||
|
val userName = MMKV.defaultMMKV().decodeString(BZYConstants.MMKV_KEY_REMEMBER_USERNAME, "")
|
||||||
|
var enNmae = URLEncoder.encode(userName, "UTF-8")
|
||||||
|
Log.d("enNmae==>${enNmae}")
|
||||||
|
if (TextUtils.isEmpty(kefuHost)) {
|
||||||
|
var mmkvHost = MMKV.defaultMMKV()
|
||||||
|
.decodeString(BZYConstants.MMKV_KEY_KEFU_HOST, "")
|
||||||
|
// com.cncat.vpn.common.log.Log.d("mmkvHost kf ==>${mmkvHost}")
|
||||||
|
webViewAtyVM.getYunTiKefuHost(object : AsyncBodyCallback {
|
||||||
|
override suspend fun suc(str: String) {
|
||||||
|
// com.cncat.vpn.common.log.Log.d("str==>${str}")
|
||||||
|
if (str != mmkvHost) {
|
||||||
|
MMKV.defaultMMKV()
|
||||||
|
.encode(BZYConstants.MMKV_KEY_KEFU_HOST, str)
|
||||||
|
}
|
||||||
|
kefuHost = str
|
||||||
|
startActivity(
|
||||||
|
Intent(
|
||||||
|
Intent.ACTION_VIEW,
|
||||||
|
Uri.parse(str + "&app_account=${enNmae}")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun err() {
|
||||||
|
if (!TextUtils.isEmpty(mmkvHost)) {
|
||||||
|
startActivity(
|
||||||
|
Intent(
|
||||||
|
Intent.ACTION_VIEW,
|
||||||
|
Uri.parse(mmkvHost + "&app_account=${enNmae}")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
startActivity(
|
||||||
|
Intent(
|
||||||
|
Intent.ACTION_VIEW,
|
||||||
|
Uri.parse(kefuHost + "&app_account=${enNmae}")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,65 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
>
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:gravity="center"
|
||||||
|
android:id="@+id/rl_title_bar"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="60dp"
|
||||||
|
android:layout_marginTop="30dp"
|
||||||
|
android:visibility="gone"
|
||||||
|
>
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_centerVertical="true"
|
||||||
|
android:id="@+id/iv_back"
|
||||||
|
android:layout_width="30dp"
|
||||||
|
android:layout_height="30dp"
|
||||||
|
android:src="@drawable/ic_s_back" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tv_title"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_toStartOf="@+id/iv_more"
|
||||||
|
android:layout_toEndOf="@+id/iv_back"
|
||||||
|
android:gravity="center"
|
||||||
|
android:text="@string/expenses_record"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
android:textSize="21sp"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/iv_more"
|
||||||
|
tools:ignore="ContentDescription"
|
||||||
|
android:layout_width="30dp"
|
||||||
|
android:layout_height="30dp"
|
||||||
|
android:layout_alignParentEnd="true"
|
||||||
|
android:src="@drawable/ic_s_back"
|
||||||
|
android:visibility="invisible" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tv_more"
|
||||||
|
tools:ignore="ContentDescription"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="30dp"
|
||||||
|
android:text="线路测试"
|
||||||
|
android:layout_marginRight="20dp"
|
||||||
|
android:layout_centerVertical="true"
|
||||||
|
android:layout_centerHorizontal="true"
|
||||||
|
android:gravity="center"
|
||||||
|
android:textColor="@color/yellow"
|
||||||
|
android:layout_alignParentEnd="true"
|
||||||
|
android:visibility="invisible" />
|
||||||
|
</RelativeLayout>
|
||||||
|
<FrameLayout
|
||||||
|
android:id="@+id/fl_container"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_below="@+id/rl_title_bar"
|
||||||
|
/>
|
||||||
|
</RelativeLayout>
|
||||||
|
|
@ -0,0 +1,40 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="@drawable/ic_index_bg">
|
||||||
|
<RelativeLayout
|
||||||
|
android:layout_marginTop="20dp"
|
||||||
|
android:id="@+id/rl_title_bar"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="60dp">
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tv_title"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:gravity="center"
|
||||||
|
android:text=""
|
||||||
|
android:textColor="@color/white"
|
||||||
|
android:textSize="21sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
/>
|
||||||
|
<ImageView
|
||||||
|
android:layout_centerVertical="true"
|
||||||
|
android:id="@+id/iv_back"
|
||||||
|
android:layout_width="30dp"
|
||||||
|
android:layout_height="30dp"
|
||||||
|
android:src="@drawable/ic_s_back"
|
||||||
|
android:contentDescription="@string/kefu"
|
||||||
|
/>
|
||||||
|
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
|
<WebView
|
||||||
|
android:layout_below="@+id/rl_title_bar"
|
||||||
|
android:id="@+id/webView"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="@color/main_bg" />
|
||||||
|
|
||||||
|
|
||||||
|
</RelativeLayout>
|
||||||
|
|
@ -106,6 +106,8 @@ subprojects {
|
||||||
buildConfigField("boolean", "PREMIUM", "Boolean.parseBoolean(\"false\")")
|
buildConfigField("boolean", "PREMIUM", "Boolean.parseBoolean(\"false\")")
|
||||||
buildConfigField("boolean", "is_back_cn", "false")
|
buildConfigField("boolean", "is_back_cn", "false")
|
||||||
buildConfigField("boolean", "is_ym", "true")
|
buildConfigField("boolean", "is_ym", "true")
|
||||||
|
buildConfigField("boolean", "is_tz", "false")
|
||||||
|
buildConfigField("boolean", "is_yunti", "false")
|
||||||
buildConfigField("String", "applicationId", "\"com.yingmao.clash\"")
|
buildConfigField("String", "applicationId", "\"com.yingmao.clash\"")
|
||||||
buildConfigField("String", "service_url", "\"https://api.ymvpnpro.cc:8700\"")
|
buildConfigField("String", "service_url", "\"https://api.ymvpnpro.cc:8700\"")
|
||||||
buildConfigField("boolean", "is_free", "false")
|
buildConfigField("boolean", "is_free", "false")
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue