添加验证码和隐私政策弹窗(太子指定渠道)

This commit is contained in:
cyh 2025-05-13 15:58:41 +08:00
parent b908465db1
commit 0b6a9433c7
17 changed files with 578 additions and 148 deletions

View File

@ -10,7 +10,7 @@
<uses-feature
android:name="android.hardware.touchscreen"
android:required="false" /> <!-- <uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE" /> -->
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"
@ -43,6 +43,7 @@
android:supportsRtl="true"
android:theme="@style/Theme.Octopus"
tools:ignore="GoogleAppIndexingWarning"
android:usesCleartextTraffic="true"
tools:targetApi="N">
<activity
android:name=".act.InstallApplicationActivity"

View File

@ -1,13 +1,16 @@
package com.yingmao.clash.act
import android.annotation.SuppressLint
import android.content.Intent
import android.content.pm.ActivityInfo
import android.net.Uri
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.text.Html
import android.util.Log
import android.view.View
import android.webkit.WebChromeClient
import android.webkit.WebResourceRequest
import android.webkit.WebSettings
import android.webkit.WebView
import android.webkit.WebViewClient
@ -41,30 +44,43 @@ class AgreementAndPrivacyActivity : BaseActivity() {
settings.javaScriptEnabled = true
settings.domStorageEnabled = true
// settings.setAppCacheMaxSize((1024 * 1024 * 4).toLong())
val appCachePath = applicationContext.cacheDir.absolutePath
// val appCachePath = applicationContext.cacheDir.absolutePath
// settings.setAppCachePath(appCachePath)
settings.allowFileAccess = true
// settings.setAppCacheEnabled(true)
settings.cacheMode = WebSettings.LOAD_NO_CACHE
if (android.os.Build.VERSION.SDK_INT >= 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" -> {

View File

@ -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

View File

@ -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<String>()
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<Bitmap>(){
.into(object : SimpleTarget<Bitmap>() {
override fun onResourceReady(
resource: Bitmap,
transition: Transition<in Bitmap>?
transition: Transition<in Bitmap>?,
) {
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) {

View File

@ -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) {

View File

@ -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"

View File

@ -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()) {

View File

@ -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()) {

View File

@ -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 {

View File

@ -254,32 +254,7 @@ object Utils {
}
}
fun getIPAddress(): String {
try {
val en: Enumeration<NetworkInterface> = NetworkInterface.getNetworkInterfaces()
while (en.hasMoreElements()) {
val intf: NetworkInterface = en.nextElement()
val enumIpAddr: Enumeration<InetAddress> = 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 {

View File

@ -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()
}
}

View File

@ -0,0 +1,92 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
>
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="@drawable/activity_bg"
android:gravity="center"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintWidth_percent="0.8"
tools:ignore="MissingConstraints">
<TextView
android:id="@+id/tv_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:layout_marginBottom="10dp"
android:gravity="center"
android:text="用户协议与隐私政策说明"
android:textColor="@color/blue_4072FE"
android:textSize="16sp"
android:textStyle="bold" />
<LinearLayout
android:id="@+id/rg_pay_type"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="15dp"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:orientation="vertical">
<TextView
android:id="@+id/dialog_agreement_info"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</TextView>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_margin="15dp"
android:layout_height="wrap_content">
<TextView
android:id="@+id/but_cancel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/activity_close_bg"
android:layout_weight="1"
android:gravity="center"
android:paddingTop="5dp"
android:textSize="12sp"
android:layout_marginStart="@dimen/dp_15"
android:layout_marginEnd="@dimen/dp_15"
android:paddingBottom="5dp"
android:text="@string/disagree">
</TextView>
<TextView
android:id="@+id/but_agree"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/activity_jump_bg"
android:textSize="14sp"
android:layout_weight="1"
android:textStyle="bold"
android:gravity="center"
android:text="@string/agree"
android:paddingTop="5dp"
android:paddingBottom="5dp">
</TextView>
</LinearLayout>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -12,6 +12,25 @@
android:layout_height="match_parent"
>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<WebView
android:id="@+id/webView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="invisible"
android:background="@color/main_bg"
/>
<ProgressBar
android:id="@+id/pb_web"
android:visibility="invisible"
android:layout_centerInParent="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:indeterminateTint="@color/blue_0136CB" />
</RelativeLayout>
<LinearLayout
android:visibility="gone"
android:id="@+id/ll_action"

View File

@ -351,4 +351,6 @@ Service Description\n
<string name="sure_restart">Suggest restarting</string>
<string name="restart">Restart</string>
<string name="node_item_test">Speed test</string>
<string name="agree">Agree</string>
<string name="disagree">Disagree</string>
</resources>

View File

@ -341,4 +341,6 @@
<string name="sure_restart">"建議重啓 "</string>
<string name="restart">"重啓 "</string>
<string name="node_item_test">線路測速</string>
<string name="agree">同意</string>
<string name="disagree">不同意</string>
</resources>

View File

@ -340,4 +340,6 @@
<string name="sure_restart">"建議重啓 "</string>
<string name="restart">"重啓 "</string>
<string name="node_item_test">線路測速</string>
<string name="agree">同意</string>
<string name="disagree">不同意</string>
</resources>

View File

@ -131,6 +131,7 @@
<string name="CheckLoginFailure">检查登录失败</string>
<string name="LoginException">登录异常</string>
<string name="AgreeAgreement">同意《隐私协议》和《用户协议》</string>
<string name="AgreeAgreement2">请您充分阅读并理解《隐私政策》和《用户协议》我们非常重视您的隐私和个人信息,在您使用过程中,我们会收集部分个人信息。例如,会申请设备信息等。您可以点击《用户协议》和《隐私政策》查看详细内容。您可以选择“同意”继续使用我们的服务,或者选择“不同意”退出。</string>
<string name="ReadAgreement">请仔细阅读并同意《隐私协议》和《用户协议》</string>
<string name="loginTips">小提示:自动注册初始密码为 123456手动注册请忽略</string>
<string name="LoginTips2">小提示2华为鸿蒙系统由于鉴定机制的问题将App误报为诈骗软件请忽略正常放心使用有任何问题联系客服及售后</string>
@ -359,4 +360,6 @@
<string name="sure_restart">建议重启</string>
<string name="restart">重启</string>
<string name="node_item_test">线路测速</string>
<string name="agree">同意</string>
<string name="disagree">不同意</string>
</resources>