1. 项目概述:为什么我们需要一个Play Integrity Checker?
如果你是一名Android开发者,或者对Android设备安全、应用生态的“纯净度”感兴趣,那么“Play Integrity API”这个词你肯定不陌生。简单来说,它是Google Play服务提供的一套API,用于验证运行你应用的设备是否真实、未被篡改,以及应用本身是否来自可信渠道。这听起来像是Google在“管闲事”,但实际上,它关乎应用开发者的核心利益和用户的最终体验。
想象一下,你开发了一款付费应用或包含内购的游戏。如果用户通过修改系统、使用非官方渠道安装的修改版APK,或者运行在模拟器上,轻松绕过了你的付费验证,你的收入从何而来?更进一步,如果一些恶意软件或自动化脚本在大量虚拟设备上运行你的应用,进行刷榜、刷评论或欺诈活动,不仅损害你的经济利益,还会污染你的应用数据,让基于用户行为的算法推荐完全失效。Play Integrity API就是为了应对这些挑战而生的“守门员”。
然而,作为开发者,我们如何知道自己的应用集成是否正确?如何测试不同设备(包括那些可能被Root或安装了Magisk的设备)的验证结果?如何向测试团队或合作伙伴直观地展示验证状态?这就是“Play Integrity Checker”工具的价值所在。它不是一个简单的API调用演示,而是一个功能完整、可独立运行、能深入展示验证细节的Android应用。通过构建这样一个工具,你不仅能彻底掌握Play Integrity API的集成与调试方法,更能将其核心验证逻辑可视化,成为一个在日常开发和测试中极具实用价值的“瑞士军刀”。
2. 核心原理与API深度解析
在动手敲代码之前,我们必须吃透Play Integrity API的工作原理。它远不止一个返回“真”或“假”的简单接口。
2.1 Play Integrity API的三层验证体系
Play Integrity API的验证结果不是一个布尔值,而是一个包含多个字段的令牌(Token),解码后主要包含三个核心部分的评估:
-
设备完整性(Device Integrity) :评估设备本身的状态。理想情况下,设备应通过Android兼容性测试套件(CTS),并且系统未被篡改。这里会返回如
MEETS_DEVICE_INTEGRITY这样的结果。如果设备被Root、Bootloader已解锁或安装了自定义ROM,这部分验证就可能失败。 -
应用完整性(App Integrity) :验证应用本身的安装来源和完整性。关键结果是
MEETS_BASIC_INTEGRITY和MEETS_STRONG_INTEGRITY。-
MEETS_BASIC_INTEGRITY:意味着应用运行在一个基本的、未被深度篡改的Android环境上。即使设备被Root,只要应用包名、签名证书与Google Play上记录的一致,通常仍能通过基础完整性检查。这是防止在模拟器或严重篡改系统上运行的最低防线。 -
MEETS_STRONG_INTEGRITY:这是最高级别的应用完整性。它要求应用必须是从Google Play商店安装的,且未被重新打包或修改。任何来自第三方商店、通过ADB侧载或修改过的APK,都无法满足强完整性。
-
-
账户详情(Account Details) :可选部分,用于验证用户账户是否正常(例如,不是被开发者列入黑名单的账户)。这对于打击滥用行为的进阶策略很有用。
注意 :
MEETS_DEVICE_INTEGRITY和MEETS_STRONG_INTEGRITY是两个不同维度的概念。一个从官方Play商店安装的应用在已Root的设备上,可能满足MEETS_STRONG_INTEGRITY(因为应用来源纯净),但无法满足MEETS_DEVICE_INTEGRITY(因为设备系统被修改)。
2.2 集成流程与密钥管理
集成Play Integrity API的核心步骤包括服务端和客户端的配合:
-
在Google Play Console中配置 :这是起点。你需要为你的应用在Play Console中启用Play Integrity API。更重要的是,你需要在这里创建一个“非对称密钥对”。Google会保存公钥,而私钥(一个
.json文件)则由你下载并妥善保管在 你的应用后端服务器 上。这个私钥 绝对不应该 被打包到客户端APK中,否则会被轻易提取,导致验证形同虚设。 -
客户端(Android App)发起请求 :在你的应用(也就是我们要构建的Checker工具)中,调用Integrity API,你会得到一个加密的
integrityToken。这个令牌本身对你(客户端)是不可读的。 -
服务端验证令牌 :客户端将这个
integrityToken发送到你自己的后端服务器。服务器使用之前下载的私钥,调用Google的验证接口(https://playintegrity.googleapis.com/v1/PACKAGE_NAME:decodeIntegrityToken)来解密和验证这个令牌。验证结果会以清晰的JSON格式返回,包含了上述所有的完整性评估细节、时间戳、设备信息等。 -
服务端将结果返回客户端 :你的服务器将验证后的、可读的结果返回给Android客户端,客户端再根据结果决定后续流程(如允许登录、禁止交易等)。
对于我们这个“Play Integrity Checker”工具,为了使其能独立运行而不依赖一个复杂的后端,我们将采用一种简化但安全的模式:我们依然遵循客户端-服务端架构,但我们可以构建一个极简的、仅供演示和测试用的后端(例如,使用Cloud Functions、Firebase或一个简单的Python Flask服务),并将这个后端的地址硬编码或配置在App中。 关键在于,这个演示后端的私钥仅用于此测试工具,且你需要明白在生产环境中,私钥必须由你真正的业务服务器保管。
3. 开发环境搭建与项目初始化
工欲善其事,必先利其器。我们选择Android Studio作为开发环境,它是Google官方的IDE,对Play Integrity API等Google服务有最好的支持。
3.1 Android Studio配置要点
如果你已经安装了Android Studio,请确保SDK工具更新至最新。特别是
Google Play services
和
Google Repository
这两个SDK组件必须安装。你可以在Android Studio的
Settings/Preferences
->
Appearance & Behavior
->
System Settings
->
Android SDK
->
SDK Tools
选项卡中检查和安装。
对于网络搜索热词中提到的“android studio怎么设置中文?”,这属于IDE界面语言设置,并不影响编码。你可以在
Settings/Preferences
->
Plugins
->
Marketplace
中搜索“Chinese (Simplified) Language Pack”插件并安装,重启后即可切换为中文界面。但考虑到开发文档和社区资源多以英文为主,我个人建议保持英文界面,这对长期学习和排查问题更有帮助。
3.2 创建新项目与依赖配置
-
新建项目 :打开Android Studio,选择“New Project”,模板选择“Empty Views Activity”(即传统的基于View的Activity,为了更清晰地展示逻辑,我们暂不使用Compose)。项目命名如
PlayIntegrityChecker,包名可设为com.yourname.playintegritychecker,语言选择Kotlin(推荐,代码更简洁),最低API级别建议设为API 24(Android 7.0),以覆盖大多数设备。 -
添加关键依赖 :打开项目根目录的
build.gradle.kts(Module: app) 文件,在dependencies块中添加以下依赖:dependencies { implementation("com.google.android.play:integrity:1.3.0") // Play Integrity API 客户端库 implementation("com.squareup.retrofit2:retrofit:2.9.0") // 用于网络请求到我们的验证服务器 implementation("com.squareup.retrofit2:converter-gson:2.9.0") // 用Gson解析JSON implementation("com.google.code.gson:gson:2.10.1") // Gson库 // 其他基础依赖... }添加后同步(Sync)项目。
-
配置网络权限 :由于应用需要向你的验证服务器发送请求,必须在
AndroidManifest.xml文件中添加互联网权限:<uses-permission android:name="android.permission.INTERNET" />
3.3 模拟验证服务器的准备(关键步骤)
为了让工具能独立运行,我们需要一个临时性的“验证服务器”。这里提供两个最快捷的方案:
方案A:使用Google Cloud Functions(无服务器,推荐) 这是最接近生产环境的简易方案。你可以编写一个Node.js或Python函数,接收令牌,调用Google验证接口,然后返回结果。
- 在Google Cloud Platform创建一个新项目。
- 启用Cloud Functions API。
- 编写一个HTTP触发的函数,核心逻辑是使用你从Play Console下载的私钥文件,初始化Google API客户端,然后解码令牌。
-
部署函数后,你会得到一个HTTPS端点(例如
https://your-region-your-project.cloudfunctions.net/verifyToken)。将这个URL配置到你的Android应用中。
方案B:使用本地测试服务器(如Python Flask,仅用于开发) 对于纯本地测试,你可以快速搭建一个Flask服务器。
# 示例:app.py (务必不要在生产环境使用此简单代码)
from flask import Flask, request, jsonify
from google.oauth2 import service_account
from googleapiclient.discovery import build
import json
app = Flask(__name__)
# 加载从Play Console下载的私钥JSON文件
SERVICE_ACCOUNT_KEY_FILE = 'your-private-key.json'
credentials = service_account.Credentials.from_service_account_file(
SERVICE_ACCOUNT_KEY_FILE,
scopes=['https://www.googleapis.com/auth/playintegrity']
)
service = build('playintegrity', 'v1', credentials=credentials)
@app.route('/verify', methods=['POST'])
def verify_token():
data = request.json
integrity_token = data.get('token')
package_name = 'com.yourname.playintegritychecker' # 你的应用包名
request_body = {'integrityToken': integrity_token}
response = service.decodeIntegrityToken(packageName=package_name, body=request_body).execute()
return jsonify(response)
if __name__ == '__main__':
app.run(ssl_context='adhoc', host='0.0.0.0', port=5000) # 注意:需要HTTPS
在电脑上运行此脚本,并确保手机和电脑在同一局域网。你需要将Android应用中的服务器地址设为
https://你的电脑IP:5000/verify
。
重要:Android Pie (API 28) 及以上默认要求HTTPS,所以本地测试也需要配置SSL(如上例使用
adhoc
)或修改App的网络安全配置。
实操心得 :在开发初期,强烈建议使用方案B进行快速迭代和调试。你可以先在电脑上运行Flask服务器,用Postman测试通接口,再集成到App中。这能帮你隔离客户端和服务端问题。记得在
AndroidManifest.xml的<application>标签内添加android:usesCleartextTraffic="true"以允许HTTP通信(仅限调试!),或者为调试构建配置网络安全配置文件以信任你的自签名证书。
4. 客户端应用核心功能实现
现在,我们开始构建Checker工具的Android客户端部分。核心界面可以很简单:一个按钮用于触发检查,几个TextView用于显示结果。
4.1 用户界面设计
打开
activity_main.xml
,设计一个简单的布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="16dp">
<Button
android:id="@+id/btn_check"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="32dp"
android:text="开始完整性检查" />
<TextView
android:id="@+id/tv_status"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:text="状态:等待检查..."
android:textSize="16sp" />
<ScrollView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:layout_marginTop="16dp">
<TextView
android:id="@+id/tv_result"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#f5f5f5"
android:padding="12dp"
android:text="详细结果将显示在这里..."
android:textIsSelectable="true" /> <!-- textIsSelectable允许用户复制文本 -->
</ScrollView>
</LinearLayout>
这个布局包含一个触发按钮、一个状态提示框和一个可滚动、可复制的文本框用于显示详细的JSON结果。
4.2 集成Play Integrity API客户端
在
MainActivity.kt
中,我们实现核心逻辑。
首先,初始化Play Integrity Manager:
import com.google.android.play.core.integrity.IntegrityManager
import com.google.android.play.core.integrity.IntegrityManagerFactory
import com.google.android.play.core.integrity.IntegrityTokenRequest
import com.google.android.play.core.integrity.IntegrityTokenResponse
import com.google.android.gms.common.ConnectionResult
import com.google.android.gms.common.GoogleApiAvailability
class MainActivity : AppCompatActivity() {
private lateinit var integrityManager: IntegrityManager
private lateinit var btnCheck: Button
private lateinit var tvStatus: TextView
private lateinit var tvResult: TextView
// 你的后端验证服务器地址(请替换为实际地址)
private val YOUR_SERVER_URL = "https://your-server.com/verify"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
btnCheck = findViewById(R.id.btn_check)
tvStatus = findViewById(R.id.tv_status)
tvResult = findViewById(R.id.tv_result)
// 1. 检查Google Play服务是否可用
if (!isGooglePlayServicesAvailable()) {
tvStatus.text = "状态:错误 - 设备未安装或版本过旧的Google Play服务"
btnCheck.isEnabled = false
return
}
// 2. 创建IntegrityManager实例
integrityManager = IntegrityManagerFactory.create(applicationContext)
btnCheck.setOnClickListener {
requestIntegrityToken()
}
}
private fun isGooglePlayServicesAvailable(): Boolean {
val googleApiAvailability = GoogleApiAvailability.getInstance()
val resultCode = googleApiAvailability.isGooglePlayServicesAvailable(this)
return resultCode == ConnectionResult.SUCCESS
}
// ... 后续代码
}
4.3 请求令牌与处理服务器验证
接着,实现
requestIntegrityToken
方法,向Play服务请求令牌,然后发送到我们的服务器进行验证。
private fun requestIntegrityToken() {
tvStatus.text = "状态:正在请求完整性令牌..."
tvResult.text = ""
btnCheck.isEnabled = false
// 构建令牌请求
val integrityTokenRequest = IntegrityTokenRequest.builder()
.setNonce(generateNonce()) // 生成一个随机数防止重放攻击
.setCloudProjectNumber(YOUR_CLOUD_PROJECT_NUMBER) // 你在Google Cloud的项目编号
.build()
integrityManager.requestIntegrityToken(integrityTokenRequest)
.addOnSuccessListener { response: IntegrityTokenResponse ->
val integrityToken = response.token()
tvStatus.text = "状态:令牌获取成功,正在验证..."
// 将令牌发送到你的服务器进行验证
sendTokenToServer(integrityToken)
}
.addOnFailureListener { e ->
runOnUiThread {
tvStatus.text = "状态:请求令牌失败 - ${e.localizedMessage}"
btnCheck.isEnabled = true
tvResult.text = "错误详情:\n${e.stackTraceToString()}"
}
}
}
private fun generateNonce(): String {
// 生成一个随机的Base64编码的字符串作为Nonce
val random = SecureRandom()
val bytes = ByteArray(16) // 16字节足够
random.nextBytes(bytes)
return Base64.encodeToString(bytes, Base64.URL_SAFE or Base64.NO_WRAP)
}
private fun sendTokenToServer(token: String) {
// 使用Retrofit进行网络请求
val retrofit = Retrofit.Builder()
.baseUrl(YOUR_SERVER_URL) // 注意:这里应该是基础URL,如 https://your-server.com/
.addConverterFactory(GsonConverterFactory.create())
.build()
val service = retrofit.create(VerificationService::class.java)
val call = service.verifyToken(VerificationRequest(token))
call.enqueue(object : Callback<VerificationResponse> {
override fun onResponse(call: Call<VerificationResponse>, response: Response<VerificationResponse>) {
runOnUiThread {
btnCheck.isEnabled = true
if (response.isSuccessful) {
val result = response.body()
tvStatus.text = "状态:服务器验证成功!"
// 格式化并显示详细的JSON结果
val gson = GsonBuilder().setPrettyPrinting().create()
val prettyJson = gson.toJson(result)
tvResult.text = prettyJson
// 可以在这里添加逻辑,解析result中的deviceIntegrity, appIntegrity等字段,给出更友好的提示
parseAndDisplaySummary(result)
} else {
tvStatus.text = "状态:服务器返回错误 - ${response.code()}"
tvResult.text = "错误响应体:\n${response.errorBody()?.string()}"
}
}
}
override fun onFailure(call: Call<VerificationResponse>, t: Throwable) {
runOnUiThread {
tvStatus.text = "状态:网络请求失败"
tvResult.text = "异常信息:\n${t.localizedMessage}"
btnCheck.isEnabled = true
}
}
})
}
// 定义网络请求接口
interface VerificationService {
@POST("verify") // 与你的服务器端点对应
fun verifyToken(@Body request: VerificationRequest): Call<VerificationResponse>
}
// 请求体和响应体的数据类
data class VerificationRequest(val token: String)
data class VerificationResponse(
// 根据Google API返回的实际JSON结构定义字段
val requestDetails: RequestDetails?,
val appIntegrity: AppIntegrity?,
val deviceIntegrity: DeviceIntegrity?,
val accountDetails: AccountDetails?
// ... 其他字段
) {
data class RequestDetails(val requestPackageName: String?, val timestampMillis: Long?)
data class AppIntegrity(val appRecognitionVerdict: String?, val packageName: String?, val certificateSha256Digest: List<String>?)
data class DeviceIntegrity(val deviceRecognitionVerdict: List<String>?)
data class AccountDetails(val appLicensingVerdict: String?)
}
// 解析并显示摘要信息
private fun parseAndDisplaySummary(response: VerificationResponse?) {
response?.let {
val summary = StringBuilder()
summary.append("=== 完整性检查摘要 ===\n\n")
// 设备完整性
val deviceVerdicts = it.deviceIntegrity?.deviceRecognitionVerdict
if (deviceVerdicts.isNullOrEmpty()) {
summary.append("设备完整性: 未通过\n")
} else {
summary.append("设备完整性: ${deviceVerdicts.joinToString(", ")}\n")
// 判断常见状态
when {
deviceVerdicts.contains("MEETS_DEVICE_INTEGRITY") -> summary.append(" → 设备状态良好,系统可信。\n")
else -> summary.append(" → 设备可能被修改(如Root、解锁Bootloader)。\n")
}
}
// 应用完整性
val appVerdict = it.appIntegrity?.appRecognitionVerdict
summary.append("\n应用完整性: ${appVerdict ?: "未知"}\n")
when (appVerdict) {
"MEETS_STRONG_INTEGRITY" -> summary.append(" → 应用来自Google Play商店,且未被篡改。\n")
"MEETS_BASIC_INTEGRITY" -> summary.append(" → 应用运行在基本完整的环境,但可能非官方渠道安装。\n")
null, "UNKNOWN" -> summary.append(" → 无法确定应用完整性。\n")
else -> summary.append(" → 应用完整性验证失败。\n")
}
// 在详细JSON结果前插入摘要
val currentText = tvResult.text.toString()
tvResult.text = "$summary\n--- 原始JSON详情 ---\n$currentText"
}
}
5. 测试、验证与结果解读
构建好应用后,最关键的环节就是测试。你需要在不同状态的设备上安装并运行你的Checker工具,观察结果。
5.1 构建与安装测试包
- 在Android Studio中,生成一个签名后的APK(或使用调试密钥签名的APK用于测试)。 重要 :你必须在Google Play Console中,将你用于签名的证书指纹(SHA-1或SHA-256)添加到你的应用的“Play Integrity API”配置下的“允许的证书”列表中。否则,验证会失败。
-
将APK安装到测试设备上。准备以下几类测试设备:
- 纯净官方设备 :未Root、未解锁Bootloader、从Play商店安装你的Checker。
- Root设备 :已获取Root权限(如通过Magisk)的设备。
- 模拟器 :Android Studio自带的模拟器。
-
侧载安装
:通过ADB命令
adb install app-debug.apk安装,模拟非Play商店渠道。
5.2 运行测试与结果分析
在每类设备上运行应用,点击检查按钮。观察状态和详细结果。
-
在纯净官方设备上
:预期结果应包含
deviceRecognitionVerdict: ["MEETS_DEVICE_INTEGRITY"]和appRecognitionVerdict: "MEETS_STRONG_INTEGRITY"。这是最理想的状态。 -
在Root设备上
:
deviceRecognitionVerdict很可能为空或不包含MEETS_DEVICE_INTEGRITY。但appRecognitionVerdict可能仍是MEETS_STRONG_INTEGRITY(如果App是从Play商店安装的)。这直观展示了设备完整性和应用完整性的区别。 -
在模拟器上
:通常两者都无法通过,
appRecognitionVerdict可能是MEETS_BASIC_INTEGRITY或更低。 -
通过ADB侧载安装
:
appRecognitionVerdict将不会是MEETS_STRONG_INTEGRITY,因为它不是来自Play商店。
5.3 常见问题排查实录
在开发和测试过程中,你几乎一定会遇到下面这些问题:
问题1:调用
requestIntegrityToken
直接失败,返回错误码
-11
(API_NOT_AVAILABLE)。
- 原因 :最常见的原因是设备上没有安装或未更新Google Play服务。或者,你使用的Cloud Project Number不属于一个已正确启用并配置了Play Integrity API的Google Cloud项目。
-
排查
:
- 确保测试设备上Google Play服务已更新至最新。
- 在Play Console中,确认你的应用(包名)已启用Play Integrity API。
-
确认代码中的
YOUR_CLOUD_PROJECT_NUMBER填写正确。这个数字是Google Cloud项目编号,不是Play Console的应用ID。你可以在Google Cloud Console项目概览页找到它。
问题2:服务器验证返回HTTP 403错误。
- 原因 :服务器端调用Google API时认证失败。
-
排查
:
- 确保服务器代码中加载的私钥JSON文件是正确的,且来自Play Console中对应应用的配置。
-
确保服务器代码中请求的
packageName参数与私钥所属的应用包名完全一致。 - 检查Google Cloud服务账号是否有权限访问Play Integrity API。你需要在Google Cloud Console为你的服务账号分配“Play Integrity API User”角色。
问题3:验证结果中
appRecognitionVerdict
始终不是
MEETS_STRONG_INTEGRITY
,即使是从Play商店安装的。
- 原因 :你可能使用了调试签名(debug keystore)构建APK进行测试,但未在Play Console中注册调试证书指纹。
-
排查
:
-
获取你的调试密钥的SHA-256指纹:
keytool -list -v -keystore ~/.android/debug.keystore -alias androiddebugkey -storepass android -keypass android -
将得到的SHA-256指纹值,添加到Play Console中你的应用下的
Play Integrity API->允许的证书列表中。 - 重新构建安装测试。注意,这个配置可能需要几个小时才能在全球生效。
-
获取你的调试密钥的SHA-256指纹:
问题4:网络搜索热词中提到的路径,如
/storage/emulated/0/android/data/com.tencent.tmgp.pubgmhd/...
。
- 解读 :这类路径是Android应用的标准数据存储路径(外部存储的应用私有目录)。它们与Play Integrity无关,但反映了用户或脚本可能尝试访问或修改应用数据。一个健壮的Play Integrity Checker工具,可以扩展功能,例如检查自身应用目录是否被异常访问或篡改,作为额外的安全层,但这属于应用自身防护范畴,而非Play Integrity API的标准功能。
6. 功能扩展与进阶应用
一个基础的Checker工具已经完成。但我们可以让它更强大,成为一个真正的“安全验证工具箱”。
6.1 增加本地缓存与历史记录
每次检查都产生宝贵的验证数据。我们可以将这些结果(时间戳、设备型号、各项完整性结果)保存到本地数据库(如Room),并提供一个历史记录查看界面。这有助于测试人员对比同一设备在不同状态(如Root前、Root后、隐藏Root后)下的验证结果变化。
6.2 集成设备信息收集
在发送令牌到服务器验证的同时,可以附带一些基本的、不涉及隐私的设备信息,如
Build.MODEL
,
Build.BRAND
,
Build.VERSION.SDK_INT
等。服务器端在返回验证结果时,可以将这些信息一并记录到日志中。这对于分析哪些设备型号、系统版本更容易出现验证问题非常有帮助。
6.3 模拟“攻击”与绕过检测测试(仅供安全研究)
为了深入理解Play Integrity API的防护能力,你可以在受控环境中进行测试:
- 使用Magisk Hide/DenyList :在Root设备上,配置Magisk对你的Checker应用隐藏Root状态。观察验证结果是否发生变化。这能帮你了解Play Integrity API检测Root的深度。
- 在模拟器上安装Google Play服务 :一些修改过的模拟器镜像包含了Google Play服务。在这些模拟器上运行你的Checker,看它能否被识别出来。
- 使用Xposed/LSPosed模块 :编写或使用现有模块,尝试Hook Play Integrity API的相关调用,返回伪造的“通过”结果。这能帮助你评估API的抗篡改能力。
重要警告 :此类测试应仅限于你自己拥有完全控制权的设备和应用,用于安全研究和提升应用防护。绝对不要对他人应用进行此类测试,这不仅是非法的,也违反Google Play的政策。
6.4 构建自动化测试套件
你可以将Checker工具的核心验证逻辑封装成一个库(Library Module),然后为你主应用的UI自动化测试(使用Espresso或UI Automator)添加一个测试用例:在关键流程(如登录、支付)开始前,自动运行一次完整性检查,并将结果输出到测试日志中。这能在回归测试中持续监控你的应用运行环境是否安全合规。
构建一个完整的Play Integrity Checker工具,远不止是调用一个API那么简单。它迫使你深入理解Android安全模型、客户端-服务端交互、证书管理以及各种设备状态。通过这个过程,你获得的不仅仅是这个工具本身,而是一套应对应用安全、反作弊、渠道保护等现实问题的完整方法论和实战能力。当你再次看到那些试图绕过验证的非常规路径时,你就能更清晰地知道你的防线在哪里,又该如何加固它。

3118

被折叠的 条评论
为什么被折叠?



