一、问题场景及现象
最近各应用市场发出需要兼容android11的要求,于是在新版本里面将目标版本升级到30,但是升级后发现应用中判断其他应用是否安装的方法执行失败,每次获取的安装状态都是未安装。最终定位到原因在android11上的版本兼容上。
在targetSdkVersion 升级到30之前,通过packagemanager去获取对应包名的信息是能获取成功的,但升级后就无法获取到对应的信息了
二、解决方法
在清单文件AndroidManifest.xml中声明以下权限即可
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"
tools:ignore="QueryAllPackagesPermission"/>
<!-- 如果QUERY_ALL_PACKAGES被媒体覆盖,通过以下标签使得匹配intent的app对于应用是可见的! -->
<queries>
<intent>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent>
</queries>
三、问题出现原因
在android11上,google进行了软件包可见性过滤,基本上将第三方开发的应用都进行过滤掉了。
点击查看对应官方文档
通过文档或截图,我们知道,如果我们使用的getInstalledApplications()方法去获取应用信息会受到影响,通过代码调试得到以下影响程度
不在清单文件中声明权限,packageManager.getInstalledPackages(0)获取的已安装应用只有系统级应用,无第三方开发app信息。
声明了QUERY_ALL_PACKAGES,再通过该方法即可拿到手机系统内所有应用,自然能获取某个包名对应的app是否安装、应用名称、版本号等
但是该权限是获取所有应用信息、在官方的推荐程度为不推荐、更推荐使用标签去进行精准匹配应用,
如我们在上面的解决方法中的标签,其表示匹配所有满足具有该intent定义的应用,普通应用都会定义有这样一个intent,其实也算是获取所有应用。
如果我们只需要知道某一个或某几个应用,我们可以这样去定义标签
<queries>
<package android:name="com.tencent.mm" /> //微信
<package android:name="com.tencent.mobileqq" /> //QQ
<package android:name="应用包名" />
</queries>
四、扩展一下
国内某些手机会有一个“读取应用列表权限”、我们在使用getInstalledPackages(0)去获取所有安装的应用包时会触发该权限,会直接弹出一个系统应用权限申请,拒绝之后我们也会出现获取不到应用列表信息。
但是可以获取到指定包名的应用信息,当然这个获取会被上面的android11的权限影响,即无权限或该应用对本应用不可见即无法获取该应用权限