限制与其他应用的互动

权限不仅用于请求系统功能,您还可以限制其他应用与您应用组件的互动方式。

本指南介绍了如何检查其他应用已声明的权限集。本指南还说明了如何配置 Activity、Service、内容提供程序和广播接收器,以限制其他应用与您的应用互动的方式。

检查其他应用的权限

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

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

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

还有许多其他有用的方式来检查权限

  • 在调用服务时,将权限字符串传入 Context.checkCallingPermission()。此方法会返回一个整数,指示当前调用进程是否已获得该权限。请注意,此方法只能在执行来自另一个进程的调用时使用,通常通过从服务发布或以其他方式提供给另一个进程的 IDL 接口来实现。
  • 要检查另一个进程是否已获得特定权限,请将进程 (PID) 传入 Context.checkPermission()
  • 要检查另一个软件包是否已获得特定权限,请将软件包名称传入 PackageManager.checkPermission()

限制与其他应用 Activity 的互动

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

限制与其他应用 Service 的互动

使用清单中 <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 授予权限。在启动 Activity 或向 Activity 返回结果时,设置 Intent.FLAG_GRANT_READ_URI_PERMISSION intent 标志、Intent.FLAG_GRANT_WRITE_URI_PERMISSION intent 标志或两个标志。这会分别授予其他应用对 intent 中包含的数据 URI 的读取、写入或读/写权限。其他应用会获得这些特定 URI 的权限,无论它们是否普遍拥有访问内容提供程序中数据的权限。

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

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

如需了解更多信息,请查看 grantUriPermission()revokeUriPermission()checkUriPermission() 方法的参考资料。

限制与其他应用广播接收器的互动

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

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

请注意,接收器和广播方都可以要求权限。发生这种情况时,两个权限检查都必须通过,intent 才能传递到关联的目标。如需了解更多信息,请参阅通过权限限制广播