增加防篡改控制
This commit is contained in:
3
.idea/.gitignore
generated
vendored
3
.idea/.gitignore
generated
vendored
@@ -1,3 +0,0 @@
|
|||||||
# Default ignored files
|
|
||||||
/shelf/
|
|
||||||
/workspace.xml
|
|
||||||
6
.idea/AndroidProjectSystem.xml
generated
6
.idea/AndroidProjectSystem.xml
generated
@@ -1,6 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="AndroidProjectSystem">
|
|
||||||
<option name="providerId" value="com.android.tools.idea.GradleProjectSystem" />
|
|
||||||
</component>
|
|
||||||
</project>
|
|
||||||
6
.idea/compiler.xml
generated
6
.idea/compiler.xml
generated
@@ -1,6 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="CompilerConfiguration">
|
|
||||||
<bytecodeTargetLevel target="1.7" />
|
|
||||||
</component>
|
|
||||||
</project>
|
|
||||||
18
.idea/deploymentTargetSelector.xml
generated
18
.idea/deploymentTargetSelector.xml
generated
@@ -1,18 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="deploymentTargetSelector">
|
|
||||||
<selectionStates>
|
|
||||||
<SelectionState runConfigName="app">
|
|
||||||
<option name="selectionMode" value="DROPDOWN" />
|
|
||||||
<DropdownSelection timestamp="2026-09-10T09:58:20.491101800Z">
|
|
||||||
<Target type="DEFAULT_BOOT">
|
|
||||||
<handle>
|
|
||||||
<DeviceId pluginId="PhysicalDevice" identifier="serial=3A251FDJH000CE" />
|
|
||||||
</handle>
|
|
||||||
</Target>
|
|
||||||
</DropdownSelection>
|
|
||||||
<DialogSelection />
|
|
||||||
</SelectionState>
|
|
||||||
</selectionStates>
|
|
||||||
</component>
|
|
||||||
</project>
|
|
||||||
4
.idea/encodings.xml
generated
4
.idea/encodings.xml
generated
@@ -1,4 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="Encoding" defaultCharsetForPropertiesFiles="UTF-8" />
|
|
||||||
</project>
|
|
||||||
24
.idea/gradle.xml
generated
24
.idea/gradle.xml
generated
@@ -1,24 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="GradleMigrationSettings" migrationVersion="1" />
|
|
||||||
<component name="GradleSettings">
|
|
||||||
<option name="linkedExternalProjectsSettings">
|
|
||||||
<GradleProjectSettings>
|
|
||||||
<option name="testRunner" value="CHOOSE_PER_TEST" />
|
|
||||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
|
||||||
<option name="gradleJvm" value="#GRADLE_LOCAL_JAVA_HOME" />
|
|
||||||
<option name="modules">
|
|
||||||
<set>
|
|
||||||
<option value="$PROJECT_DIR$" />
|
|
||||||
<option value="$PROJECT_DIR$/FastBleLib" />
|
|
||||||
<option value="$PROJECT_DIR$/app" />
|
|
||||||
<option value="$PROJECT_DIR$/baselibrary" />
|
|
||||||
<option value="$PROJECT_DIR$/easyPhotos" />
|
|
||||||
<option value="$PROJECT_DIR$/easysocket" />
|
|
||||||
</set>
|
|
||||||
</option>
|
|
||||||
</GradleProjectSettings>
|
|
||||||
</option>
|
|
||||||
<option name="offlineMode" value="true" />
|
|
||||||
</component>
|
|
||||||
</project>
|
|
||||||
4
.idea/misc.xml
generated
4
.idea/misc.xml
generated
@@ -1,4 +0,0 @@
|
|||||||
<project version="4">
|
|
||||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
|
||||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" project-jdk-name="jbr-21" project-jdk-type="JavaSDK" />
|
|
||||||
</project>
|
|
||||||
17
.idea/runConfigurations.xml
generated
17
.idea/runConfigurations.xml
generated
@@ -1,17 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="RunConfigurationProducerService">
|
|
||||||
<option name="ignoredProducers">
|
|
||||||
<set>
|
|
||||||
<option value="com.intellij.execution.junit.AbstractAllInDirectoryConfigurationProducer" />
|
|
||||||
<option value="com.intellij.execution.junit.AllInPackageConfigurationProducer" />
|
|
||||||
<option value="com.intellij.execution.junit.PatternConfigurationProducer" />
|
|
||||||
<option value="com.intellij.execution.junit.TestInClassConfigurationProducer" />
|
|
||||||
<option value="com.intellij.execution.junit.UniqueIdConfigurationProducer" />
|
|
||||||
<option value="com.intellij.execution.junit.testDiscovery.JUnitTestDiscoveryConfigurationProducer" />
|
|
||||||
<option value="org.jetbrains.kotlin.idea.junit.KotlinJUnitRunConfigurationProducer" />
|
|
||||||
<option value="org.jetbrains.kotlin.idea.junit.KotlinPatternConfigurationProducer" />
|
|
||||||
</set>
|
|
||||||
</option>
|
|
||||||
</component>
|
|
||||||
</project>
|
|
||||||
6
.idea/vcs.xml
generated
6
.idea/vcs.xml
generated
@@ -1,6 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="VcsDirectoryMappings">
|
|
||||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
|
||||||
</component>
|
|
||||||
</project>
|
|
||||||
@@ -1 +1 @@
|
|||||||
#Thu Sep 10 18:18:21 CST 2026
|
#Fri Sep 11 15:28:30 CST 2026
|
||||||
|
|||||||
@@ -502,7 +502,7 @@ abstract class BaseActivity<T : ViewBinding>(val inflater: (inflater: LayoutInfl
|
|||||||
} else {
|
} else {
|
||||||
tip.length * (1000L / 10)
|
tip.length * (1000L / 10)
|
||||||
}
|
}
|
||||||
if (showTime < 1000) showTime = 1500
|
if (showTime < 2000) showTime = 2000
|
||||||
if (showTime > 8000) showTime = 8000
|
if (showTime > 8000) showTime = 8000
|
||||||
mViewBinding.root.postDelayed({
|
mViewBinding.root.postDelayed({
|
||||||
if (!isFinishing) {
|
if (!isFinishing) {
|
||||||
@@ -920,7 +920,7 @@ abstract class BaseActivity<T : ViewBinding>(val inflater: (inflater: LayoutInfl
|
|||||||
mTranslateView = translateView
|
mTranslateView = translateView
|
||||||
val r = Rect()
|
val r = Rect()
|
||||||
translateView.getWindowVisibleDisplayFrame(r)
|
translateView.getWindowVisibleDisplayFrame(r)
|
||||||
val heightDiff = translateView.getRootView().height - (r.bottom - r.top)
|
val heightDiff = translateView.rootView.height - (r.bottom - r.top)
|
||||||
if (heightDiff > 200) { // 如果高度差大于200,说明键盘是弹出的
|
if (heightDiff > 200) { // 如果高度差大于200,说明键盘是弹出的
|
||||||
// 进行布局调整
|
// 进行布局调整
|
||||||
if (!isKeyboardTranslate) {
|
if (!isKeyboardTranslate) {
|
||||||
|
|||||||
@@ -95,6 +95,17 @@ interface INetworkService {
|
|||||||
// @Url 一定要传入以“/”结尾注解会替换 baseUrl,每次调用可传入完整 URL
|
// @Url 一定要传入以“/”结尾注解会替换 baseUrl,每次调用可传入完整 URL
|
||||||
suspend fun blePassThrough(@Url url: String, @Body body: RequestBody): Response<ResponseBody>
|
suspend fun blePassThrough(@Url url: String, @Body body: RequestBody): Response<ResponseBody>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查apk包状态
|
||||||
|
*/
|
||||||
|
@FormUrlEncoded
|
||||||
|
@POST("user/fetchPackageCheckStatus")
|
||||||
|
suspend fun checkPackageStatus(
|
||||||
|
@Field("packageName") packageName: String,
|
||||||
|
@Field("signSha256") signSha256: String,
|
||||||
|
@Field("nonce") nonce: String
|
||||||
|
): BaseResponse<String>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取国家代码号
|
* 获取国家代码号
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -834,6 +834,14 @@ object NetworkApi : BaseNetworkApi<INetworkService>(INetworkService.BASE_URL) {
|
|||||||
*/
|
*/
|
||||||
suspend fun blePassThrough(url: String, body: RequestBody) = service.blePassThrough(url, body)
|
suspend fun blePassThrough(url: String, body: RequestBody) = service.blePassThrough(url, body)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查apk包状态
|
||||||
|
*/
|
||||||
|
suspend fun checkPackageStatus(packageName: String, signSha256: String, nonce: String) =
|
||||||
|
getResult {
|
||||||
|
service.checkPackageStatus(packageName, signSha256, nonce)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 取消自动续费/自动订阅
|
* 取消自动续费/自动订阅
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ import com.abbidot.tracker.ui.fragment.pet.PetV2Fragment
|
|||||||
import com.abbidot.tracker.util.Util
|
import com.abbidot.tracker.util.Util
|
||||||
import com.abbidot.tracker.util.ViewUtil
|
import com.abbidot.tracker.util.ViewUtil
|
||||||
import com.abbidot.tracker.util.bluetooth.SRBleUtil
|
import com.abbidot.tracker.util.bluetooth.SRBleUtil
|
||||||
|
import com.abbidot.tracker.vm.AppSetViewModel
|
||||||
import com.abbidot.tracker.vm.ConnectionDeviceViewModel
|
import com.abbidot.tracker.vm.ConnectionDeviceViewModel
|
||||||
import com.abbidot.tracker.vm.CountDownTimerViewModel
|
import com.abbidot.tracker.vm.CountDownTimerViewModel
|
||||||
import com.abbidot.tracker.vm.DataViewModel
|
import com.abbidot.tracker.vm.DataViewModel
|
||||||
@@ -75,6 +76,7 @@ class HomeV2Activity : BaseActivity<ActivityHomeV2Binding>(ActivityHomeV2Binding
|
|||||||
private val mAutomaticConnectionDeviceViewModel: ConnectionDeviceViewModel by viewModels()
|
private val mAutomaticConnectionDeviceViewModel: ConnectionDeviceViewModel by viewModels()
|
||||||
private val mLogBleReportViewModel: LogBleReportViewModel by viewModels()
|
private val mLogBleReportViewModel: LogBleReportViewModel by viewModels()
|
||||||
private val mCountDownTimerViewModel: CountDownTimerViewModel by viewModels()
|
private val mCountDownTimerViewModel: CountDownTimerViewModel by viewModels()
|
||||||
|
private val mAppSetViewModel: AppSetViewModel by viewModels()
|
||||||
|
|
||||||
// private val mSocketSendMessageViewModel: SocketSendMessageViewModel by viewModels()
|
// private val mSocketSendMessageViewModel: SocketSendMessageViewModel by viewModels()
|
||||||
private val mFamilyViewModel: FamilyViewModel by viewModels()
|
private val mFamilyViewModel: FamilyViewModel by viewModels()
|
||||||
@@ -180,6 +182,7 @@ class HomeV2Activity : BaseActivity<ActivityHomeV2Binding>(ActivityHomeV2Binding
|
|||||||
} else {
|
} else {
|
||||||
//清除首次绑定设备信息
|
//清除首次绑定设备信息
|
||||||
MMKVUtil.putString(MMKVKey.FirstDeviceMac, "")
|
MMKVUtil.putString(MMKVKey.FirstDeviceMac, "")
|
||||||
|
//监听网络变化
|
||||||
val connectivityManager = getSystemService(CONNECTIVITY_SERVICE) as ConnectivityManager
|
val connectivityManager = getSystemService(CONNECTIVITY_SERVICE) as ConnectivityManager
|
||||||
val networkCallback: ConnectivityManager.NetworkCallback =
|
val networkCallback: ConnectivityManager.NetworkCallback =
|
||||||
object : ConnectivityManager.NetworkCallback() {
|
object : ConnectivityManager.NetworkCallback() {
|
||||||
@@ -187,7 +190,10 @@ class HomeV2Activity : BaseActivity<ActivityHomeV2Binding>(ActivityHomeV2Binding
|
|||||||
// 当网络可用时调用
|
// 当网络可用时调用
|
||||||
super.onAvailable(network)
|
super.onAvailable(network)
|
||||||
LogUtil.e("当网络可用时,onAvailable")
|
LogUtil.e("当网络可用时,onAvailable")
|
||||||
if (mNetworkRequestsFailRetryCount == mNetworkRequestsFailMaxCount && mPetList.isEmpty()) {
|
//首次启动APP,没有网络去检验APP合法性,就在网络可用时去检验
|
||||||
|
if (MMKVUtil.getInt(MMKVKey.isCheckLegalApp) == ConstantInt.Type2) {
|
||||||
|
mAppSetViewModel.checkPackageStatus(applicationContext)
|
||||||
|
} else if (mNetworkRequestsFailRetryCount == mNetworkRequestsFailMaxCount && mPetList.isEmpty()) {
|
||||||
mNetworkRequestsFailRetryCount = 0
|
mNetworkRequestsFailRetryCount = 0
|
||||||
isFirst = false
|
isFirst = false
|
||||||
mDataViewModel.getHomeBindPetList(this@HomeV2Activity)
|
mDataViewModel.getHomeBindPetList(this@HomeV2Activity)
|
||||||
@@ -295,6 +301,22 @@ class HomeV2Activity : BaseActivity<ActivityHomeV2Binding>(ActivityHomeV2Binding
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
mAppSetViewModel.mCheckPackageStatusLiveData.observe(this) {
|
||||||
|
if (null == it) {
|
||||||
|
showToast(R.string.txt_no_legal_app, true)
|
||||||
|
} else {
|
||||||
|
if (null == it.getOrNull()) {
|
||||||
|
showToast(R.string.txt_no_legal_app, true, Gravity.CENTER)
|
||||||
|
} else {
|
||||||
|
MMKVUtil.putInt(MMKVKey.isCheckLegalApp, ConstantInt.Type1)
|
||||||
|
if (mNetworkRequestsFailRetryCount == mNetworkRequestsFailMaxCount && mPetList.isEmpty()) {
|
||||||
|
mNetworkRequestsFailRetryCount = 0
|
||||||
|
isFirst = false
|
||||||
|
mDataViewModel.getHomeBindPetList(this@HomeV2Activity)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
//退出登录
|
//退出登录
|
||||||
XEventBus.observe(this, EventName.LogOut) {
|
XEventBus.observe(this, EventName.LogOut) {
|
||||||
finish()
|
finish()
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import com.abbidot.baselibrary.util.MMKVUtil
|
|||||||
import com.abbidot.baselibrary.util.Utils
|
import com.abbidot.baselibrary.util.Utils
|
||||||
import com.abbidot.baselibrary.util.rsa.Base64
|
import com.abbidot.baselibrary.util.rsa.Base64
|
||||||
import com.abbidot.tracker.R
|
import com.abbidot.tracker.R
|
||||||
|
import com.abbidot.tracker.constant.ConstantInt
|
||||||
import com.abbidot.tracker.constant.KeyNames
|
import com.abbidot.tracker.constant.KeyNames
|
||||||
import com.abbidot.tracker.databinding.ActivitySplashBinding
|
import com.abbidot.tracker.databinding.ActivitySplashBinding
|
||||||
import com.abbidot.tracker.dialog.PrivacyPolicyDialog
|
import com.abbidot.tracker.dialog.PrivacyPolicyDialog
|
||||||
@@ -31,10 +32,12 @@ import com.abbidot.tracker.retrofit2.INetworkService
|
|||||||
import com.abbidot.tracker.util.ThirdPartyUtil
|
import com.abbidot.tracker.util.ThirdPartyUtil
|
||||||
import com.abbidot.tracker.util.Util
|
import com.abbidot.tracker.util.Util
|
||||||
import com.abbidot.tracker.util.bluetooth.SRBleUtil
|
import com.abbidot.tracker.util.bluetooth.SRBleUtil
|
||||||
|
import com.abbidot.tracker.vm.AppSetViewModel
|
||||||
import com.abbidot.tracker.vm.CountDownTimerViewModel
|
import com.abbidot.tracker.vm.CountDownTimerViewModel
|
||||||
import com.baidu.location.LocationClient
|
import com.baidu.location.LocationClient
|
||||||
import com.baidu.mapapi.CoordType
|
import com.baidu.mapapi.CoordType
|
||||||
import com.baidu.mapapi.SDKInitializer
|
import com.baidu.mapapi.SDKInitializer
|
||||||
|
import com.baidu.platform.comapi.util.NetworkUtil
|
||||||
import com.hjq.toast.Toaster
|
import com.hjq.toast.Toaster
|
||||||
import com.qmuiteam.qmui.arch.QMUIActivity
|
import com.qmuiteam.qmui.arch.QMUIActivity
|
||||||
import com.stripe.android.PaymentConfiguration
|
import com.stripe.android.PaymentConfiguration
|
||||||
@@ -57,6 +60,7 @@ class SplashActivity : QMUIActivity() {
|
|||||||
private lateinit var mViewBinding: ActivitySplashBinding
|
private lateinit var mViewBinding: ActivitySplashBinding
|
||||||
|
|
||||||
private val mCountDownTimerViewModel: CountDownTimerViewModel by viewModels()
|
private val mCountDownTimerViewModel: CountDownTimerViewModel by viewModels()
|
||||||
|
private val mAppSetViewModel: AppSetViewModel by viewModels()
|
||||||
|
|
||||||
// IWXAPI 是第三方 app 和微信通信的 openApi 接口
|
// IWXAPI 是第三方 app 和微信通信的 openApi 接口
|
||||||
private lateinit var mApi: IWXAPI
|
private lateinit var mApi: IWXAPI
|
||||||
@@ -114,6 +118,36 @@ class SplashActivity : QMUIActivity() {
|
|||||||
mViewBinding.ivSplashDebug.visibility = View.VISIBLE
|
mViewBinding.ivSplashDebug.visibility = View.VISIBLE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (NetworkUtil.isNetworkAvailable(mContext)) {
|
||||||
|
mAppSetViewModel.apply {
|
||||||
|
mCheckPackageStatusLiveData.observe(this@SplashActivity) {
|
||||||
|
if (null == it) {
|
||||||
|
showToastAndFinish()
|
||||||
|
} else {
|
||||||
|
if (null == it.getOrNull()) {
|
||||||
|
showToastAndFinish()
|
||||||
|
} else {
|
||||||
|
MMKVUtil.putInt(MMKVKey.isCheckLegalApp, ConstantInt.Type1)
|
||||||
|
legalApp()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mAppSetViewModel.checkPackageStatus(applicationContext)
|
||||||
|
} else {
|
||||||
|
MMKVUtil.putInt(MMKVKey.isCheckLegalApp, ConstantInt.Type2)
|
||||||
|
legalApp()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun showToastAndFinish() {
|
||||||
|
Toaster.show(getString(R.string.txt_no_legal_app))
|
||||||
|
mViewBinding.root.postDelayed({
|
||||||
|
finish()
|
||||||
|
}, 2000)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun legalApp() {
|
||||||
mCountDownTimerViewModel.mCountDownEndLiveData.observe(this) {
|
mCountDownTimerViewModel.mCountDownEndLiveData.observe(this) {
|
||||||
mViewBinding.splashLottieAnimationView.cancelAnimation()
|
mViewBinding.splashLottieAnimationView.cancelAnimation()
|
||||||
val userId = MMKVUtil.getString(MMKVKey.UserId)
|
val userId = MMKVUtil.getString(MMKVKey.UserId)
|
||||||
|
|||||||
@@ -1,13 +1,16 @@
|
|||||||
package com.abbidot.tracker.vm
|
package com.abbidot.tracker.vm
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.abbidot.baselibrary.constant.MMKVKey
|
import com.abbidot.baselibrary.constant.MMKVKey
|
||||||
|
import com.abbidot.baselibrary.util.AppUtils
|
||||||
import com.abbidot.baselibrary.util.MMKVUtil
|
import com.abbidot.baselibrary.util.MMKVUtil
|
||||||
import com.abbidot.tracker.bean.NotificationBean
|
import com.abbidot.tracker.bean.NotificationBean
|
||||||
import com.abbidot.tracker.retrofit2.NetworkApi
|
import com.abbidot.tracker.retrofit2.NetworkApi
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import java.util.UUID
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*Created by .yzq on 2024/9/26/026.
|
*Created by .yzq on 2024/9/26/026.
|
||||||
@@ -18,6 +21,7 @@ class AppSetViewModel : ViewModel() {
|
|||||||
|
|
||||||
val mGetNotificationLiveData = MutableLiveData<Result<MutableList<NotificationBean>>>()
|
val mGetNotificationLiveData = MutableLiveData<Result<MutableList<NotificationBean>>>()
|
||||||
val mSetNotificationLiveData = MutableLiveData<Result<String>>()
|
val mSetNotificationLiveData = MutableLiveData<Result<String>>()
|
||||||
|
val mCheckPackageStatusLiveData = MutableLiveData<Result<String>>()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取通知设置
|
* 获取通知设置
|
||||||
@@ -40,4 +44,17 @@ class AppSetViewModel : ViewModel() {
|
|||||||
mSetNotificationLiveData.value = result
|
mSetNotificationLiveData.value = result
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查apk包状态
|
||||||
|
*/
|
||||||
|
fun checkPackageStatus(context: Context) {
|
||||||
|
viewModelScope.launch {
|
||||||
|
val packageName = context.packageName
|
||||||
|
val signSha256 = AppUtils.getApkSignSha256(context)
|
||||||
|
val nonce = UUID.randomUUID().toString()
|
||||||
|
val result = NetworkApi.checkPackageStatus(packageName, signSha256, nonce)
|
||||||
|
mCheckPackageStatusLiveData.value = result
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -948,4 +948,5 @@
|
|||||||
<string name="txt_auto_renewal_on">自动续订已开启</string>
|
<string name="txt_auto_renewal_on">自动续订已开启</string>
|
||||||
<string name="txt_remove">移除</string>
|
<string name="txt_remove">移除</string>
|
||||||
<string name="txt_turn_off_remove">关闭并移除</string>
|
<string name="txt_turn_off_remove">关闭并移除</string>
|
||||||
|
<string name="txt_no_legal_app">非法APP,请从正规渠道下载安装</string>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -999,4 +999,5 @@
|
|||||||
<string name="txt_auto_renewal_on">Auto-Renewal Is On</string>
|
<string name="txt_auto_renewal_on">Auto-Renewal Is On</string>
|
||||||
<string name="txt_remove">Remove</string>
|
<string name="txt_remove">Remove</string>
|
||||||
<string name="txt_turn_off_remove">Turn Off & Remove</string>
|
<string name="txt_turn_off_remove">Turn Off & Remove</string>
|
||||||
|
<string name="txt_no_legal_app">非法APP,请从正规渠道下载安装</string>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -44,6 +44,7 @@ import androidx.annotation.StringDef
|
|||||||
MMKVKey.UserGpsLat,
|
MMKVKey.UserGpsLat,
|
||||||
MMKVKey.UserGpsLon,
|
MMKVKey.UserGpsLon,
|
||||||
MMKVKey.UserGpsSpeed,
|
MMKVKey.UserGpsSpeed,
|
||||||
|
MMKVKey.isCheckLegalApp,
|
||||||
MMKVKey.isFirstCheckBleOpen,
|
MMKVKey.isFirstCheckBleOpen,
|
||||||
MMKVKey.UUID,
|
MMKVKey.UUID,
|
||||||
MMKVKey.Shared
|
MMKVKey.Shared
|
||||||
@@ -66,6 +67,7 @@ annotation class MMKVKey {
|
|||||||
const val Gender = "gender"
|
const val Gender = "gender"
|
||||||
const val BirthdayDate = "birthdayDate"
|
const val BirthdayDate = "birthdayDate"
|
||||||
const val CountryCode = "countryCode"
|
const val CountryCode = "countryCode"
|
||||||
|
const val isCheckLegalApp = "isCheckLegalApp"
|
||||||
|
|
||||||
//首次绑定流程
|
//首次绑定流程
|
||||||
const val FirstDeviceId = "firstDeviceId"
|
const val FirstDeviceId = "firstDeviceId"
|
||||||
|
|||||||
@@ -75,8 +75,8 @@ class CommonRequestInterceptor : Interceptor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val uuid = MMKVUtil.getString(MMKVKey.UUID)
|
val uniqueId = MMKVUtil.getString(MMKVKey.UUID)
|
||||||
paramList.add("uuid$uuid")
|
paramList.add("uuid$uniqueId")
|
||||||
val sign = if (paramList.isNotEmpty()) {
|
val sign = if (paramList.isNotEmpty()) {
|
||||||
//按key的字母排序
|
//按key的字母排序
|
||||||
paramList.sort()
|
paramList.sort()
|
||||||
@@ -87,7 +87,7 @@ class CommonRequestInterceptor : Interceptor {
|
|||||||
|
|
||||||
val token = MMKVUtil.getString(MMKVKey.Token)
|
val token = MMKVUtil.getString(MMKVKey.Token)
|
||||||
builder.addHeader("token", token)
|
builder.addHeader("token", token)
|
||||||
builder.addHeader("uuid", uuid)
|
builder.addHeader("uuid", uniqueId)
|
||||||
builder.addHeader("sign", sign)
|
builder.addHeader("sign", sign)
|
||||||
|
|
||||||
return chain.proceed(builder.build())
|
return chain.proceed(builder.build())
|
||||||
|
|||||||
@@ -6,9 +6,11 @@ import android.content.pm.ApplicationInfo
|
|||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
import android.content.res.Configuration
|
import android.content.res.Configuration
|
||||||
import android.content.res.Resources
|
import android.content.res.Resources
|
||||||
|
import android.os.Build
|
||||||
import android.provider.Settings
|
import android.provider.Settings
|
||||||
import android.text.TextUtils
|
import android.text.TextUtils
|
||||||
import com.abbidot.baselibrary.constant.MMKVKey
|
import com.abbidot.baselibrary.constant.MMKVKey
|
||||||
|
import java.security.MessageDigest
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
|
|
||||||
@@ -115,19 +117,87 @@ class AppUtils {
|
|||||||
*/
|
*/
|
||||||
@SuppressLint("HardwareIds")
|
@SuppressLint("HardwareIds")
|
||||||
fun saveUniqueId(context: Context) {
|
fun saveUniqueId(context: Context) {
|
||||||
var uuid = MMKVUtil.getString(MMKVKey.UUID)
|
var uniqueId = MMKVUtil.getString(MMKVKey.UUID)
|
||||||
if (TextUtils.isEmpty(uuid)) {
|
if (TextUtils.isEmpty(uniqueId)) {
|
||||||
val androidId =
|
val androidId =
|
||||||
Settings.Secure.getString(context.contentResolver, Settings.Secure.ANDROID_ID)
|
Settings.Secure.getString(context.contentResolver, Settings.Secure.ANDROID_ID)
|
||||||
?: ""
|
?: ""
|
||||||
uuid = if (TextUtils.isEmpty(androidId))
|
uniqueId = if (TextUtils.isEmpty(androidId)) UUID.randomUUID().toString()
|
||||||
UUID.randomUUID().toString()
|
else androidId
|
||||||
else
|
MMKVUtil.putString(MMKVKey.UUID, uniqueId)
|
||||||
androidId
|
|
||||||
MMKVUtil.putString(MMKVKey.UUID, uuid)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*获取apk签名Sha256
|
||||||
|
*/
|
||||||
|
fun getApkSignSha2561(context: Context): String {
|
||||||
|
return try {
|
||||||
|
val pm = context.packageManager
|
||||||
|
val pkgName = context.packageName
|
||||||
|
val pkgInfo = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||||
|
// API33+ Android13,直接用GET_SIGNING_CERTIFICATES,不需要if判断
|
||||||
|
val flagLong = PackageManager.GET_SIGNING_CERTIFICATES.toLong()
|
||||||
|
pm.getPackageInfo(pkgName, PackageManager.PackageInfoFlags.of(flagLong))
|
||||||
|
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
||||||
|
// API28 ~ API32
|
||||||
|
pm.getPackageInfo(pkgName, PackageManager.GET_SIGNING_CERTIFICATES)
|
||||||
|
} else {
|
||||||
|
// API24 ~ API27
|
||||||
|
pm.getPackageInfo(pkgName, PackageManager.GET_SIGNATURES)
|
||||||
|
}
|
||||||
|
val cert = when {
|
||||||
|
Build.VERSION.SDK_INT >= Build.VERSION_CODES.P && pkgInfo.signingInfo != null -> pkgInfo.signingInfo.signingCertificateHistory?.firstOrNull()
|
||||||
|
else -> pkgInfo.signatures?.firstOrNull()
|
||||||
|
} ?: return ""
|
||||||
|
val digest = MessageDigest.getInstance("SHA-256")
|
||||||
|
val hashBytes = digest.digest(cert.toByteArray())
|
||||||
|
hashBytes.joinToString("") { "%02x".format(Locale.US, it) }
|
||||||
|
} catch (_: Exception) {
|
||||||
|
""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取apk签名Sha256
|
||||||
|
*/
|
||||||
|
fun getApkSignSha256(context: Context): String {
|
||||||
|
return try {
|
||||||
|
val pm = context.packageManager
|
||||||
|
val pkgName = context.packageName
|
||||||
|
val pkgInfo = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||||
|
// API33+ Android13
|
||||||
|
val flagLong = PackageManager.GET_SIGNING_CERTIFICATES.toLong()
|
||||||
|
pm.getPackageInfo(pkgName, PackageManager.PackageInfoFlags.of(flagLong))
|
||||||
|
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
||||||
|
// API28 ~ API32
|
||||||
|
pm.getPackageInfo(pkgName, PackageManager.GET_SIGNING_CERTIFICATES)
|
||||||
|
} else {
|
||||||
|
// API24 ~ API27
|
||||||
|
pm.getPackageInfo(pkgName, PackageManager.GET_SIGNATURES)
|
||||||
|
}
|
||||||
|
val certBytes = when {
|
||||||
|
Build.VERSION.SDK_INT >= Build.VERSION_CODES.P && pkgInfo.signingInfo != null -> {
|
||||||
|
// 读取【当前生效签名】apkContentsSigners,不是历史证书
|
||||||
|
val activeCert =
|
||||||
|
pkgInfo.signingInfo.apkContentsSigners?.firstOrNull() ?: return ""
|
||||||
|
activeCert.toByteArray()
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> {
|
||||||
|
val signature = pkgInfo.signatures?.firstOrNull() ?: return ""
|
||||||
|
signature.toByteArray()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val digest = MessageDigest.getInstance("SHA-256")
|
||||||
|
val hashBytes = digest.digest(certBytes)
|
||||||
|
hashBytes.joinToString(separator = "") { "%02x".format(Locale.US, it) }
|
||||||
|
} catch (_: Exception) {
|
||||||
|
""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取系统国家地区
|
* 获取系统国家地区
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user