diff --git a/app/build.gradle.kts b/app/build.gradle.kts index ec88bad..d27ecea 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -25,7 +25,7 @@ dependencies { implementation(libs.rikkax.multiprocess) val commonAar = file("libs/common.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 oss = file("libs/oss-android-sdk-2.9.19.aar") if (oss.exists()) { @@ -45,8 +45,8 @@ dependencies { println("core.aar does not exist") } - if (hideawayEar.exists()) { - implementation(files(hideawayEar)) + if (hideapiAar.exists()) { + implementation(files(hideapiAar)) } else { println("hideapi.aar does not exist") } @@ -58,14 +58,18 @@ dependencies { implementation(libs.kotlin.coroutine) implementation(libs.androidx.core) +// implementation(libs.androidx.activity) +// implementation(libs.androidx.fragment) implementation(libs.androidx.appcompat) implementation(libs.androidx.coordinator) implementation(libs.androidx.recyclerview) implementation(libs.google.material) - implementation("androidx.lifecycle:lifecycle-livedata-ktx:2.9.1") - implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.9.1") - implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.9.1") + implementation("androidx.lifecycle:lifecycle-livedata-ktx:2.5.1") + implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.5.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.jakewharton:process-phoenix:3.0.0") @@ -78,13 +82,29 @@ dependencies { api("com.orhanobut:logger:2.2.0") api("com.google.code.gson:gson:2.10.1") 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: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") + +// https://mvnrepository.com/artifact/com.alipay.sdk/alipaysdk-android 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") + // https://mvnrepository.com/artifact/com.airbnb.android/lottie 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") { exclude("com.hihonor.mcs", "ads-identifier") exclude("com.huawei.hms", "ads-identifier") @@ -92,7 +112,9 @@ dependencies { //stripe 支付 implementation("com.stripe:stripe-android:21.4.2")// 使用最新版本 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") + // 荣耀的最新版本广告标识服务SDK,参阅 https://developer.hihonor.com/cn/kitdoc?kitId=11030&navigation=guides&docId=intergrate.md api ("com.hihonor.mcs:ads-identifier:1.0.2.301") implementation("com.android.installreferrer:installreferrer:2.2")// 使用最新版本 @@ -108,7 +130,9 @@ task("downloadGeoFiles") { 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/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 { geoFilesUrls.forEach { (downloadUrl, outputFileName) -> @@ -159,6 +183,9 @@ android { abiFilters.add("armeabi-v7a") } } +// sourceSets.all { +// jniLibs.srcDir("src/main/jniLibs") +// } sourceSets.all { jniLibs.srcDir("src/main/jniLibs") } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 9e242c4..7c1102d 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -166,6 +166,9 @@ + = mutableListOf() - -// var clash: ClashManager? = null - } - - private lateinit var swipeLayout: SwipeRefreshLayout - private lateinit var changeNodeVM: ChangeNodeVM - private lateinit var nodeListRv: RecyclerView - private var names: List? = 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(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 { - var mList: MutableList = 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>("") - 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>() {}.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() - 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(); - 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?) { - 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 -> { - - } - } - } - - -} diff --git a/app/src/main/java/com/yingmao/clash/act/ExpensesRecordVM.kt b/app/src/main/java/com/yingmao/clash/act/ExpensesRecordVM.kt index aeba095..8a2fddf 100644 --- a/app/src/main/java/com/yingmao/clash/act/ExpensesRecordVM.kt +++ b/app/src/main/java/com/yingmao/clash/act/ExpensesRecordVM.kt @@ -9,7 +9,7 @@ import com.yingmao.clash.net.http.HttpReqType import com.yingmao.clash.net.http.NetService class ExpensesRecordVM: BaseViewMode() { - fun getExpensesRecord(page :PageInfo){ + fun getExpensesRecord(page : ExpensesRecordActivity.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,"")!! diff --git a/app/src/main/java/com/yingmao/clash/act/NewMainActivity.kt b/app/src/main/java/com/yingmao/clash/act/NewMainActivity.kt index b26deff..b885f13 100644 --- a/app/src/main/java/com/yingmao/clash/act/NewMainActivity.kt +++ b/app/src/main/java/com/yingmao/clash/act/NewMainActivity.kt @@ -79,6 +79,8 @@ import com.yingmao.clash.view.dialog.DialogBandChoose import com.yingmao.clash.view.dialog.DialogNotice import com.yingmao.clash.view.dialog.RxDialogShapeLoading 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.GlobalScope import kotlinx.coroutines.Job @@ -776,7 +778,7 @@ class NewMainActivity : BaseActivity() { ) } - private fun goCheckLogin() { + fun goCheckLogin() { mainAtyVM.checkLogin() } private fun showBindAccount() { diff --git a/app/src/main/java/com/yingmao/clash/base/BaseActivity.kt b/app/src/main/java/com/yingmao/clash/base/BaseActivity.kt index 001b32b..b722997 100644 --- a/app/src/main/java/com/yingmao/clash/base/BaseActivity.kt +++ b/app/src/main/java/com/yingmao/clash/base/BaseActivity.kt @@ -3,7 +3,11 @@ package com.yingmao.clash.base import android.annotation.SuppressLint import android.app.Activity import android.content.Context +import android.content.Intent 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.Bundle import android.text.TextUtils @@ -14,14 +18,24 @@ import android.view.inputmethod.InputMethodManager import android.widget.* import androidx.annotation.RequiresApi 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.yingmao.clash.BuildConfig +import com.yingmao.clash.R import com.yingmao.clash.conf.BZYConstants 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.remote.Broadcasts import com.yingmao.clash.remote.Remote import com.cncat.vpn.service.store.ServiceStore +import com.yingmao.clash.util.ApplicationObserver import com.yingmao.clash.util.StatusBarUtils import com.yingmao.clash.util.UiStore import com.yingmao.clash.view.dialog.RxDialogShapeLoading @@ -29,26 +43,59 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.MainScope import kotlinx.coroutines.cancel import kotlinx.coroutines.channels.Channel +import kotlinx.coroutines.launch import java.util.* -@Suppress("DEPRECATION") 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 events = Channel(Channel.UNLIMITED) - private var baseLoading: RxDialogShapeLoading? = null + + // private var dayNight: DayNight = DayNight.Day + var baseLoading: RxDialogShapeLoading? = null val serStore by lazy { ServiceStore(this) } - @RequiresApi(Build.VERSION_CODES.M) + companion object { +// var switchFinshSet: MutableSet? = 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?) { super.onCreate(savedInstanceState) - requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; //竖屏 + requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT; //竖屏 StatusBarUtils.with(this).init() window.decorView.systemUiVisibility = 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(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() { super.onStart() @@ -67,6 +114,33 @@ open class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope(), Br 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) { viewMode.statusData.observe(activity) { when (it) { @@ -93,14 +167,16 @@ open class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope(), Br @SuppressLint("ClickableViewAccessibility") open fun setupUI(view: View) { + // Set up touch listener for non-text box views to hide keyboard. if (view !is EditText) view.setOnTouchListener { _, _ -> hideSoftKeyboard(this@BaseActivity) false } + //If a layout container, iterate over children and seed recursion. if (view is ViewGroup) { - for (i in 0 until view.childCount) { - val innerView: View = view.getChildAt(i) + for (i in 0 until (view as ViewGroup).childCount) { + val innerView: View = (view as ViewGroup).getChildAt(i) setupUI(innerView) } } @@ -114,6 +190,24 @@ open class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope(), Br 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() { events.trySend(Event.ProfileChanged) } @@ -140,6 +234,12 @@ open class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope(), Br override fun onStopped(cause: String?) { events.trySend(Event.ClashStop) + +// if (cause != null && activityStarted) { +// launch { +// design?.showExceptionToast(ClashException(cause)) +// } +// } } enum class Event { @@ -170,6 +270,63 @@ open class BaseActivity : AppCompatActivity(), CoroutineScope by MainScope(), Br 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 fun switchServer2(): Boolean { 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) var newUrlString = originalUrl 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 { +// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { +// if (!isNetworkAvailable(this@BaseActivity)){ +// return isChange +// } +// } if (it.isEmpty()) { Log.d(Conf.TAG, "routerHost isEmpty") - return 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) { - return false + if (switchFinshSet?.size!! >= routerHost.size) { + return isChange } Log.d(Conf.TAG, "routerHost not empty") +// val iterator = it.iterator() +// while (iterator.hasNext()) { +// val newUrl = iterator.next() +// Log.e( +// "Data", +// "遍历备用的url:$newUrl, contains==>${switchFinshSet?.contains(newUrl)}" +// ) +// if (newUrl == originalUrl) { +// switchFinshSet?.add(newUrl) +// iterator.remove() +// continue +// } +// if (switchFinshSet?.contains(newUrl) == true) { +// iterator.remove() +// } else { +// Log.e("Retry", "切换到新url:$newUrl") +// isChange = true +// newUrlString = newUrl +// iterator.remove() +// if (originalUrl != null) { +// switchFinshSet?.add(originalUrl) +// mmkv.encode(BZYConstants.MMKV_KEY_OLD_CURRENT_HOST, originalUrl) +// } +// break +// } +// } for (url in it) { if (url == originalUrl) { - switchFinishSet.add(url) - mmkv.encode(BZYConstants.MMKV_KEY_Switch_Finsh_Set, switchFinishSet) + switchFinshSet?.add(url) + mmkv.encode(BZYConstants.MMKV_KEY_Switch_Finsh_Set, switchFinshSet) continue } - if (switchFinishSet.contains(url)) { + if (switchFinshSet?.contains(url) == true) { continue } else { isChange = true - Log.e("Retry", "切换到新url:$url") + android.util.Log.e("Retry", "切换到新url:$url") newUrlString = url - switchFinishSet.add(newUrlString) - mmkv.encode(BZYConstants.MMKV_KEY_Switch_Finsh_Set, switchFinishSet) + switchFinshSet?.add(newUrlString) + mmkv.encode(BZYConstants.MMKV_KEY_Switch_Finsh_Set, switchFinshSet) +// mmkv.encode(BZYConstants.MMKV_KEY_OLD_CURRENT_HOST, newUrlString) break } } +// mmkv.encode(BZYConstants.MMKV_KEY_ROUTER_HOST, routerHost) mmkv.encode(BZYConstants.MMKV_KEY_CURRENT_HOST, newUrlString) } diff --git a/app/src/main/java/com/yingmao/clash/conf/Conf.kt b/app/src/main/java/com/yingmao/clash/conf/Conf.kt index cbc50c8..5ea705b 100644 --- a/app/src/main/java/com/yingmao/clash/conf/Conf.kt +++ b/app/src/main/java/com/yingmao/clash/conf/Conf.kt @@ -17,7 +17,7 @@ class Conf { return context?.getString(R.string.app_name_taizi)!! } else { if (BuildConfig.is_ym) { - return context?.getString(R.string.WFApiPort)!! + return context?.getString(R.string.app_name_gz)!! } else { return context?.getString(R.string.app_name)!! } diff --git a/app/src/main/java/com/yingmao/clash/fragment/NewAccFragment.kt b/app/src/main/java/com/yingmao/clash/fragment/NewAccFragment.kt index 3b02033..9272d6c 100644 --- a/app/src/main/java/com/yingmao/clash/fragment/NewAccFragment.kt +++ b/app/src/main/java/com/yingmao/clash/fragment/NewAccFragment.kt @@ -32,7 +32,7 @@ import com.yingmao.clash.R import com.yingmao.clash.act.NewMainActivity import com.yingmao.clash.act.NewMainActivity.Companion.isSubed 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.Conf 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.util.ActivityResultLifecycle import com.yingmao.clash.util.CommonUtils +import com.yingmao.clash.util.Utils import com.yingmao.clash.util.startClashService import com.yingmao.clash.util.stopClashService import com.yingmao.clash.view.RxToast @@ -89,7 +90,7 @@ class NewAccFragment : BaseFragment(), CoroutineScope by CoroutineScope(Dispatch // var currentNode: Profile? = null private var reConnection = false private var connectId=-1 - + private var baseLoading: RxDialogShapeLoading? = null override fun init( titleBarRl: RelativeLayout, backIv: ImageView, @@ -182,7 +183,7 @@ class NewAccFragment : BaseFragment(), CoroutineScope by CoroutineScope(Dispatch rxDialogSureCancel.show() } else { - startClash() + startClash(false) } } @@ -220,25 +221,21 @@ class NewAccFragment : BaseFragment(), CoroutineScope by CoroutineScope(Dispatch } - private fun startClash() { - if (checkExpire()) { - if (isAdded) { - RxToast.info(resources.getString(R.string.AccountExpired)) - } - - return - } + private fun startClash(isStart:Boolean) { launch { - NewMainActivity.profileBinder?.let { pm -> + if(isStart){ + delay(2000) + } + profileBinder?.let { pm -> val active = pm.queryActive() if (active == null) { - com.cncat.vpn.common.log.Log.d("startClash: 未选择") + Log.d("startClash: 未选择") val pro = pm.queryAll().find { it.name == Conf.getClashConfName(this@NewAccFragment.context) } 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) newUuid = profile.uuid.toString(); @@ -267,7 +264,6 @@ class NewAccFragment : BaseFragment(), CoroutineScope by CoroutineScope(Dispatch stateChanged(Clash_Starting, true) context?.startClashService() accelerateViewModel.appStartupStatus() -// clashRunning = true } launch(Dispatchers.Main){ lottieView.playAnimation() @@ -285,6 +281,9 @@ class NewAccFragment : BaseFragment(), CoroutineScope by CoroutineScope(Dispatch stop_u_timer() e.printStackTrace() } + withContext(Dispatchers.Main){ + hideLoading() + } } } @@ -340,7 +339,7 @@ class NewAccFragment : BaseFragment(), CoroutineScope by CoroutineScope(Dispatch Intents.ACTION_CLASH_REQUEST_STOP -> { // clashRunning = false - com.cncat.vpn.common.log.Log.d("ACTION_CLASH_REQUEST_STOP") + Log.d("ACTION_CLASH_REQUEST_STOP") if (::rxDialogShapeLoading.isInitialized) { if (!rxDialogShapeLoading.isShowing) { if (isAdded) { @@ -431,7 +430,7 @@ class NewAccFragment : BaseFragment(), CoroutineScope by CoroutineScope(Dispatch if (clashRunning) { Log.d("clashRunning $clashRunning") } else { - startClash() + startClash(false) } } else { if (::rxDialogShapeLoading.isInitialized || rxDialogShapeLoading.isShowing) { @@ -452,9 +451,7 @@ class NewAccFragment : BaseFragment(), CoroutineScope by CoroutineScope(Dispatch checkGlo() }?.run { if (is_runing == true && !clashRunning) { - startClash() - } else { - + startClash(false) } } } 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) if (validPeriod > 0) { var nowTime = System.currentTimeMillis(); - com.cncat.vpn.common.log.Log.d("validPeriod==>$validPeriod, nowTime==>$nowTime") + Log.d("validPeriod==>$validPeriod, nowTime==>$nowTime") if (validPeriod >= nowTime) { return false } @@ -757,12 +754,12 @@ class NewAccFragment : BaseFragment(), CoroutineScope by CoroutineScope(Dispatch if (clashRunning) { Log.d("clashRunning $clashRunning") } else { - startClash() + startClash(false) } checkGlo() }?.run { if (isRunning == true && !clashRunning) { - startClash() + startClash(false) } } } @@ -791,10 +788,4 @@ class NewAccFragment : BaseFragment(), CoroutineScope by CoroutineScope(Dispatch baseLoading?.cancel() } } - private fun goNewRecharge() { - if (activity != null) { - val newUiMain = activity as NewMainActivity - newUiMain.goBackupRechargeWeb() - } - } } \ No newline at end of file diff --git a/app/src/main/java/com/yingmao/clash/vm/MainAtyVM.kt b/app/src/main/java/com/yingmao/clash/vm/MainAtyVM.kt index a3ccd24..999fc00 100644 --- a/app/src/main/java/com/yingmao/clash/vm/MainAtyVM.kt +++ b/app/src/main/java/com/yingmao/clash/vm/MainAtyVM.kt @@ -389,18 +389,4 @@ class MainAtyVM : PublicViewMode() { val requestBody: RequestBody = jsonString.toRequestBody("application/json; charset=utf-8".toMediaType()) 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( - "phoneNumber" to username, - "userId" to userId, - "phToken" to phToken, - "pageno" to "${page.page}", - "pageSize" to "5", - ) - doAsync(HttpReqType.EXPENSES_RECORD){httpApi.phOrderList(params)} - } } \ No newline at end of file diff --git a/app/src/main/java/com/yingmao/clash/webview/BZYWebViewKeFu.kt b/app/src/main/java/com/yingmao/clash/webview/BZYWebViewKeFu.kt new file mode 100644 index 0000000..b01a729 --- /dev/null +++ b/app/src/main/java/com/yingmao/clash/webview/BZYWebViewKeFu.kt @@ -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(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() + } + } +} \ No newline at end of file diff --git a/app/src/main/res/layout/activity_base.xml b/app/src/main/res/layout/activity_base.xml new file mode 100644 index 0000000..68f6230 --- /dev/null +++ b/app/src/main/res/layout/activity_base.xml @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/bzy_kefu_webview_layout.xml b/app/src/main/res/layout/bzy_kefu_webview_layout.xml new file mode 100644 index 0000000..ce03a1f --- /dev/null +++ b/app/src/main/res/layout/bzy_kefu_webview_layout.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index 5e2fe74..0a2cafb 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -106,6 +106,8 @@ subprojects { buildConfigField("boolean", "PREMIUM", "Boolean.parseBoolean(\"false\")") buildConfigField("boolean", "is_back_cn", "false") buildConfigField("boolean", "is_ym", "true") + buildConfigField("boolean", "is_tz", "false") + buildConfigField("boolean", "is_yunti", "false") buildConfigField("String", "applicationId", "\"com.yingmao.clash\"") buildConfigField("String", "service_url", "\"https://api.ymvpnpro.cc:8700\"") buildConfigField("boolean", "is_free", "false")