官方描述:
Android11更改了 应用 查询在设备上安装其他应用信息(
queryIntentActivities)以及与之交互(startService)的方式。使用<queries>元素,应用可以定义一组自身可访问的其他软件包。通过告知系统应向您的应用现实哪些其他软件包,此元素有助于鼓励最小权限原则。
一:被影响的Api
1. PackageManager.queryIntentActivities:
- <Android 11(Api Level 30):应用可以通过该方法查询设备上所有符合参数intent的Activity列表。
- >=Android 11:系统隐藏了大部分App信息,应用只能查询部分App。除非该应用显示声明查看某个package下的信息。
上述代码,当App的targetSdkVersion为29时,返回的是当前手机上所有被安装的app信息。(我测试机上的App)
当App的targetSdkVersion为30时,返回的是被系统过滤的App信息:
这里说明下哪些App系统会默认让App可见:
- your own app.
- Certain system packages, such as the media provider, that implement core Android functionality.
- the app that installed your app.
- Any app that launches an activity in your app using the startActivityForResult() method
- Any app that starts or binds to a service in your app.
- Any app that accesses a content provider in your app.
- Any app that has a content provider, where your app has been granted URI permission to access the content provider.
- Any app that receives input from your app. This case applies only when your app provides input as an input method editor.
如果想要查询某个App的activity信息,可以在manifest中增加标签:
<manifest package="com.example.game">
<queries>
<package android:name="com.example.store" />
<package android:name="com.example.services" />
</queries>
...
</manifest>
这样使用queryIntentActivities查询时,就会包含queris里声明的app信息。
2.Context.startService:
- <Android 11(Api Level 30):应用可以通过该方法启动其他App的service。
- >=Android 11(Api Level 30):应用必须在AndroidManifest中用queries声明要启动的service对应的包名才可以启动,否则系统会说找不到相应的Service。
上述代码,当App的targetSdkVersion为29时,可以启动其他App的service。
当App的targetSdkVersion为30时,执行该代码不会抛出异常,但系统日志会提示找不到相应的service。
如果想要正确执行,则需要在manifest中加入queries:
<manifest package="com.example.game">
<queries>
<package android:name="com.example.store" />
</queries>
...
</manifest>
另外startActivity方法在Android 11上不受影响,即使queries中没有声明,也可以打开其他App的页面。