限制与其他应用的交互

权限不仅用于请求系统功能。您还可以限制其他应用如何与您的应用组件进行交互。

本指南介绍如何检查另一个应用声明的权限集。本指南还介绍了如何配置活动、服务、内容提供程序和广播接收器以限制其他应用如何与您的应用进行交互。

检查另一个应用的权限

要查看另一个应用声明的权限集,请使用设备或模拟器完成以下步骤

  1. 打开应用的应用信息屏幕。
  2. 选择权限应用权限屏幕加载。

    此屏幕显示一组权限组。系统将应用声明的权限集组织到这些组中。

还有许多其他有用的方法可以检查权限

  • 在调用服务期间,将权限字符串传递到 Context.checkCallingPermission()。此方法返回一个整数,指示该权限是否已授予当前调用进程。请注意,这只能在您执行来自另一个进程的调用时使用,通常是通过从服务发布的 IDL 接口或以某种方式提供给另一个进程的方式。
  • 要检查是否已向另一个进程授予特定权限,请将进程 (PID) 传递到 Context.checkPermission()
  • 要检查另一个包是否已获得特定权限,请将包名传递到PackageManager.checkPermission()

限制与应用活动的交互

在清单中的 <activity>标签中使用android:permission属性来限制哪些其他应用可以启动该Activity。在Context.startActivity()Activity.startActivityForResult()期间会检查此权限。如果调用者没有所需的权限,则会发生SecurityException

限制与应用服务的交互

在清单中的 <service>标签中使用android:permission属性来限制哪些其他应用可以启动或绑定到关联的Service。在Context.startService()Context.stopService()Context.bindService()期间会检查此权限。如果调用者没有所需的权限,则会发生SecurityException

限制与应用内容提供商的交互

使用 <provider>标签中的android:permission属性来限制哪些其他应用可以访问ContentProvider中的数据。(内容提供商可以使用称为URI权限的重要附加安全机制,这将在下一节中介绍。)与其他组件不同,您可以为内容提供商设置两个单独的权限属性: android:readPermission限制哪些其他应用可以从提供商读取数据,而 android:writePermission限制哪些其他应用可以写入数据。请注意,如果提供商同时受读取和写入权限保护,则仅持有写入权限并不允许应用从提供商读取数据。

首次检索提供商以及应用对提供商执行操作时,都会检查权限。如果请求的应用没有任一权限,则会发生SecurityException。使用ContentResolver.query()需要读取权限;使用ContentResolver.insert()ContentResolver.update()ContentResolver.delete()需要写入权限。在所有这些情况下,如果没有所需的权限,都会导致SecurityException

基于每个URI授予访问权限

系统为您提供了对其他应用如何访问应用内容提供商的更细粒度的控制。特别是,您的内容提供商可以使用读取和写入权限来保护自身,同时仍然允许其直接客户端与其他应用共享特定URI。要声明您的应用对该模型的支持,请使用android:grantUriPermissions属性或<grant-uri-permission>元素。

您还可以基于每个URI授予权限。启动活动或将结果返回到活动时,设置Intent.FLAG_GRANT_READ_URI_PERMISSION意图标志、Intent.FLAG_GRANT_WRITE_URI_PERMISSION意图标志或这两个标志。这分别为包含在意图中的数据URI授予其他应用读取、写入或读取/写入权限。其他应用将获得这些特定URI的权限,而不管它们是否具有更普遍地访问内容提供商中数据的权限。

例如,假设用户正在使用您的应用查看带有图像附件的电子邮件。其他应用通常不应能够访问电子邮件内容,但它们可能对查看图像感兴趣。您的应用可以使用意图和Intent.FLAG_GRANT_READ_URI_PERMISSION意图标志来允许图像查看应用查看图像。

另一个需要考虑的是应用可见性。如果您的应用面向 Android 11(API 级别 30)或更高版本,系统会自动使某些应用对您的应用可见,并默认隐藏其他应用。如果您的应用具有内容提供商并已向另一个应用授予 URI 权限,则您的应用会自动对该其他应用可见

有关更多信息,请查看grantUriPermission()revokeUriPermission()checkUriPermission()方法的参考材料。

限制与应用广播接收器的交互

<receiver>标签中使用android:permission属性来限制哪些其他应用可以向关联的BroadcastReceiver发送广播。在Context.sendBroadcast()返回后,系统会尝试将提交的广播传递给给定的接收器,此时会检查权限。这意味着权限失败不会导致异常抛回调用方——它只是不传递Intent

同样,您可以向Context.registerReceiver()提供权限,以控制哪些其他应用可以向以编程方式注册的接收器广播。反过来,您可以在调用Context.sendBroadcast()时提供权限,以限制哪些广播接收器可以接收广播。

请注意,接收器和广播器都可以要求权限。发生这种情况时,必须通过两个权限检查才能将意图传递给关联的目标。有关更多信息,请参阅使用权限限制广播