diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index dc576d9..83af42f 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -10,7 +10,7 @@ - + = android.os.Build.VERSION_CODES.LOLLIPOP) { settings.mixedContentMode = WebSettings.MIXED_CONTENT_ALWAYS_ALLOW } - webView.webViewClient = object : WebViewClient() { - override fun shouldOverrideUrlLoading(view: WebView, url: String): Boolean { - Logger.d("访问的url地址:$url") - return true - } - } +// webView.webViewClient = object : WebViewClient() { +// override fun shouldOverrideUrlLoading(view: WebView, url: String): Boolean { +// Logger.d("访问的url地址:$url") +// return true +// } +// } webView.webChromeClient = object : WebChromeClient() { override fun onProgressChanged(view: WebView?, newProgress: Int) { } } + // 处理所有点击跳转 + webView.webViewClient = object : WebViewClient() { + override fun shouldOverrideUrlLoading(view: WebView, request: WebResourceRequest): Boolean { + + val url = request.url.toString() + com.cncat.vpn.common.log.Log.d("shouldOverrideUrlLoading url ==>${url}") + // 可选:跳转外部浏览器 + val intent = Intent(Intent.ACTION_VIEW, Uri.parse(url)) + view.context.startActivity(intent) + return true // 表示拦截并自处理 + } + } } fun loadAgreeHtml(){ if (BuildConfig.is_ym){ webView.loadUrl("file:android_asset/agreement.html") }else if (BuildConfig.is_tz){ - webView.loadUrl("file:android_asset/agreement_taizi_hk.html") + webView.loadUrl("https://www.taiziapp.com/agreement.html") } else{ webView.loadUrl("file:android_asset/agreement_bzy.html") @@ -75,7 +91,7 @@ class AgreementAndPrivacyActivity : BaseActivity() { if (BuildConfig.is_ym){ webView.loadUrl("file:android_asset/privacy.html") } else if (BuildConfig.is_tz){ - webView.loadUrl("file:android_asset/privacy_hk.html") + webView.loadUrl("https://www.taiziapp.com/privacy.html") } else{ webView.loadUrl("file:android_asset/privacy_bzy.html") @@ -95,7 +111,7 @@ class AgreementAndPrivacyActivity : BaseActivity() { if (language.equals("en")) { webView.loadUrl("file:android_asset/agreement_en.html") } else if (language.equals("zh") && country.equals("HK")) { - webView.loadUrl("file:android_asset/agreement_hk.html") + loadAgreeHtml() } else { loadAgreeHtml() } @@ -106,7 +122,7 @@ class AgreementAndPrivacyActivity : BaseActivity() { } "Chinese-HK" -> { - webView.loadUrl("file:android_asset/agreement_hk.html") + loadAgreeHtml() } "English" -> { @@ -125,7 +141,7 @@ class AgreementAndPrivacyActivity : BaseActivity() { if (language.equals("en")) { webView.loadUrl("file:android_asset/privacy_en.html") } else if (language.equals("zh") && country.equals("HK")) { - webView.loadUrl("file:android_asset/privacy_hk.html") + loadPriHtml() } else { loadPriHtml() } @@ -136,7 +152,7 @@ class AgreementAndPrivacyActivity : BaseActivity() { } "Chinese-HK" -> { - webView.loadUrl("file:android_asset/privacy_hk.html") + loadPriHtml() } "English" -> { diff --git a/app/src/main/java/com/yingmao/clash/act/RegisterActivity.kt b/app/src/main/java/com/yingmao/clash/act/RegisterActivity.kt index a0625aa..8331647 100644 --- a/app/src/main/java/com/yingmao/clash/act/RegisterActivity.kt +++ b/app/src/main/java/com/yingmao/clash/act/RegisterActivity.kt @@ -23,7 +23,6 @@ import com.yingmao.clash.net.http.HttpStatus import com.yingmao.clash.net.http.entity.RegisterRsp import com.yingmao.clash.util.AESUtil import com.yingmao.clash.util.CommonUtils -import com.yingmao.clash.util.Utils import com.yingmao.clash.view.PasswordTransformationMethodBigDot import com.yingmao.clash.view.RxToast import com.yingmao.clash.view.SlidingVerification @@ -146,7 +145,7 @@ class RegisterActivity : BaseActivity(), View.OnClickListener { req_json.addProperty("password", password) req_json.addProperty("checkPassword", password) req_json.addProperty("invitationCode", BuildConfig.productId) - req_json.addProperty("clientIp", Utils.getIPAddress()) + req_json.addProperty("clientIp", "127.0.0.1") req_json.addProperty("from", "5") var data = AESUtil.byteArrayToHexStr( AESUtil.encrypt(req_json.toString()) @@ -187,14 +186,14 @@ class RegisterActivity : BaseActivity(), View.OnClickListener { Log.d("it.progress==>${it.progress}") if (it.progress >= it.max) { it.isEnabled = false - verificationSv.progress=it.max + verificationSv.progress = it.max verificationTipTv.text = getString(R.string.verification_success) verificationTipTv.setTextColor(R.color.black) verificationSv.setProgressDrawableTiled(getDrawable(R.drawable.login_btn_bg_selector)) if (!checkInput()) { - }else { + } else { } } else it.progress = 0 diff --git a/app/src/main/java/com/yingmao/clash/act/SplashActivity.kt b/app/src/main/java/com/yingmao/clash/act/SplashActivity.kt index 0143ca1..dc5da34 100644 --- a/app/src/main/java/com/yingmao/clash/act/SplashActivity.kt +++ b/app/src/main/java/com/yingmao/clash/act/SplashActivity.kt @@ -2,6 +2,7 @@ package com.yingmao.clash.act import android.Manifest import android.annotation.SuppressLint +import android.content.Context import android.content.Intent import android.content.pm.PackageManager import android.graphics.Bitmap @@ -10,10 +11,17 @@ import android.net.Uri import android.os.Build import android.os.Bundle import android.provider.Settings +import android.text.SpannableString +import android.text.TextPaint import android.text.TextUtils +import android.text.style.ClickableSpan import android.util.Log import android.view.View import android.view.WindowManager +import android.webkit.JavascriptInterface +import android.webkit.WebSettings +import android.webkit.WebView +import android.webkit.WebViewClient import android.widget.ProgressBar import android.widget.RelativeLayout import android.widget.TextView @@ -56,6 +64,7 @@ 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.DialogAgreementPrivacyChoose import com.yingmao.clash.view.dialog.DialogAppVersion import com.yingmao.clash.view.dialog.DialogDoMainChoose import com.yingmao.clash.view.dialog.RxDialogSureCancel @@ -73,14 +82,21 @@ class SplashActivity : BaseActivity() { private val mPermissions = hashSetOf() private val PERMISSION_REQUEST_CODE: Int = 1 private val PERMISSION_SETTING_REQUEST_CODE = 2 + private val Captcha_REQUEST_CODE = 3333 private lateinit var rlPb: View private lateinit var ll_action: View - private lateinit var username: String - private lateinit var rlMain: RelativeLayout + + private lateinit var rlMain: RelativeLayout private lateinit var splashAtyVM: SplashAtyVM - private var registerKey = "" - private var registerIV2 = "" + + companion object { + public var registerKey = "" + public var registerIV2 = "" + public lateinit var username: String + } + + private var captchaInfo = "" private var initErrMsg = "" override fun onCreate(savedInstanceState: Bundle?) { @@ -89,13 +105,13 @@ class SplashActivity : BaseActivity() { 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) + rlMain = findViewById(R.id.rlMain) rlPb = findViewById(R.id.rl_pb) ll_action = findViewById(R.id.ll_action) @@ -107,8 +123,14 @@ class SplashActivity : BaseActivity() { serStore.isBZY = true } } + if (BuildConfig.productId=="182268"){ - + }else{ + //隐私政策先授权后获取 + username = Utils.getUniqueID(this) + MainApplication.initUtil() + } + initWebView() // mPermissions.add(Manifest.permission.READ_PHONE_STATE) // mPermissions.add(Manifest.permission.INTERNET) // mPermissions.add(Manifest.permission.ACCESS_NETWORK_STATE) @@ -179,8 +201,7 @@ class SplashActivity : BaseActivity() { // "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" +// "" // ) // ) // ) @@ -202,55 +223,14 @@ class SplashActivity : BaseActivity() { } } } -// 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) +// val Sgtr= AESUtil.decrypt("73CC9D719D4B46616F7FB72DBFABFA88B716D1AF0F8B8A42929F9EE5D198EB059A7934DD0074D1810CD56B5312FD5FDACC25EED6C6B2351DB11A3BF78E3010A417CDE40EEFF768849AEF25773AF541C01464DB7C9B0B7C30D36EEA414EA86F9923AAF325C15BB75170C148C4F257AA2D6A32BFB582D498B13B38E49BB8DF1663") // println("Sgtr==>$Sgtr") - // OpenInstall.getWakeUp(intent, wakeUpAdapter) // OpenInstall.getInstall { appData, error -> // var appData = appData @@ -281,6 +261,104 @@ class SplashActivity : BaseActivity() { // 此处要调用,否则App在后台运行时,会无法获取 // OpenInstall.getWakeUp(intent, wakeUpAdapter) } + + private lateinit var webView: WebView + private lateinit var pb_web: ProgressBar + var dialogAgreementPrivacyChoose: DialogAgreementPrivacyChoose? = null + private fun initAgreementPrivacy(){ + if (BuildConfig.is_tz && BuildConfig.productId == "182268") { + if (dialogAgreementPrivacyChoose == null) { + dialogAgreementPrivacyChoose = DialogAgreementPrivacyChoose(this@SplashActivity) + } + if (dialogAgreementPrivacyChoose?.isShowing == false) { + dialogAgreementPrivacyChoose?.setOnTryButtonListener(object : + DialogAgreementPrivacyChoose.OnTryButtonListener { + override fun agree() { + username = Utils.getUniqueID(this@SplashActivity) + MainApplication.initUtil() + dialogAgreementPrivacyChoose?.dismiss() + } + + override fun cancel() { + dialogAgreementPrivacyChoose?.dismiss() + finish() + } + }) + dialogAgreementPrivacyChoose?.show() + } + } + } + private fun initWebView() { + + webView = findViewById(R.id.webView) + pb_web = findViewById(R.id.pb_web) + + if (!BuildConfig.is_ym) { + + rlPb.visibility = View.INVISIBLE + } else { + webView.visibility = View.GONE + } + } + + @SuppressLint("JavascriptInterface") + private fun setWebView() { + initAgreementPrivacy() + // WebView设置 + val webSettings = webView.settings + // 可选,设置开启Chrome调试 + WebView.setWebContentsDebuggingEnabled(true) + // 设置屏幕自适应 + webSettings.useWideViewPort = true + webSettings.loadWithOverviewMode = true + // 建议禁止缓存加载,以确保在攻击发生时可快速获取最新的阿里云验证码2.0进行对抗 + webSettings.cacheMode = WebSettings.LOAD_NO_CACHE + // 设置WebView组件支持加载JavaScript + webSettings.javaScriptEnabled = true + webSettings.domStorageEnabled = true + + + // 设置不使用默认浏览器,而直接使用WebView组件加载页面 + webView.webViewClient = object : WebViewClient() { + override fun shouldOverrideUrlLoading(view: WebView, url: String): Boolean { + view.loadUrl(url) + return true + } + } + webView.addJavascriptInterface(CaptchaJsInterface(), "CaptchaJsInterface") +// testWebview.addJavascriptInterface(new testJsInterface(), "testInterface"); + // 加载业务页面 + webView.loadUrl("file:///android_asset/captcha.html") +// webView.loadUrl("https://api.yingmaovpnpro.win:18002/78zccgy0nsgknh9n4/captcha.html") + } + + inner class CaptchaJsInterface() { + + @JavascriptInterface + public fun getVerifyResult(verifyResult: String): Boolean { + com.cncat.vpn.common.log.Log.d("verifyResult==>${verifyResult}") + captchaInfo = verifyResult + + launch { + webView.setOnTouchListener { _, _ -> true } + pb_web.visibility = View.VISIBLE + } + + + + doRegisterByEncryption() + return true + } + } + + private class CaptchaJsSuccessInterface { + @JavascriptInterface + public fun result(verifyResult: String) { +// Log.d("verifyResult==>${verifyResult}") + + } + } + private fun setLocalLanguage() { var defLan = "" if (BuildConfig.is_tz) { @@ -386,7 +464,14 @@ class SplashActivity : BaseActivity() { splashAtyVM.checkLogin() } else { // doRegister() - doRegisterByEncryption() + if (!BuildConfig.is_ym) { + rlPb.visibility = View.INVISIBLE + webView.visibility = View.VISIBLE + setWebView() + } else { + webView.visibility = View.GONE + doRegisterByEncryption() + } } } else {//非渠道自由包 val token = MMKV.defaultMMKV().decodeString(BZYConstants.MMKV_KEY_TOKEN) @@ -424,7 +509,7 @@ class SplashActivity : BaseActivity() { "password" to BZYConstants.defaultPassword, "checkPassword" to BZYConstants.defaultPassword, "id" to BuildConfig.productId, - "clientIp" to Utils.getIPAddress(), + "clientIp" to "127.0.0.1", "from" to "5", ) splashAtyVM.register(params) @@ -432,14 +517,16 @@ class SplashActivity : BaseActivity() { @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("clientIp", "127.0.0.1") req_json.addProperty("from", "5") req_json.addProperty("androidDevice", username) + if (captchaInfo.isNotEmpty()) { + req_json.addProperty("captchaVerifyParam", captchaInfo) + } if (registerKey.isNotEmpty() && registerIV2.isNotEmpty()) { val data = AESUtil.byteArrayToHexStr( AESUtil.RegisterEncrypt(req_json.toString(), registerKey, registerIV2) @@ -543,6 +630,7 @@ class SplashActivity : BaseActivity() { // // } + @SuppressLint("ClickableViewAccessibility") override fun httpSuccess(httpStatus: HttpStatus.Success) { when (httpStatus.reqType) { HttpReqType.REGISTER -> { @@ -602,6 +690,12 @@ class SplashActivity : BaseActivity() { startActivity(intent) finish() // graphicVerificationDialog() + } else if (code == "403") { + pb_web.visibility = View.INVISIBLE + message?.let { + RxToast.error(it) + } + webView.setOnTouchListener { _, _ -> false } } else { MaterialDialog(this@SplashActivity).show { message(text = initErrMsg) @@ -676,19 +770,23 @@ class SplashActivity : BaseActivity() { } } } - HttpReqType.SplashBg->{ + + 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) + 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(){ + .into(object : SimpleTarget() { override fun onResourceReady( resource: Bitmap, - transition: Transition? + transition: Transition?, ) { val bitmapDrawable = BitmapDrawable(resource) rlMain.setBackgroundDrawable(bitmapDrawable) @@ -701,7 +799,8 @@ class SplashActivity : BaseActivity() { } } - HttpReqType.App_VERION_CHECK->{ + + 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) { @@ -714,13 +813,13 @@ class SplashActivity : BaseActivity() { if (!TextUtils.isEmpty(md.versionPath)) { showUpdateDialog(md.versionPath!!, md.illustrate!!, false) } - }else{ + } else { val intent = Intent(this@SplashActivity, UIMainActivity::class.java) startActivity(intent) finish() } } - }else{ + } else { val intent = Intent(this@SplashActivity, UIMainActivity::class.java) startActivity(intent) finish() @@ -737,14 +836,14 @@ class SplashActivity : BaseActivity() { when (httpStatus.reqType) { HttpReqType.REGISTER -> { rlPb.visibility = View.GONE - + pb_web.visibility = View.INVISIBLE com.cncat.vpn.common.log.Log.d("httpFailure HttpReqType.REGISTER") try { RxToast.error("检测到网络异常,请尝试切换其他地址.") - if (dialogDoMainChoose==null) { + if (dialogDoMainChoose == null) { dialogDoMainChoose = DialogDoMainChoose(this@SplashActivity) } - if (dialogDoMainChoose?.isShowing==false){ + if (dialogDoMainChoose?.isShowing == false) { dialogDoMainChoose?.setOnTryButtonListener(object : DialogDoMainChoose.OnTryButtonListener { override fun tryButton() { @@ -757,7 +856,7 @@ class SplashActivity : BaseActivity() { override fun cancel() { com.cncat.vpn.common.log.Log.d("tryButton REGISTER cancel") dialogDoMainChoose?.dismiss() - dialogDoMainChoose=null + dialogDoMainChoose = null } }) dialogDoMainChoose?.setOnListItemListener(object : @@ -817,15 +916,18 @@ class SplashActivity : BaseActivity() { SplashHelper(splashAtyVM).getHostWithFallback { success -> MainScope().launch { if (success) { - if (dialogDoMainChoose==null) { + if (dialogDoMainChoose == null) { dialogDoMainChoose = DialogDoMainChoose(this@SplashActivity) } - if (dialogDoMainChoose?.isShowing==false){ + if (dialogDoMainChoose?.isShowing == false) { dialogDoMainChoose?.setOnTryButtonListener(object : DialogDoMainChoose.OnTryButtonListener { override fun tryButton() { var currentHost = MMKV.defaultMMKV() - .decodeString(BZYConstants.MMKV_KEY_CURRENT_HOST, "") + .decodeString( + BZYConstants.MMKV_KEY_CURRENT_HOST, + "" + ) // com.cncat.vpn.common.log.Log.d("tryButton CHECK_LOGIN currentHost==>${currentHost}") splashAtyVM.checkLogin() } @@ -974,13 +1076,23 @@ class SplashActivity : BaseActivity() { @RequiresApi(Build.VERSION_CODES.M) override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) + com.cncat.vpn.common.log.Log.d("onActivityResult requestCode==>${requestCode}") if (requestCode == PERMISSION_SETTING_REQUEST_CODE) { if (checkPermissions(mPermissions)) { isNeedRegister() //TODO } else { requestPermissions(deniedPermissions.toTypedArray(), PERMISSION_REQUEST_CODE) } + } else if (requestCode == Captcha_REQUEST_CODE) { + + + captchaInfo = + data?.extras?.getString(BZYConstants.REQUEST_CODE_Captcha_Result_Key).toString() + com.cncat.vpn.common.log.Log.d("onActivityResult captchaInfo==>${captchaInfo}") + doRegisterByEncryption() + } + } private fun toMainPage() { @@ -1002,6 +1114,7 @@ class SplashActivity : BaseActivity() { 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)) @@ -1061,6 +1174,7 @@ class SplashActivity : BaseActivity() { }) dialog.show() } + fun installApk(filePath: String) { val file = File(filePath) val uri: Uri = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { diff --git a/app/src/main/java/com/yingmao/clash/app/MainApplication.kt b/app/src/main/java/com/yingmao/clash/app/MainApplication.kt index 05b2c25..cc8a2a2 100644 --- a/app/src/main/java/com/yingmao/clash/app/MainApplication.kt +++ b/app/src/main/java/com/yingmao/clash/app/MainApplication.kt @@ -64,7 +64,7 @@ class MainApplication : Application() { userBean = bean } - fun restartApp(activity: Activity,listener:OnRestartButtonListener) { + fun restartApp(activity: Activity, listener: OnRestartButtonListener) { var dialogDoMainChoose = DialogSureRestartChoose(activity) if (!dialogDoMainChoose.isShowing) { @@ -91,11 +91,49 @@ class MainApplication : Application() { } + fun initUtil() { + getApp()?.let { mainApplication -> + + + /* + * 错误日志上传捕获 + * */ + val crashCatchHandler: CrashCatchHandler = CrashCatchHandler.getInstance() //获得单例 + crashCatchHandler.init(mainApplication) //初始化,传入context + + if (DeviceID.supportedOAID(mainApplication)) { + // 获取OAID/AAID,异步回调 + DeviceID.getOAID(mainApplication, object : IGetter { + override fun onOAIDGetComplete(result: String) { + // 不同厂商的OAID/AAID格式是不一样的,可进行MD5、SHA1之类的哈希运算统一 + Log.d("onOAIDGetComplete ${result}") + OAID = result + } + + override fun onOAIDGetError(error: Exception) { + // 获取OAID/AAID失败 + error.printStackTrace() + } + }) + } + //openinstall +// OpenInstall.init(applicationContext); + PaymentConfiguration.init( + mainApplication, + "pk_live_51Nkl6vLWP3xWXY4LfXtdMtXzHazv6pav2rH1p1BfICeh5meGGjglExiw4GgmSzWO7NptEM1c549Fe11zRy9nCfxs009zEwLpXP" + ) +// OpenInstall.preInit(applicationContext) +// OpenInstall.init(applicationContext) + } + } + } - interface OnRestartButtonListener{ + + interface OnRestartButtonListener { fun enterButton() fun cancelButton() } + override fun attachBaseContext(base: Context?) { super.attachBaseContext(base) } @@ -121,37 +159,7 @@ class MainApplication : Application() { val MMKVRootDir = MMKV.initialize(applicationContext) Logger.i("MMKV_ROOT_DIR:$MMKVRootDir") updateNotificationChannels() - /* - * 错误日志上传捕获 - * */ - val crashCatchHandler: CrashCatchHandler = CrashCatchHandler.getInstance() //获得单例 - crashCatchHandler.init(applicationContext) //初始化,传入context - if (DeviceID.supportedOAID(applicationContext)) { - // 获取OAID/AAID,异步回调 - DeviceID.getOAID(applicationContext, object : IGetter { - override fun onOAIDGetComplete(result: String) { - // 不同厂商的OAID/AAID格式是不一样的,可进行MD5、SHA1之类的哈希运算统一 - Log.d("onOAIDGetComplete ${result}") - OAID = result - } - - override fun onOAIDGetError(error: Exception) { - // 获取OAID/AAID失败 - error.printStackTrace() - } - }) - } - - - //openinstall -// OpenInstall.init(applicationContext); - PaymentConfiguration.init( - applicationContext, - "pk_live_51Nkl6vLWP3xWXY4LfXtdMtXzHazv6pav2rH1p1BfICeh5meGGjglExiw4GgmSzWO7NptEM1c549Fe11zRy9nCfxs009zEwLpXP" - ) -// OpenInstall.preInit(applicationContext) -// OpenInstall.init(applicationContext) } fun updateActivity(language: String, locale: Locale) { diff --git a/app/src/main/java/com/yingmao/clash/conf/BZYConstants.kt b/app/src/main/java/com/yingmao/clash/conf/BZYConstants.kt index 0fbf6d2..253f546 100644 --- a/app/src/main/java/com/yingmao/clash/conf/BZYConstants.kt +++ b/app/src/main/java/com/yingmao/clash/conf/BZYConstants.kt @@ -38,6 +38,8 @@ class BZYConstants { const val REQUEST_CODE_PAY_WEB_Stripe = 1001 const val REQUEST_CODE_PAY_WEB_BiLai = 1002 + const val REQUEST_CODE_Captcha_Result_Key = "REQUEST_CODE_Captcha_Result_Key" + //是否需要完善资料 const val MMKV_KEY_IS_PERFECT = "isPerfect" diff --git a/app/src/main/java/com/yingmao/clash/fragment/home/HomeFragment.kt b/app/src/main/java/com/yingmao/clash/fragment/home/HomeFragment.kt index 1c30731..2df728a 100644 --- a/app/src/main/java/com/yingmao/clash/fragment/home/HomeFragment.kt +++ b/app/src/main/java/com/yingmao/clash/fragment/home/HomeFragment.kt @@ -186,7 +186,9 @@ class HomeFragment : BaseFragment(), CoroutineScope by CoroutineScope(Dispatcher llLine = view.findViewById(R.id.llLine) clActivity = view.findViewById(R.id.clActivity) clMember = view.findViewById(R.id.clMember) - + if (BuildConfig.productId=="182268"&&BuildConfig.is_tz){ + clActivity.visibility=View.INVISIBLE + } llLine.setOnClickListener { if (checkExpire()) { diff --git a/app/src/main/java/com/yingmao/clash/fragment/setting/SettingFragment.kt b/app/src/main/java/com/yingmao/clash/fragment/setting/SettingFragment.kt index 7ba03e6..4dc1c16 100644 --- a/app/src/main/java/com/yingmao/clash/fragment/setting/SettingFragment.kt +++ b/app/src/main/java/com/yingmao/clash/fragment/setting/SettingFragment.kt @@ -250,6 +250,11 @@ class SettingFragment : BaseFragment(), CoroutineScope by CoroutineScope(Dispatc tvVersion = view.findViewById(R.id.tvVersion) clFire = view.findViewById(R.id.clFire) + if (BuildConfig.productId=="182268" && BuildConfig.is_tz){ + clFire.visibility=View.GONE + clTelegraph.visibility=View.GONE + clPreventLoss.visibility=View.INVISIBLE + } setExpireDate() if (checkExpire()) { diff --git a/app/src/main/java/com/yingmao/clash/net/http/NetService.kt b/app/src/main/java/com/yingmao/clash/net/http/NetService.kt index dba2407..e05d3fa 100644 --- a/app/src/main/java/com/yingmao/clash/net/http/NetService.kt +++ b/app/src/main/java/com/yingmao/clash/net/http/NetService.kt @@ -59,6 +59,7 @@ class NetService private constructor() : INetService { // "https://api.gaogaoshousoft.cc:18001" // "https://api.yingmaox.cc:8700" // "https://113.108.210.50:21002" +// "https://bc5b-14-146-29-2.ngrok-free.app" MMKV.defaultMMKV().decodeString(BZYConstants.MMKV_KEY_CURRENT_HOST, BuildConfig.service_url)!! // MMKV.defaultMMKV().decodeString(BZYConstants.MMKV_KEY_CURRENT_HOST, "https://app.bazhuayujiasu.cc:18001") } else { diff --git a/app/src/main/java/com/yingmao/clash/util/Utils.kt b/app/src/main/java/com/yingmao/clash/util/Utils.kt index 4e8dd07..bd68f1d 100644 --- a/app/src/main/java/com/yingmao/clash/util/Utils.kt +++ b/app/src/main/java/com/yingmao/clash/util/Utils.kt @@ -254,32 +254,7 @@ object Utils { } } - fun getIPAddress(): String { - try { - val en: Enumeration = NetworkInterface.getNetworkInterfaces() - while (en.hasMoreElements()) { - val intf: NetworkInterface = en.nextElement() - val enumIpAddr: Enumeration = intf.getInetAddresses() - while (enumIpAddr.hasMoreElements()) { - val inetAddress: InetAddress = enumIpAddr.nextElement() - if (!inetAddress.isLoopbackAddress() && !inetAddress.isLinkLocalAddress() && inetAddress.isSiteLocalAddress()) { - return inetAddress.getHostAddress() - } - } - } - } catch (e: java.lang.Exception) { - e.printStackTrace() - } - return "0.0.0.0" - } - fun getIPAddress(context: Context): String? { - val wifiManager = - context.applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager - val wifiInfo = wifiManager.connectionInfo - val ipAddress = wifiInfo.ipAddress - return (ipAddress and 0xFF).toString() + "." + (ipAddress shr 8 and 0xFF) + "." + (ipAddress shr 16 and 0xFF) + "." + (ipAddress shr 24 and 0xFF) - } public fun isAppInstalled(context: Context, packageName: String): Boolean { return try { diff --git a/app/src/main/java/com/yingmao/clash/view/dialog/DialogAgreementPrivacyChoose.kt b/app/src/main/java/com/yingmao/clash/view/dialog/DialogAgreementPrivacyChoose.kt new file mode 100644 index 0000000..b2088f9 --- /dev/null +++ b/app/src/main/java/com/yingmao/clash/view/dialog/DialogAgreementPrivacyChoose.kt @@ -0,0 +1,187 @@ +package com.yingmao.clash.view.dialog + +import android.annotation.SuppressLint +import android.app.Activity +import android.content.Context +import android.content.DialogInterface +import android.content.Intent +import android.graphics.Color +import android.text.Spannable +import android.text.SpannableStringBuilder +import android.text.TextUtils +import android.text.method.LinkMovementMethod +import android.text.style.BackgroundColorSpan +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.Button +import android.widget.TextView +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView +import com.chad.library.adapter.base.BaseQuickAdapter +import com.cncat.vpn.common.log.Log +import com.tencent.mmkv.MMKV + +import com.yingmao.clash.R +import com.yingmao.clash.act.AgreementAndPrivacyActivity +import com.yingmao.clash.act.MyClickableSpan +import com.yingmao.clash.act.UIMainActivity +import com.yingmao.clash.conf.BZYConstants +import com.yingmao.clash.entity.DomainItemBean + +import com.yingmao.clash.view.adapter.DomainListAdapter + + +/** + * @author tamsiree + * @date 2016/7/19 + * 确认 取消 Dialog + */ +open class DialogAgreementPrivacyChoose : RxDialog { + lateinit var titleView: TextView + private set + lateinit var but_agree: TextView + private set + lateinit var but_cancel: TextView + private set + lateinit var dialog_agreement_info: TextView + private set + lateinit var onTryListener: OnTryButtonListener + + lateinit var onDomainListItemListener: OnListItemListener + + constructor(context: Context?, themeResId: Int) : super(context!!, themeResId) { + initView() + } + + constructor( + context: Context?, + cancelable: Boolean, + cancelListener: DialogInterface.OnCancelListener?, + ) : super(context!!, cancelable, cancelListener) { + initView() + } + + constructor(context: Context?) : super(context!!) { + initView() + } + + constructor(context: Activity?) : super(context!!) { + initView() + } + + constructor(context: Context?, alpha: Float, gravity: Int) : super(context, alpha, gravity) { + initView() + } + + + @SuppressLint("MissingInflatedId") + private fun initView() { + val dialogView = + LayoutInflater.from(context).inflate(R.layout.dialog_agreement_privacy_choose, null) + titleView = dialogView.findViewById(R.id.tv_title) + but_agree = dialogView.findViewById(R.id.but_agree) + but_cancel = dialogView.findViewById(R.id.but_cancel) + dialog_agreement_info = dialogView.findViewById(R.id.dialog_agreement_info) + + initUserAgreementView(context, dialog_agreement_info) + + but_agree.setOnClickListener { + onTryListener.agree() + } + but_cancel.setOnClickListener { onTryListener.cancel() } + + setContentView(dialogView) + setCancelable(false) + window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT) + + + } + + private fun initUserAgreementView(activity: Context, textView: TextView) { + var privacy_s = 16 + var privacy_e = 22 + var agreement_s = 9 + var agreement_e = 15 + + val spannableStringBuilder = + SpannableStringBuilder(activity.resources.getString(R.string.AgreeAgreement2)) + val clickableSpan: MyClickableSpan = object : MyClickableSpan() { + override fun onClick(view: View) { + val backgroundColorSpan = BackgroundColorSpan(Color.parseColor("#4072FE")) + spannableStringBuilder.setSpan( + backgroundColorSpan, + agreement_s, + agreement_e, + Spannable.SPAN_EXCLUSIVE_INCLUSIVE + ) + textView.text = spannableStringBuilder + val intent = Intent(activity, AgreementAndPrivacyActivity::class.java) + intent.putExtra( + BZYConstants.EXTRA_KEY_AGREEMENT, + BZYConstants.EXTRA_PRIVACY_AGREEMENT + ) + activity.startActivity(intent) + } + } + spannableStringBuilder.setSpan( + clickableSpan, + agreement_s, + agreement_e, + Spannable.SPAN_EXCLUSIVE_INCLUSIVE + ) + + val privacyClickableSpan: MyClickableSpan = object : MyClickableSpan() { + override fun onClick(view: View) { + val backgroundColorSpan = BackgroundColorSpan(Color.parseColor("#4072FE")) + spannableStringBuilder.setSpan( + backgroundColorSpan, + privacy_s, + privacy_e, + Spannable.SPAN_EXCLUSIVE_INCLUSIVE + ) + textView.text = spannableStringBuilder + val intent = Intent(activity, AgreementAndPrivacyActivity::class.java) + intent.putExtra( + BZYConstants.EXTRA_KEY_AGREEMENT, + BZYConstants.EXTRA_USER_AGREEMENT + ) + activity.startActivity(intent) + } + } + spannableStringBuilder.setSpan( + privacyClickableSpan, + privacy_s, + privacy_e, + Spannable.SPAN_EXCLUSIVE_INCLUSIVE + ) + textView.text = spannableStringBuilder + textView.movementMethod = LinkMovementMethod.getInstance() + + + } + + fun setOnTryButtonListener(listener: OnTryButtonListener) { + this.onTryListener = listener + } + + fun setOnListItemListener(listener: OnListItemListener) { + this.onDomainListItemListener = listener + } + + + private fun changeSubUrl(originalUrl: String, newUrl: String): String { + return originalUrl.replace(Regex("https://[^/]+/"), "$newUrl/") + + } + + interface OnTryButtonListener { + fun agree() + fun cancel() + } + + interface OnListItemListener { + fun listItemClick() + + } +} \ No newline at end of file diff --git a/app/src/main/res/layout/dialog_agreement_privacy_choose.xml b/app/src/main/res/layout/dialog_agreement_privacy_choose.xml new file mode 100644 index 0000000..68b271b --- /dev/null +++ b/app/src/main/res/layout/dialog_agreement_privacy_choose.xml @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/layout_splash_activity.xml b/app/src/main/res/layout/layout_splash_activity.xml index 09c57cd..c3a5ba2 100644 --- a/app/src/main/res/layout/layout_splash_activity.xml +++ b/app/src/main/res/layout/layout_splash_activity.xml @@ -12,6 +12,25 @@ android:layout_height="match_parent" > + + + + + Suggest restarting Restart Speed test + Agree + Disagree \ No newline at end of file diff --git a/app/src/main/res/values-zh-rHK/strings.xml b/app/src/main/res/values-zh-rHK/strings.xml index 5d9881f..02399cc 100644 --- a/app/src/main/res/values-zh-rHK/strings.xml +++ b/app/src/main/res/values-zh-rHK/strings.xml @@ -341,4 +341,6 @@ "建議重啓 " "重啓 " 線路測速 + 同意 + 不同意 \ No newline at end of file diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index cb6a362..8e4b81f 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -340,4 +340,6 @@ "建議重啓 " "重啓 " 線路測速 + 同意 + 不同意 \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index fd4a078..bd488dd 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -131,6 +131,7 @@ 检查登录失败 登录异常 同意《隐私协议》和《用户协议》 + 请您充分阅读并理解《隐私政策》和《用户协议》我们非常重视您的隐私和个人信息,在您使用过程中,我们会收集部分个人信息。例如,会申请设备信息等。您可以点击《用户协议》和《隐私政策》查看详细内容。您可以选择“同意”继续使用我们的服务,或者选择“不同意”退出。 请仔细阅读并同意《隐私协议》和《用户协议》 小提示:自动注册初始密码为 123456,手动注册请忽略 小提示2:华为鸿蒙系统由于鉴定机制的问题,将App误报为诈骗软件,请忽略正常放心使用,有任何问题联系客服及售后 @@ -359,4 +360,6 @@ 建议重启 重启 线路测速 + 同意 + 不同意 \ No newline at end of file