在 Android 11 (API 30) 及更高版本中,通过在 AndroidManifest.xml 中添加
html
<queries>
元素声明需要查询的特定应用商店包名后:
-
不需要额外请求权限 (如 QUERY_ALL_PACKAGES )即可查询这些应用的安装状态
-
这是 Google 官方推荐的替代方案,完全符合隐私政策要求
具体说明:
1. 优势 :
- 无需动态请求权限
- 不会触发 Google Play 的隐私审核问题
- 仅能查询明确声明的包名,更安全
2. 实现方式 :
在 AndroidManifest.xml 中添加如下内容:
XML
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<queries>
<!-- 华为应用商店 -->
<package android:name="com.huawei.appmarket" />
<!-- 小米应用商店 -->
<package android:name="com.xiaomi.market" />
<!-- OPPO应用商店 -->
<package android:name="com.oppo.market" />
<package android:name="com.heytap.market" />
<!-- VIVO应用商店 -->
<package android:name="com.bbk.appstore" />
<!-- 魅族应用市场 -->
<package android:name="com.meizu.mstore" />
<!-- 荣耀应用商店 -->
<package android:name="com.hihonor.appmarket" />
<!-- 腾讯应用宝 -->
<package android:name="com.tencent.android.qqdownloader" />
<!-- 360手机助手 -->
<package android:name="com.qihoo.appstore" />
<!-- 百度手机助手 -->
<package android:name="com.baidu.appsearch" />
<!-- 其他应用商店... -->
</queries>
</manifest>
3. 代码查询方式 :
可以简化查询逻辑,直接检查特定包名:
java
public static List<String> checkHasInsatllAppStores(Context context) {
List<String> list = new ArrayList<>();
PackageManager pm = context.getPackageManager();
for (String pkg : STORE_PACKAGES) {
try {
pm.getPackageInfo(pkg, PackageManager.GET_ACTIVITIES);
list.add(pkg);
} catch (PackageManager.NameNotFoundException e) {
// 应用未安装
}
}
return list;
}
4.典型使用场景 :
java
try {
// 查询微信是否安装
PackageInfo info = pm.getPackageInfo("com.tencent.mm", PackageManager.GET_ACTIVITIES);
Log.d("App", "微信版本:" + info.versionName);
} catch (PackageManager.NameNotFoundException e) {
// 应用未安装
}
- 注意事项 :
- 此方案在 Android 11+ 是必须的
- 在 Android 10 及以下版本会自动生效
- 只能查询明确声明的包名
- 需要确保 <queries> 中包含了所有需要检测的应用商店包名
- 需要声明 <queries> 或权限(Android 11+)
- 主线程调用可能引发ANR,建议在子线程执行
- 捕获 NameNotFoundException 是必须的
这种方案既解决了权限问题,又符合 Google Play 的隐私政策要求,是当前查询特定应用安装状态的最佳实践。