7、权限问题
Android 11(API级别30)以及更高版本, 更改了应用查询用户已在设备上安装的其他应用以及与之交互的方式。使用 <queries>
元素,应用可以定义一组自身可访问的其他软件包。
如果您的应用以 Android 11 或更高版本为目标平台,您可能需要在应用的清单文件中添加 <queries>
元素。在 <queries>
元素中,您可以按软件包名称、intent 签名或提供程序授权指定软件包。
如果解决权限问题就会出现这样的错误,无法找到URI,java.lang.IllegalArgumentException: Unknown URL content://com.example.sqlite.provider/book
。解决方法如下:
7.1 指定软件包名进行交互
现在新的应用ententprovidertest
是无法访问刚刚继承过ContenProvider
应用名为sqlite
的应用,我们需要指定sqlite
的软件包名:
<queries>
<package android:name="com.example.sqlite" />
</queries>
这样我们使用ententprovidertest,就可以操作刚刚实现ContenProvider
的应用的数据库。
7.2 在给定提供程序授权的情况下查询应用及与之交互
如果您需要查询 Content Provider 但不知道具体的软件包名称,您可以在 <provider>
元素中声明该提供程序授权,假设我们不知道sqlite
应用的包名,我们只知道它包含一个内容提供者:
<provider
android:name=".DatabaseProvider"
android:authorities="com.example.sqlite.provider"
android:enabled="true"
android:exported="true"></provider>
我们需要在ententprovidertest
应用中查询是否存在这个sqlite
应用的authorities
。在ententprovidertest
应用的AndroidManifest中加入这段代码:
<queries>
<provider android:authorities="com.example.sqlite.provider"/>
</queries>
这样,ententprovidertest
应用就可以在运行时查询设备上是否安装了名为 sqlite
的应用,并可以访问其内容提供者 com.example.sqlite.provider
提供的数据。
请注意,如果在单个 <queries>
元素中需要声明多个提供者授权,您可以使用以英文分号分隔的方式来列出它们,如下所示:
<queries>
<provider android:authorities="com.example.sqlite.provider; com.example.otherprovider" />
</queries>
或者,您也可以使用多个 <provider>
元素,将它们全部放在同一个 <queries>
元素中,如下所示:
<queries>
<provider android:authorities="com.example.sqlite.provider" />
<provider android:authorities="com.example.otherprovider" />
</queries>
7.3 查询所有应用及与之交互
在极少数情况下,您的应用可能需要查询设备上的所有已安装应用或与之交互,不管这些应用包含哪些组件。为了允许您的应用看到其他所有已安装应用,系统会提供 QUERY_ALL_PACKAGES
权限。它允许应用查询设备上所有已安装应用的信息,包括它们的包名、版本。
下面列出了适合添加 QUERY_ALL_PACKAGES
权限的用例的一些示例:
- 启动器应用
- 无障碍应用
- 浏览器
- 点对点 (P2P) 共享应用
- 设备管理应用
- 安全应用
在ententprovidertest
应用的AndroidManifest中加上:
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"
tools:ignore="QueryAllPackagesPermission" />
QUERY_ALL_PACKAGES
权限:允许查询设备上的任何正常应用程序,无论清单声明如何。
防护级别:普通
文章完整版请移动步:探究ContentProvider、运行时申请权限的做法、访问其他程序中的数据、创建自己的ContentProvider、实现跨程序数据共享并且解决存在的权限问题导致无法访问。