package com.yingmao.clash.act import android.Manifest import android.annotation.SuppressLint import android.content.Intent import android.content.pm.PackageManager import android.graphics.Bitmap import android.graphics.drawable.BitmapDrawable import android.net.Uri import android.os.Build import android.os.Bundle import android.provider.Settings import android.text.TextUtils import android.util.Log import android.view.View import android.view.WindowManager import android.widget.ProgressBar import android.widget.RelativeLayout import android.widget.TextView import android.widget.Toast import androidx.annotation.RequiresApi import androidx.core.app.ActivityCompat import androidx.core.content.ContextCompat import androidx.core.content.FileProvider import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.lifecycleScope import com.afollestad.materialdialogs.MaterialDialog import com.afollestad.materialdialogs.customview.customView import com.bumptech.glide.Glide import com.bumptech.glide.request.target.SimpleTarget import com.bumptech.glide.request.transition.Transition import com.cncat.vpn.service.ClashManager import com.cncat.vpn.service.remote.IClashManager import com.cncat.vpn.service.remote.wrap import com.fm.openinstall.OpenInstall import com.fm.openinstall.listener.AppWakeUpAdapter import com.fm.openinstall.model.AppData import com.google.gson.JsonObject import com.orhanobut.logger.Logger import com.tencent.mmkv.MMKV import com.yingmao.clash.BuildConfig import com.yingmao.clash.R import com.yingmao.clash.app.MainApplication import com.yingmao.clash.base.BaseActivity import com.yingmao.clash.captcha.Captcha import com.yingmao.clash.conf.BZYConstants import com.yingmao.clash.conf.BZYConstants.Companion.MMKV_KEY_IS_REGISTER import com.yingmao.clash.conf.BZYConstants.Companion.MMKV_KEY_NOTE_DEFAULT_PSW import com.yingmao.clash.conf.BZYConstants.Companion.MMKV_KEY_REMEMBER_PASSWORD import com.yingmao.clash.conf.BZYConstants.Companion.MMKV_KEY_REMEMBER_USERNAME import com.yingmao.clash.entity.CheckLoginRsp import com.yingmao.clash.listener.DownLoadListener import com.yingmao.clash.net.http.HttpReqType import com.yingmao.clash.net.http.HttpStatus import com.yingmao.clash.net.http.entity.AppVersionCheckRsp import com.yingmao.clash.net.http.entity.LoginRsp import com.yingmao.clash.net.http.entity.RegisterRsp import com.yingmao.clash.net.http.entity.StartingBeans import com.yingmao.clash.util.AESUtil import com.yingmao.clash.util.Utils import com.yingmao.clash.view.RxToast import com.yingmao.clash.view.dialog.DialogAppVersion import com.yingmao.clash.view.dialog.DialogDoMainChoose import com.yingmao.clash.view.dialog.RxDialogSureCancel import com.yingmao.clash.vm.SplashAtyVM import kotlinx.coroutines.MainScope import kotlinx.coroutines.async import kotlinx.coroutines.launch import java.io.File import java.util.Locale class SplashActivity : BaseActivity() { private val deniedPermissions = hashSetOf() private val mPermissions = hashSetOf() private val PERMISSION_REQUEST_CODE: Int = 1 private val PERMISSION_SETTING_REQUEST_CODE = 2 private lateinit var rlPb: View private lateinit var ll_action: View private lateinit var username: String private lateinit var rlMain: RelativeLayout private lateinit var splashAtyVM: SplashAtyVM private var registerKey = "" private var registerIV2 = "" private var initErrMsg = "" override fun onCreate(savedInstanceState: Bundle?) { window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION) super.onCreate(savedInstanceState) setLocalLanguage() initErrMsg = resources.getString(R.string.splashErrorTips) username = Utils.getUniqueID(this) // var username2 = Utils.getUniqueID2(this); // com.cncat.vpn.common.log.Log.d("username==>" + username + ", username2==>" + username2) splashAtyVM = ViewModelProvider(this).get(SplashAtyVM::class.java) observe(this, splashAtyVM) setContentView(R.layout.layout_splash_activity) rlMain=findViewById(R.id.rlMain) rlPb = findViewById(R.id.rl_pb) ll_action = findViewById(R.id.ll_action) serStore.isYM = BuildConfig.is_ym if (!BuildConfig.is_ym) { if (BuildConfig.is_tz) { serStore.isTZ = true } else { serStore.isBZY = true } } // mPermissions.add(Manifest.permission.READ_PHONE_STATE) // mPermissions.add(Manifest.permission.INTERNET) // mPermissions.add(Manifest.permission.ACCESS_NETWORK_STATE) // if (checkPermissions(mPermissions)) {//权限请求通过 // Log.e("gg", "per sss") // } else {//权限请求未通过 // if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { // requestPermissions(mPermissions.toTypedArray(), PERMISSION_REQUEST_CODE) // } // } // OpenInstall.getInstall(object : AppInstallListener { // override fun onInstallFinish( // appData: AppData?, // error: com.fm.openinstall.model.Error?, // ) { // var mAppData = appData // if (error != null && error.shouldRetry()) { // // 获取数据异常,可以尝试重新获取 // } else { // if (mAppData == null) mAppData = AppData() // val channelCode = mAppData.getChannel() // 获取渠道编号参数 // val bindData = mAppData.getData() // 获取自定义参数 // com.cncat.vpn.common.log.Log.d("channelCode==>${channelCode}, bindData==>${bindData}") // } // } // }) // DeviceID.getOAID(this, object : IGetter { // override fun onOAIDGetComplete(result: String) { // // 不同厂商的OAID/AAID格式是不一样的,可进行MD5、SHA1之类的哈希运算统一 // com.cncat.vpn.common.log.Log.d("onOAIDGetComplete result==>${result}") // } // // override fun onOAIDGetError(error: Exception) { // // 获取OAID/AAID失败 // error.printStackTrace() // } // }) // com.cncat.vpn.common.log.Log.d("onOAIDGetComplete result==>${ DeviceIdentifier.getOAID(this)}") //获取配置背景 splashAtyVM.getSplashBg() var clashBinder = MainApplication.getApp()?.let { ClashManager(it).wrap() as IClashManager } clashBinder?.let { cb -> var signList = AESUtil.getSingInfo(this@SplashActivity, BuildConfig.applicationId, AESUtil.SHA256) if (signList.isNotEmpty()) { var si = signList[0] var ss1 = cb.getSS1(si) var ss2 = cb.getSS2(si) registerKey = cb.getRegisterKey(si) registerIV2 = cb.getRegisterKiv(si) // com.cncat.vpn.common.log.Log.d("si==>${si}, ss1==>${ss1}, ss2==>${ss2}") AESUtil.KEY2 = ss1 AESUtil.IV2 = ss2 // 太子 // com.cncat.vpn.common.log.Log.d("tz encrypt:"+ AESUtil.byteArrayToHexStr(AESUtil.encrypt(""))) // 八爪鱼 com.cncat.vpn.common.log.Log.d("bzy encrypt:"+ AESUtil.byteArrayToHexStr(AESUtil.encrypt(""))) // 八爪鱼 2 // com.cncat.vpn.common.log.Log.d("bzy2 encrypt:"+ AESUtil.byteArrayToHexStr(AESUtil.encrypt(""))) // 影猫 // com.cncat.vpn.common.log.Log.d( // "ym encrypt:" + // AESUtil.byteArrayToHexStr( // AESUtil.encrypt( // "https://api.yingmaohot.org+https://api.yingmao888.net+" + // "https://api.ymsohot.com+https://ma.wztgyh.com+https://ymapi.yingmaox.cc" // ) // ) // ) val routerSet = MMKV.defaultMMKV().decodeStringSet(BZYConstants.MMKV_KEY_ROUTER_HOST) if (routerSet != null && routerSet.size > 0) { isNeedRegister() } else { rlPb.visibility = View.VISIBLE if (BuildConfig.is_back_cn == true) { //没有备用域名所以无需调用getHost isNeedRegister() } else { SplashHelper(splashAtyVM).getHostWithFallback { success -> MainScope().launch { if (success) { isNeedRegister() } else { isNeedRegister() } } } // splashAtyVM.getHostByGithub(object : AsyncCallback { // override suspend fun suc() { // Log.e("data", "getHostByGithub suc") // MainScope().launch { // isNeedRegister() // } // } // // override fun err() { // Log.e("data", "getHostByGithub err") // splashAtyVM.getHostByAWS(object : AsyncCallback { // override suspend fun suc() { // Log.e("data", "getHostByAWS suc") // MainScope().launch { // isNeedRegister() // } // } // // override fun err() { // Log.e("data", "getHostByAWS err") // splashAtyVM.getHost(object : AsyncCallback { // override suspend fun suc() { // Log.e("data", "getHost suc") // MainScope().launch { // isNeedRegister() // } // } // // override fun err() { // Log.e("data", "getHost err") // //全部失败后也调用 // MainScope().launch { // isNeedRegister() // } // } // }) // } // }) // } // }) } } } } // val Sgtr= AESUtil.Registerdecrypt("CCBF308D702235C8F810876987A43AB02B84EBB47DBFF1B915D5FBB29FF2DBAE90DB72D58351D09D223D49E44A2A073D9156E84D6B7EB89D7493A3F0A7240EE076ADC83B5A12AC37616CEDED00643AD1E6851AFECA82E373CB4E518DF2190708F5191AE195758E8EA41A5242A6C94216B64FF8715B35C54CB894113FC93361F32FDA86CF34093DF924230DEBE27A69293C761A9A797A652A1C35C95C27FB5EB4" // ,registerKey,registerIV2) // println("Sgtr==>$Sgtr") OpenInstall.getWakeUp(intent, wakeUpAdapter) OpenInstall.getInstall { appData, error -> var appData = appData if (error != null && error.shouldRetry()) { // 获取数据异常,可以尝试重新获取 } else { if (appData == null) appData = AppData() val channelCode = appData.getChannel() // 获取渠道编号参数 val bindData = appData.getData() // 获取自定义参数 Log.d("OpenInstall", "getInstall : channelCode = $channelCode"+"bindData::"+bindData) } } } private var wakeUpAdapter: AppWakeUpAdapter = object : AppWakeUpAdapter() { override fun onWakeUp(appData: AppData) { // 打印数据便于调试 Log.d("OpenInstall", "getWakeUp : wakeupData = $appData") // 获取渠道编号参数 val channelCode = appData.getChannel() // 获取自定义参数 val bindData = appData.getData() Log.d("OpenInstall", "channelCode : bindData = $channelCode"+"bindData::"+bindData) } } override fun onNewIntent(intent: Intent?) { super.onNewIntent(intent) // 此处要调用,否则App在后台运行时,会无法获取 OpenInstall.getWakeUp(intent, wakeUpAdapter) } private fun setLocalLanguage() { var defLan = "" if (BuildConfig.is_tz) { defLan = "Chinese-HK" } val decodeString = MMKV.defaultMMKV().decodeString(BZYConstants.languageInfo, defLan) if (!decodeString.isNullOrEmpty()) { when (decodeString) { "Chinese-CN" -> { val config = resources.configuration config.locale = Locale.CHINA updateLanguage("Chinese-CN", Locale.CHINA) } "Chinese-HK" -> { val config = resources.configuration config.locale = Locale("zh", "HK") updateLanguage("Chinese-HK", Locale("zh", "HK")) } "English" -> { val config = resources.configuration config.locale = Locale.ENGLISH updateLanguage("English", Locale.ENGLISH) } } } } private fun checkPermission(): Boolean { if (ContextCompat.checkSelfPermission( this, Manifest.permission.ACCESS_NETWORK_STATE ) == PackageManager.PERMISSION_GRANTED && ContextCompat.checkSelfPermission( this, Manifest.permission.INTERNET ) == PackageManager.PERMISSION_GRANTED ) { return true } return false } override fun onStarted() { super.onStarted() } private fun graphicVerificationDialog() { //开启人机验证 MaterialDialog(this).show { this.cancelable(false) cornerRadius(res = R.dimen.dp_10) customView( R.layout.graphic_verification_dialog_layout, scrollable = false, noVerticalPadding = true, horizontalPadding = false ) val captchaSimple = findViewById(R.id.captCha) captchaSimple.setCaptchaListener(object : Captcha.CaptchaListener { override fun onAccess(time: Long): String { Toast.makeText( this@SplashActivity, resources.getString(R.string.VerificationSuccessful), Toast.LENGTH_SHORT ).show() dismiss() val intent = Intent(this@SplashActivity, LoginActivity::class.java) startActivity(intent) finish() return resources.getString(R.string.VerificationSuccessful) .replace("%d", "$time") } override fun onFailed(failedCount: Int): String { Toast.makeText( this@SplashActivity, resources.getString(R.string.VerificationFailed), Toast.LENGTH_SHORT ).show() return resources.getString(R.string.VerificationSuccessful) .replace("%d", "$failedCount") } override fun onMaxFailed(): String { Toast.makeText( this@SplashActivity, resources.getString(R.string.VerifiedOnce), Toast.LENGTH_SHORT ) .show() finish() return resources.getString(R.string.VerifiedOnce) } }) } } private fun isNeedRegister() { if (!BuildConfig.is_free && BuildConfig.productId.isNotEmpty()) { //渠道包都自动注册登录,广州22222也是非自动注册 rlPb.visibility = View.VISIBLE if (MMKV.defaultMMKV().decodeBool(BZYConstants.MMKV_KEY_IS_REGISTER, false)) { splashAtyVM.checkLogin() } else { // doRegister() doRegisterByEncryption() } } else {//非渠道自由包 val token = MMKV.defaultMMKV().decodeString(BZYConstants.MMKV_KEY_TOKEN) ll_action.visibility = View.VISIBLE rlPb.visibility = View.INVISIBLE if (MMKV.defaultMMKV().decodeBool(BZYConstants.MMKV_KEY_IS_REGISTER, false)) { if (token != null && token.isNotEmpty()) { ll_action.visibility = View.GONE rlPb.visibility = View.VISIBLE splashAtyVM.checkLogin() } else { val intent = Intent(this@SplashActivity, LoginActivity::class.java) startActivity(intent) finish() } } else { findViewById(R.id.rl_action_login).setOnClickListener {//点有账号直接登录的 val intent = Intent(this@SplashActivity, LoginActivity::class.java) startActivity(intent) finish() } findViewById(R.id.rl_action_register).setOnClickListener {//无账号的自动注册但不会填任何渠道号 val intent = Intent(this@SplashActivity, RegisterActivity::class.java) startActivity(intent) finish() } } } } var errorTotal: Int = 0 fun doRegister() { val params: Map = mutableMapOf( "phoneNumber" to username, "password" to BZYConstants.defaultPassword, "checkPassword" to BZYConstants.defaultPassword, "id" to BuildConfig.productId, "clientIp" to Utils.getIPAddress(), "from" to "5", ) splashAtyVM.register(params) } @Synchronized fun doRegisterByEncryption() { var req_json = JsonObject() req_json.addProperty("password", BZYConstants.defaultPassword) req_json.addProperty("checkPassword", BZYConstants.defaultPassword) req_json.addProperty("invitationCode", BuildConfig.productId) req_json.addProperty("clientIp", Utils.getIPAddress()) req_json.addProperty("from", "5") req_json.addProperty("androidDevice", username) if (registerKey.isNotEmpty() && registerIV2.isNotEmpty()) { val data = AESUtil.byteArrayToHexStr( AESUtil.RegisterEncrypt(req_json.toString(), registerKey, registerIV2) ) val params: Map = mutableMapOf( "data" to data ) splashAtyVM.registerByEncryption(params) } } // private fun initSub() { // var yaml = context?.getString(com.cncat.vpn.service.R.string.configuration_yaml) // Log.d(Conf.TAG, "initSub: $yaml") // // accelerateViewModel.statusData.observe(viewLifecycleOwner) { // when (it) { // is HttpStatus.Loading -> { // // Log.d(Conf.TAG, "正在获取节点信息...") // } // // is HttpStatus.Success -> { // // val data = it.rsp as SubscriptionRsp // if (data.code == "1000") { // // } else { //// dismissDialog() // RxToast.error("获取节点失败:${data.msg}") // } // // data.data?.let { url -> // Log.e("Data", "机场URL:=${url}") // if (url.isNotEmpty()) { //// lifecycleScope.launch { //// //// } //// sendMessage(1, url) // setSub(url) // // } // } // //// } // } // // is HttpStatus.Failure -> { // if (it.reqType == HttpReqType.GET_AIRNODES) { //// dismissDialog() //// showRetryDialog() // Logger.e("获取节点异常:${it.msg}") // } // } // } // } // } // private fun setSub(url: String) { // com.cncat.vpn.common.log.Log.d("setSub....") // // lifecycleScope.launch (Dispatchers.IO) { // com.cncat.vpn.common.log.Log.d("setSub....11") // withProfile { // com.cncat.vpn.common.log.Log.d("setSub....2") // val pro = queryAll().find { // it.name == "八爪猫" // } // // if (pro == null) { // com.cncat.vpn.common.log.Log.d("setSub.... pro is null") // var uuid: UUID = create(Profile.Type.Url, "八爪猫") // delay(500) // queryByUUID(uuid)?.let { qPro -> // setActive(qPro) // 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 { // commit(qPro.uuid) { status -> // Log.d( // Conf.TAG, // "new updateStatus: " + Gson().toJson(status.args) + ", pro==>" + status.progress // ) // } // newUuid = qPro.uuid.toString(); // isSubed = true //// } // } // } else { // Log.d(Conf.TAG, "pro 已存在 ==>" + Gson().toJson(pro)) // setActive(pro) //// update(pro.uuid) // newUuid = pro.uuid.toString(); // isSubed = true // } // profile = pro; // } // } // // } override fun httpSuccess(httpStatus: HttpStatus.Success) { when (httpStatus.reqType) { HttpReqType.REGISTER -> { dialogDoMainChoose?.dismiss() with(httpStatus.rsp as RegisterRsp) { if (code == "10000" || code == "200") { if (data != null) { if (!data.phoneNumber.isNullOrEmpty()) { MMKV.defaultMMKV() .encode(MMKV_KEY_REMEMBER_USERNAME, data.phoneNumber) } else { MMKV.defaultMMKV().encode(MMKV_KEY_REMEMBER_USERNAME, username) } } else { MMKV.defaultMMKV().encode(MMKV_KEY_REMEMBER_USERNAME, username) } MMKV.defaultMMKV() .encode(MMKV_KEY_REMEMBER_PASSWORD, BZYConstants.defaultPassword) MMKV.defaultMMKV().encode(MMKV_KEY_IS_REGISTER, true) MMKV.defaultMMKV().encode(MMKV_KEY_NOTE_DEFAULT_PSW, true) val encryName = AESUtil.byteArrayToHexStr( AESUtil.encrypt(data?.phoneNumber) ) val encryPsw = AESUtil.byteArrayToHexStr( AESUtil.encrypt(BZYConstants.defaultPassword) ) val decodeBool = MMKV.defaultMMKV().decodeBool(BZYConstants.INITIALIZATION, true) if (decodeBool) { MMKV.defaultMMKV().encode(BZYConstants.INITIALIZATION, true) } splashAtyVM.login(encryName, encryPsw) } else if (code == "20062") { message?.let { RxToast.error(it) } // if (data != null) { // // var jo = // Gson().fromJson(data, JsonObject::class.java) // var userName = jo.get("data").asString; // if (!TextUtils.isEmpty(userName)) { // // } // } if (data != null) { if (!data.phoneNumber.isNullOrEmpty()) { MMKV.defaultMMKV() .encode(MMKV_KEY_REMEMBER_USERNAME, data.phoneNumber) } else { MMKV.defaultMMKV().encode(MMKV_KEY_REMEMBER_USERNAME, username) } } else { MMKV.defaultMMKV().encode(MMKV_KEY_REMEMBER_USERNAME, username) } val intent = Intent(this@SplashActivity, LoginActivity::class.java) startActivity(intent) finish() // graphicVerificationDialog() } else { MaterialDialog(this@SplashActivity).show { message(text = initErrMsg) positiveButton(R.string.retry) { // doRegister() doRegisterByEncryption() } negativeButton(R.string.cancel) { it.dismiss() finish() } } } } } HttpReqType.LOGIN -> { val rsp = httpStatus.rsp if (rsp is LoginRsp) { if (rsp.code == "1000") { val mmkv = MMKV.defaultMMKV() com.cncat.vpn.common.log.Log.i(" HttpReqType.LOGIN token ==> ${rsp.data?.vpnToken}") mmkv.encode(BZYConstants.MMKV_KEY_TOKEN, rsp.data?.vpnToken) mmkv.encode(BZYConstants.MMKV_KEY_PH_TOKEN, rsp.data?.phToken) mmkv.encode(BZYConstants.MMKV_KEY_USER_ID, rsp.data?.userId) splashAtyVM.checkLogin() } else { MaterialDialog(this@SplashActivity).show { message(text = initErrMsg) positiveButton(R.string.retry) { val encryName = AESUtil.byteArrayToHexStr( AESUtil.encrypt(username) ) val encryPsw = AESUtil.byteArrayToHexStr( AESUtil.encrypt(BZYConstants.defaultPassword) ) splashAtyVM.login(encryName, encryPsw) } negativeButton(R.string.cancel) { it.dismiss() finish() } } } } } HttpReqType.CHECK_LOGIN -> { dialogDoMainChoose?.dismiss() (httpStatus.rsp as CheckLoginRsp).let { checkLoginRsp -> if (checkLoginRsp.code == 0) { com.cncat.vpn.common.log.Log.d("splash CHECK_LOGIN==>") checkLoginRsp.data?.let { MainApplication.setUserInfo(it) } val expired = checkLoginRsp.data?.expired val isPerfect = checkLoginRsp.data?.isPerfect val userCommand = checkLoginRsp.data?.userCommand val mmkv = MMKV.defaultMMKV() mmkv.encode(BZYConstants.MMKV_KEY_VPN_EXPIRED, expired ?: true) mmkv.encode( BZYConstants.MMKV_KEY_VPN_VALID_PERIOD, checkLoginRsp.data?.vpnExpireTime ?: 0 ) mmkv.encode(BZYConstants.MMKV_KEY_IS_PERFECT, isPerfect ?: true) mmkv.encode(BZYConstants.MMKV_KEY_VPN_UserCommand, userCommand ?: "") toMainPage() } else { toLoginPage() } } } HttpReqType.SplashBg->{ val startingBeans = httpStatus.rsp as StartingBeans startingBeans.data if(startingBeans.data!=null){ if(startingBeans.data!!.exist){ Log.d("SplashActivityStarting","startingBeans.data!!.img::"+ startingBeans.data!!.img) startingBeans.data!!.img.let { Glide.with(this).asBitmap() .load(startingBeans.data!!.img) .into(object :SimpleTarget(){ override fun onResourceReady( resource: Bitmap, transition: Transition? ) { val bitmapDrawable = BitmapDrawable(resource) rlMain.setBackgroundDrawable(bitmapDrawable) } }) } } } } HttpReqType.App_VERION_CHECK->{ (httpStatus.rsp as AppVersionCheckRsp).let { avcr -> com.cncat.vpn.common.log.Log.i("App_VERION_CHECK ==>$avcr") if (avcr.code == 200) { avcr.data?.let { md -> if (md.isForce) { //强制更新 if (!TextUtils.isEmpty(md.versionPath)) { showUpdateDialog(md.versionPath!!, md.illustrate!!, true) } } else if (md.isUpgrade) { //更新 if (!TextUtils.isEmpty(md.versionPath)) { showUpdateDialog(md.versionPath!!, md.illustrate!!, false) } }else{ val intent = Intent(this@SplashActivity, UIMainActivity::class.java) startActivity(intent) finish() } } }else{ val intent = Intent(this@SplashActivity, UIMainActivity::class.java) startActivity(intent) finish() } } } else -> {} } } var dialogDoMainChoose: DialogDoMainChoose? = null override fun httpFailure(httpStatus: HttpStatus.Failure) { when (httpStatus.reqType) { HttpReqType.REGISTER -> { rlPb.visibility = View.GONE com.cncat.vpn.common.log.Log.d("httpFailure HttpReqType.REGISTER") try { RxToast.error("检测到网络异常,请尝试切换其他地址.") if (dialogDoMainChoose==null) { dialogDoMainChoose = DialogDoMainChoose(this@SplashActivity) } if (dialogDoMainChoose?.isShowing==false){ dialogDoMainChoose?.setOnTryButtonListener(object : DialogDoMainChoose.OnTryButtonListener { override fun tryButton() { var currentHost = MMKV.defaultMMKV() .decodeString(BZYConstants.MMKV_KEY_CURRENT_HOST, "") // com.cncat.vpn.common.log.Log.d("tryButton currentHost==>${currentHost}") doRegisterByEncryption() } override fun cancel() { com.cncat.vpn.common.log.Log.d("tryButton REGISTER cancel") dialogDoMainChoose?.dismiss() dialogDoMainChoose=null } }) dialogDoMainChoose?.show() } } catch (e: Exception) { e.printStackTrace() } // if (super.switchServer()) {//切换服务器并直接重试 //// doRegister() // doRegisterByEncryption() // } else { // MaterialDialog(this@SplashActivity).show { // message(text = initErrMsg) // positiveButton(R.string.retry) { //// doRegister() // doRegisterByEncryption() // } // negativeButton(R.string.cancel) { // it.dismiss() // finish() // } // } // } } HttpReqType.LOGIN -> { MaterialDialog(this@SplashActivity).show { message(text = initErrMsg) positiveButton(R.string.confirm) { val encryName = AESUtil.byteArrayToHexStr( AESUtil.encrypt(username) ) val encryPsw = AESUtil.byteArrayToHexStr( AESUtil.encrypt(BZYConstants.defaultPassword) ) splashAtyVM.login(encryName, encryPsw) } negativeButton(R.string.cancel) { it.dismiss() finish() } } } HttpReqType.CHECK_LOGIN -> { com.cncat.vpn.common.log.Log.d("httpFailure HttpReqType.CHECK_LOGIN") try { RxToast.error("检测到网络异常,请尝试切换其他地址.") SplashHelper(splashAtyVM).getHostWithFallback { success -> MainScope().launch { if (success) { if (dialogDoMainChoose==null) { dialogDoMainChoose = DialogDoMainChoose(this@SplashActivity) } if (dialogDoMainChoose?.isShowing==false){ dialogDoMainChoose?.setOnTryButtonListener(object : DialogDoMainChoose.OnTryButtonListener { override fun tryButton() { var currentHost = MMKV.defaultMMKV() .decodeString(BZYConstants.MMKV_KEY_CURRENT_HOST, "") // com.cncat.vpn.common.log.Log.d("tryButton CHECK_LOGIN currentHost==>${currentHost}") splashAtyVM.checkLogin() } override fun cancel() { com.cncat.vpn.common.log.Log.d("tryButton CHECK_LOGIN cancel") dialogDoMainChoose?.dismiss() } }) dialogDoMainChoose?.show() } } } } } catch (e: Exception) { e.printStackTrace() toLoginPage() } // if (super.switchServer()) { // splashAtyVM.checkLogin() // } else { // toLoginPage() // } } else -> {} } } //申请权限 private fun checkPermissions(permissions: HashSet): Boolean { for (permission in permissions) { val permissionStatus = ContextCompat.checkSelfPermission(this, permission) if (permissionStatus == PackageManager.PERMISSION_DENIED) deniedPermissions.add(permission) else deniedPermissions.remove(permission) } return deniedPermissions.isEmpty() } override fun onRequestPermissionsResult( requestCode: Int, permissions: Array, grantResults: IntArray, ) { Log.e("data", "onRequestPermissionsResult requestCode==> " + requestCode) permissions.forEach { Log.e("data", "onRequestPermissionsResult permissions ==> " + it) } grantResults.forEach { Log.e("data", "onRequestPermissionsResult grantResults==> " + it) } super.onRequestPermissionsResult(requestCode, permissions, grantResults) // val deniedAndNoLongerPromptPermissions = HashSet() if (requestCode == PERMISSION_REQUEST_CODE) { for ((i, permission) in permissions.withIndex()) { if (!ActivityCompat.shouldShowRequestPermissionRationale( this, permission ) ) //不在提示权限包含 已通过的和勾选不在提示的权限 if (grantResults[i] == 0) deniedAndNoLongerPromptPermissions.remove(permission) else deniedAndNoLongerPromptPermissions.add(permission) else deniedAndNoLongerPromptPermissions.remove(permission) } } if (deniedAndNoLongerPromptPermissions.isNotEmpty()) { if (checkPermissions(mPermissions)) { isNeedRegister() //TODO return } val deniedAndNoLongerPromptPermissionsName = StringBuilder() for (deniedAndNoLongerPromptPermission in deniedAndNoLongerPromptPermissions) { when (deniedAndNoLongerPromptPermission) { // Manifest.permission.WRITE_EXTERNAL_STORAGE -> { // if (deniedPermissions.contains(deniedAndNoLongerPromptPermission)) // deniedAndNoLongerPromptPermissionsName.append("【存储】") // else // deniedAndNoLongerPromptPermissions.remove( // deniedAndNoLongerPromptPermission // ) // } Manifest.permission.READ_PHONE_STATE -> { if (deniedPermissions.contains(deniedAndNoLongerPromptPermission)) deniedAndNoLongerPromptPermissionsName.append("【手机信息】") else deniedAndNoLongerPromptPermissions.remove( deniedAndNoLongerPromptPermission ) } Manifest.permission.ACCESS_WIFI_STATE -> { if (deniedPermissions.contains(deniedAndNoLongerPromptPermission)) deniedAndNoLongerPromptPermissionsName.append("【访问WIFI信息】") else deniedAndNoLongerPromptPermissions.remove( deniedAndNoLongerPromptPermission ) } } } val rxDialogSureCancel = RxDialogSureCancel(this) rxDialogSureCancel.setContent("需要${deniedAndNoLongerPromptPermissionsName}权限,由于您设置了不再提示,需要手动开启权限!") rxDialogSureCancel.setCancelListener { rxDialogSureCancel.cancel() finish() } rxDialogSureCancel.setSureListener { val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS) val uri = Uri.fromParts("package", packageName, null) intent.data = uri startActivityForResult(intent, PERMISSION_SETTING_REQUEST_CODE) } rxDialogSureCancel.show() Logger.i("${deniedAndNoLongerPromptPermissions.size}需要${deniedAndNoLongerPromptPermissionsName.toString()}权限,由于您设置了不再提示,需要手动开启权限!") } else { if (checkPermissions(mPermissions)) { isNeedRegister() //TODO } else { finish() } } } @RequiresApi(Build.VERSION_CODES.M) override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) if (requestCode == PERMISSION_SETTING_REQUEST_CODE) { if (checkPermissions(mPermissions)) { isNeedRegister() //TODO } else { requestPermissions(deniedPermissions.toTypedArray(), PERMISSION_REQUEST_CODE) } } } private fun toMainPage() { //监测版本是否需要更新 splashAtyVM.appCheck() } private fun toLoginPage() { val intent = Intent(this, LoginActivity::class.java) startActivity(intent) finish() } fun updateLanguage(language: String, locale: Locale) { MMKV.defaultMMKV().encode(BZYConstants.languageInfo, language) val resources = this.resources val metrics = resources.displayMetrics val config = resources.configuration config.locale = locale resources.updateConfiguration(config, metrics) } private fun showUpdateDialog(url: String, illustrate: String, isForce: Boolean) { if (TextUtils.isEmpty(url)) { RxToast.error(resources.getString(R.string.downloadEmpty)) return } var notice = illustrate if (TextUtils.isEmpty(illustrate)) { notice = resources.getString(R.string.NewVersion) } var isDownloaded = false; var isFinish = false var downFilePath = "" val dialog = DialogAppVersion(this, notice, url, isForce, object : DialogAppVersion.OnClickListener { override fun ok(tv_down: TextView, pb_down: ProgressBar) { if (isFinish) { installApk(downFilePath) return } if (isDownloaded) { RxToast.info(resources.getString(R.string.downloading)) return } isDownloaded = true splashAtyVM.downLoadFile(url, object : DownLoadListener { @SuppressLint("SetTextI18n") override fun loading(progress: Int) { lifecycleScope.async { pb_down.progress = progress tv_down.text = resources.getString(R.string.download) + "$progress%" } } override fun finish(path: String) { com.cncat.vpn.common.log.Log.d("down finish path==>$path") isFinish = true downFilePath = path installApk(path) } override fun error(msg: String) { com.cncat.vpn.common.log.Log.d("down error msg==>$msg") } }) } override fun cancel() { val intent = Intent(this@SplashActivity, UIMainActivity::class.java) startActivity(intent) finish() } }) dialog.show() } fun installApk(filePath: String) { val file = File(filePath) val uri: Uri = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { FileProvider.getUriForFile(this, "${applicationContext.packageName}.fileprovider", file) } else { Uri.fromFile(file) } val intent = Intent(Intent.ACTION_VIEW).apply { setDataAndType(uri, "application/vnd.android.package-archive") flags = Intent.FLAG_ACTIVITY_NEW_TASK if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) } } startActivity(intent) } }