Android 11+如何编程检测应用是否从Google Play安装
Android 11+ 检测应用是否从Google Play安装的可行方案
以下方案均不需要申请QUERY_ALL_PACKAGES等特殊权限,可直接用于非GP渠道安装场景下禁用AdMob广告的需求:
方案1:Google官方Play Install Referrer API(优先推荐,准确率最高)
这是Google Play官方提供的安装来源查询接口,不受Android 11包可见性规则限制,只要设备搭载可用的Google Play服务就能返回准确结果,无额外权限要求。
- 接入步骤:
- 在应用模块的
build.gradle中引入官方依赖:implementation "com.android.installreferrer:installreferrer:2.2" - 应用启动时异步连接客户端,校验安装来源,核心实现代码(Kotlin):
- 在应用模块的
// 初始化客户端 val referrerClient = InstallReferrerClient.newBuilder(appContext).build() referrerClient.startConnection(object : InstallReferrerStateListener { override fun onInstallReferrerSetupFinished(resultCode: Int) { when (resultCode) { InstallReferrerResponse.OK -> { val referrerData = referrerClient.installReferrer // Google Play安装的来源包名固定为com.android.vending val isGpInstall = referrerData.installOriginPackage == "com.android.vending" if (!isGpInstall) { // 非GP渠道,关闭AdMob广告加载逻辑 disableAdLoad() } referrerClient.endConnection() } // 设备无可用Play服务、服务不支持的场景,直接按非GP渠道处理 InstallReferrerResponse.FEATURE_NOT_SUPPORTED, InstallReferrerResponse.SERVICE_UNAVAILABLE -> disableAdLoad() } } override fun onInstallReferrerServiceDisconnected() {} })
- 该接口返回的是Google Play服务端记录的真实安装来源,第三方渠道、侧载安装的场景要么返回非GP的安装包名,要么无法连接服务,不会出现误判。
方案2:包可见性适配 + PackageManager原生API(轻量无额外依赖)
你之前查到的PackageManager方案失效,核心原因是Android 11引入的包可见性限制:默认情况下应用无法查询其他非核心应用的包信息,直接调用getInstallerPackageName会返回null。只要在清单文件做简单适配,不需要特殊权限就能正常拿到结果:
- 在
AndroidManifest.xml中添加如下查询声明:
<queries> <package android:name="com.android.vending" /> </queries>
- 直接调用原生API判断安装来源:
val installerPackage = appContext.packageManager.getInstallerPackageName(appContext.packageName) val isGpInstall = installerPackage == "com.android.vending"
- 注意:该方案在部分深度定制的第三方ROM上可能被篡改安装器记录,稳定性弱于方案1,适合不想引入额外依赖的场景使用。
方案3:签名校验兜底(防二次打包、防篡改)
如果需要覆盖第三方渠道二次打包你的应用的场景,可以搭配GP应用签名校验做兜底:在Google Play后台开启Play应用签名功能后,提取GP签发的应用证书哈希值,硬编码在应用内,启动时校验当前运行应用的签名是否匹配,不匹配则直接禁用广告。
- 核心校验逻辑无额外权限要求,兼容所有Android版本:
@Suppress("DEPRECATION") fun checkAppSignature(context: Context, validGpHash: String): Boolean { val pkgInfo = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { context.packageManager.getPackageInfo( context.packageName, PackageManager.GET_SIGNING_CERTIFICATES ) } else { context.packageManager.getPackageInfo( context.packageName, PackageManager.GET_SIGNATURES ) } val signers = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { pkgInfo.signingInfo.apkContentsSigners } else { pkgInfo.signatures } val currentHash = signers.firstOrNull()?.toByteArray()?.let { hashSHA256(it) } return currentHash == validGpHash }
补充说明:Firebase App Check等移动应用证明服务确实不适合该场景,这类服务的核心作用是校验请求是否来自你未被篡改的官方应用,无法区分官方包的具体安装渠道,无法满足需求。
内容的提问来源于stack exchange,提问作者Shrinidhi K
相关产品推荐
相关产品推荐

