From f2f68e1e6d5ce1de0ceb75bd52a3483d04efaf7c Mon Sep 17 00:00:00 2001
From: yezhiqiu <123456@qq.com>
Date: Fri, 11 Sep 2026 18:16:38 +0800
Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E9=98=B2=E7=AF=A1=E6=94=B9?=
=?UTF-8?q?=E6=8E=A7=E5=88=B6?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.idea/.gitignore | 3 -
.idea/AndroidProjectSystem.xml | 6 --
.idea/compiler.xml | 6 --
.idea/deploymentTargetSelector.xml | 18 ----
.idea/encodings.xml | 4 -
.idea/gradle.xml | 24 ------
.idea/misc.xml | 4 -
.idea/runConfigurations.xml | 17 ----
.idea/vcs.xml | 6 --
.../compile-file-map.properties | 2 +-
.../com/abbidot/tracker/base/BaseActivity.kt | 4 +-
.../tracker/retrofit2/INetworkService.kt | 11 +++
.../abbidot/tracker/retrofit2/NetworkApi.kt | 8 ++
.../tracker/ui/activity/HomeV2Activity.kt | 24 +++++-
.../tracker/ui/activity/SplashActivity.kt | 34 ++++++++
.../com/abbidot/tracker/vm/AppSetViewModel.kt | 17 ++++
app/src/main/res/values-zh-rCN/strings.xml | 1 +
app/src/main/res/values/strings.xml | 1 +
.../abbidot/baselibrary/constant/MMKVKey.kt | 2 +
.../interceptor/CommonRequestInterceptor.kt | 6 +-
.../com/abbidot/baselibrary/util/AppUtils.kt | 84 +++++++++++++++++--
21 files changed, 180 insertions(+), 102 deletions(-)
delete mode 100644 .idea/.gitignore
delete mode 100644 .idea/AndroidProjectSystem.xml
delete mode 100644 .idea/compiler.xml
delete mode 100644 .idea/deploymentTargetSelector.xml
delete mode 100644 .idea/encodings.xml
delete mode 100644 .idea/gradle.xml
delete mode 100644 .idea/misc.xml
delete mode 100644 .idea/runConfigurations.xml
delete mode 100644 .idea/vcs.xml
diff --git a/.idea/.gitignore b/.idea/.gitignore
deleted file mode 100644
index 26d3352..0000000
--- a/.idea/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
-# Default ignored files
-/shelf/
-/workspace.xml
diff --git a/.idea/AndroidProjectSystem.xml b/.idea/AndroidProjectSystem.xml
deleted file mode 100644
index 4a53bee..0000000
--- a/.idea/AndroidProjectSystem.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/compiler.xml b/.idea/compiler.xml
deleted file mode 100644
index 1c5ab05..0000000
--- a/.idea/compiler.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/deploymentTargetSelector.xml b/.idea/deploymentTargetSelector.xml
deleted file mode 100644
index 0990919..0000000
--- a/.idea/deploymentTargetSelector.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/encodings.xml b/.idea/encodings.xml
deleted file mode 100644
index da0415a..0000000
--- a/.idea/encodings.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/.idea/gradle.xml b/.idea/gradle.xml
deleted file mode 100644
index 4396204..0000000
--- a/.idea/gradle.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
deleted file mode 100644
index 0822f21..0000000
--- a/.idea/misc.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml
deleted file mode 100644
index 16660f1..0000000
--- a/.idea/runConfigurations.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
deleted file mode 100644
index 94a25f7..0000000
--- a/.idea/vcs.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/FastBleLib/build/intermediates/incremental/debug/packageDebugResources/compile-file-map.properties b/FastBleLib/build/intermediates/incremental/debug/packageDebugResources/compile-file-map.properties
index 5e7c409..87267b0 100644
--- a/FastBleLib/build/intermediates/incremental/debug/packageDebugResources/compile-file-map.properties
+++ b/FastBleLib/build/intermediates/incremental/debug/packageDebugResources/compile-file-map.properties
@@ -1 +1 @@
-#Thu Sep 10 18:18:21 CST 2026
+#Fri Sep 11 15:28:30 CST 2026
diff --git a/app/src/main/java/com/abbidot/tracker/base/BaseActivity.kt b/app/src/main/java/com/abbidot/tracker/base/BaseActivity.kt
index 5e1ce0a..bf6e14f 100644
--- a/app/src/main/java/com/abbidot/tracker/base/BaseActivity.kt
+++ b/app/src/main/java/com/abbidot/tracker/base/BaseActivity.kt
@@ -502,7 +502,7 @@ abstract class BaseActivity(val inflater: (inflater: LayoutInfl
} else {
tip.length * (1000L / 10)
}
- if (showTime < 1000) showTime = 1500
+ if (showTime < 2000) showTime = 2000
if (showTime > 8000) showTime = 8000
mViewBinding.root.postDelayed({
if (!isFinishing) {
@@ -920,7 +920,7 @@ abstract class BaseActivity(val inflater: (inflater: LayoutInfl
mTranslateView = translateView
val r = Rect()
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 (!isKeyboardTranslate) {
diff --git a/app/src/main/java/com/abbidot/tracker/retrofit2/INetworkService.kt b/app/src/main/java/com/abbidot/tracker/retrofit2/INetworkService.kt
index 4c0e153..773c0e2 100644
--- a/app/src/main/java/com/abbidot/tracker/retrofit2/INetworkService.kt
+++ b/app/src/main/java/com/abbidot/tracker/retrofit2/INetworkService.kt
@@ -95,6 +95,17 @@ interface INetworkService {
// @Url 一定要传入以“/”结尾注解会替换 baseUrl,每次调用可传入完整 URL
suspend fun blePassThrough(@Url url: String, @Body body: RequestBody): Response
+ /**
+ * 检查apk包状态
+ */
+ @FormUrlEncoded
+ @POST("user/fetchPackageCheckStatus")
+ suspend fun checkPackageStatus(
+ @Field("packageName") packageName: String,
+ @Field("signSha256") signSha256: String,
+ @Field("nonce") nonce: String
+ ): BaseResponse
+
/**
* 获取国家代码号
*/
diff --git a/app/src/main/java/com/abbidot/tracker/retrofit2/NetworkApi.kt b/app/src/main/java/com/abbidot/tracker/retrofit2/NetworkApi.kt
index e98473f..dc37b20 100644
--- a/app/src/main/java/com/abbidot/tracker/retrofit2/NetworkApi.kt
+++ b/app/src/main/java/com/abbidot/tracker/retrofit2/NetworkApi.kt
@@ -834,6 +834,14 @@ object NetworkApi : BaseNetworkApi(INetworkService.BASE_URL) {
*/
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)
+ }
+
/**
* 取消自动续费/自动订阅
*/
diff --git a/app/src/main/java/com/abbidot/tracker/ui/activity/HomeV2Activity.kt b/app/src/main/java/com/abbidot/tracker/ui/activity/HomeV2Activity.kt
index a275cbe..9314c74 100644
--- a/app/src/main/java/com/abbidot/tracker/ui/activity/HomeV2Activity.kt
+++ b/app/src/main/java/com/abbidot/tracker/ui/activity/HomeV2Activity.kt
@@ -52,6 +52,7 @@ import com.abbidot.tracker.ui.fragment.pet.PetV2Fragment
import com.abbidot.tracker.util.Util
import com.abbidot.tracker.util.ViewUtil
import com.abbidot.tracker.util.bluetooth.SRBleUtil
+import com.abbidot.tracker.vm.AppSetViewModel
import com.abbidot.tracker.vm.ConnectionDeviceViewModel
import com.abbidot.tracker.vm.CountDownTimerViewModel
import com.abbidot.tracker.vm.DataViewModel
@@ -75,6 +76,7 @@ class HomeV2Activity : BaseActivity(ActivityHomeV2Binding
private val mAutomaticConnectionDeviceViewModel: ConnectionDeviceViewModel by viewModels()
private val mLogBleReportViewModel: LogBleReportViewModel by viewModels()
private val mCountDownTimerViewModel: CountDownTimerViewModel by viewModels()
+ private val mAppSetViewModel: AppSetViewModel by viewModels()
// private val mSocketSendMessageViewModel: SocketSendMessageViewModel by viewModels()
private val mFamilyViewModel: FamilyViewModel by viewModels()
@@ -180,6 +182,7 @@ class HomeV2Activity : BaseActivity(ActivityHomeV2Binding
} else {
//清除首次绑定设备信息
MMKVUtil.putString(MMKVKey.FirstDeviceMac, "")
+ //监听网络变化
val connectivityManager = getSystemService(CONNECTIVITY_SERVICE) as ConnectivityManager
val networkCallback: ConnectivityManager.NetworkCallback =
object : ConnectivityManager.NetworkCallback() {
@@ -187,7 +190,10 @@ class HomeV2Activity : BaseActivity(ActivityHomeV2Binding
// 当网络可用时调用
super.onAvailable(network)
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
isFirst = false
mDataViewModel.getHomeBindPetList(this@HomeV2Activity)
@@ -295,6 +301,22 @@ class HomeV2Activity : BaseActivity(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) {
finish()
diff --git a/app/src/main/java/com/abbidot/tracker/ui/activity/SplashActivity.kt b/app/src/main/java/com/abbidot/tracker/ui/activity/SplashActivity.kt
index 6a2f32e..2323a28 100644
--- a/app/src/main/java/com/abbidot/tracker/ui/activity/SplashActivity.kt
+++ b/app/src/main/java/com/abbidot/tracker/ui/activity/SplashActivity.kt
@@ -24,6 +24,7 @@ import com.abbidot.baselibrary.util.MMKVUtil
import com.abbidot.baselibrary.util.Utils
import com.abbidot.baselibrary.util.rsa.Base64
import com.abbidot.tracker.R
+import com.abbidot.tracker.constant.ConstantInt
import com.abbidot.tracker.constant.KeyNames
import com.abbidot.tracker.databinding.ActivitySplashBinding
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.Util
import com.abbidot.tracker.util.bluetooth.SRBleUtil
+import com.abbidot.tracker.vm.AppSetViewModel
import com.abbidot.tracker.vm.CountDownTimerViewModel
import com.baidu.location.LocationClient
import com.baidu.mapapi.CoordType
import com.baidu.mapapi.SDKInitializer
+import com.baidu.platform.comapi.util.NetworkUtil
import com.hjq.toast.Toaster
import com.qmuiteam.qmui.arch.QMUIActivity
import com.stripe.android.PaymentConfiguration
@@ -57,6 +60,7 @@ class SplashActivity : QMUIActivity() {
private lateinit var mViewBinding: ActivitySplashBinding
private val mCountDownTimerViewModel: CountDownTimerViewModel by viewModels()
+ private val mAppSetViewModel: AppSetViewModel by viewModels()
// IWXAPI 是第三方 app 和微信通信的 openApi 接口
private lateinit var mApi: IWXAPI
@@ -114,6 +118,36 @@ class SplashActivity : QMUIActivity() {
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) {
mViewBinding.splashLottieAnimationView.cancelAnimation()
val userId = MMKVUtil.getString(MMKVKey.UserId)
diff --git a/app/src/main/java/com/abbidot/tracker/vm/AppSetViewModel.kt b/app/src/main/java/com/abbidot/tracker/vm/AppSetViewModel.kt
index 3879482..d73da58 100644
--- a/app/src/main/java/com/abbidot/tracker/vm/AppSetViewModel.kt
+++ b/app/src/main/java/com/abbidot/tracker/vm/AppSetViewModel.kt
@@ -1,13 +1,16 @@
package com.abbidot.tracker.vm
+import android.content.Context
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.abbidot.baselibrary.constant.MMKVKey
+import com.abbidot.baselibrary.util.AppUtils
import com.abbidot.baselibrary.util.MMKVUtil
import com.abbidot.tracker.bean.NotificationBean
import com.abbidot.tracker.retrofit2.NetworkApi
import kotlinx.coroutines.launch
+import java.util.UUID
/**
*Created by .yzq on 2024/9/26/026.
@@ -18,6 +21,7 @@ class AppSetViewModel : ViewModel() {
val mGetNotificationLiveData = MutableLiveData>>()
val mSetNotificationLiveData = MutableLiveData>()
+ val mCheckPackageStatusLiveData = MutableLiveData>()
/**
* 获取通知设置
@@ -40,4 +44,17 @@ class AppSetViewModel : ViewModel() {
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
+ }
+ }
}
\ No newline at end of file
diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml
index 51e73b2..4da4d89 100644
--- a/app/src/main/res/values-zh-rCN/strings.xml
+++ b/app/src/main/res/values-zh-rCN/strings.xml
@@ -948,4 +948,5 @@
自动续订已开启
移除
关闭并移除
+ 非法APP,请从正规渠道下载安装
\ 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 bbb9a6d..2403931 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -999,4 +999,5 @@
Auto-Renewal Is On
Remove
Turn Off & Remove
+ 非法APP,请从正规渠道下载安装
\ No newline at end of file
diff --git a/baselibrary/src/main/java/com/abbidot/baselibrary/constant/MMKVKey.kt b/baselibrary/src/main/java/com/abbidot/baselibrary/constant/MMKVKey.kt
index 8d45e73..87e88d7 100644
--- a/baselibrary/src/main/java/com/abbidot/baselibrary/constant/MMKVKey.kt
+++ b/baselibrary/src/main/java/com/abbidot/baselibrary/constant/MMKVKey.kt
@@ -44,6 +44,7 @@ import androidx.annotation.StringDef
MMKVKey.UserGpsLat,
MMKVKey.UserGpsLon,
MMKVKey.UserGpsSpeed,
+ MMKVKey.isCheckLegalApp,
MMKVKey.isFirstCheckBleOpen,
MMKVKey.UUID,
MMKVKey.Shared
@@ -66,6 +67,7 @@ annotation class MMKVKey {
const val Gender = "gender"
const val BirthdayDate = "birthdayDate"
const val CountryCode = "countryCode"
+ const val isCheckLegalApp = "isCheckLegalApp"
//首次绑定流程
const val FirstDeviceId = "firstDeviceId"
diff --git a/baselibrary/src/main/java/com/abbidot/baselibrary/network/interceptor/CommonRequestInterceptor.kt b/baselibrary/src/main/java/com/abbidot/baselibrary/network/interceptor/CommonRequestInterceptor.kt
index ef0538d..4f8e6f6 100644
--- a/baselibrary/src/main/java/com/abbidot/baselibrary/network/interceptor/CommonRequestInterceptor.kt
+++ b/baselibrary/src/main/java/com/abbidot/baselibrary/network/interceptor/CommonRequestInterceptor.kt
@@ -75,8 +75,8 @@ class CommonRequestInterceptor : Interceptor {
}
}
- val uuid = MMKVUtil.getString(MMKVKey.UUID)
- paramList.add("uuid$uuid")
+ val uniqueId = MMKVUtil.getString(MMKVKey.UUID)
+ paramList.add("uuid$uniqueId")
val sign = if (paramList.isNotEmpty()) {
//按key的字母排序
paramList.sort()
@@ -87,7 +87,7 @@ class CommonRequestInterceptor : Interceptor {
val token = MMKVUtil.getString(MMKVKey.Token)
builder.addHeader("token", token)
- builder.addHeader("uuid", uuid)
+ builder.addHeader("uuid", uniqueId)
builder.addHeader("sign", sign)
return chain.proceed(builder.build())
diff --git a/baselibrary/src/main/java/com/abbidot/baselibrary/util/AppUtils.kt b/baselibrary/src/main/java/com/abbidot/baselibrary/util/AppUtils.kt
index c7d6399..2bb8636 100644
--- a/baselibrary/src/main/java/com/abbidot/baselibrary/util/AppUtils.kt
+++ b/baselibrary/src/main/java/com/abbidot/baselibrary/util/AppUtils.kt
@@ -6,9 +6,11 @@ import android.content.pm.ApplicationInfo
import android.content.pm.PackageManager
import android.content.res.Configuration
import android.content.res.Resources
+import android.os.Build
import android.provider.Settings
import android.text.TextUtils
import com.abbidot.baselibrary.constant.MMKVKey
+import java.security.MessageDigest
import java.util.Locale
import java.util.UUID
@@ -115,19 +117,87 @@ class AppUtils {
*/
@SuppressLint("HardwareIds")
fun saveUniqueId(context: Context) {
- var uuid = MMKVUtil.getString(MMKVKey.UUID)
- if (TextUtils.isEmpty(uuid)) {
+ var uniqueId = MMKVUtil.getString(MMKVKey.UUID)
+ if (TextUtils.isEmpty(uniqueId)) {
val androidId =
Settings.Secure.getString(context.contentResolver, Settings.Secure.ANDROID_ID)
?: ""
- uuid = if (TextUtils.isEmpty(androidId))
- UUID.randomUUID().toString()
- else
- androidId
- MMKVUtil.putString(MMKVKey.UUID, uuid)
+ uniqueId = if (TextUtils.isEmpty(androidId)) UUID.randomUUID().toString()
+ else androidId
+ MMKVUtil.putString(MMKVKey.UUID, uniqueId)
}
}
+ /**
+ *获取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) {
+ ""
+ }
+ }
+
+
/**
* 获取系统国家地区
*/