限制与其他应用的交互

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

本指南介绍了如何查看其他应用已声明的权限集,还介绍了如何配置 activity、服务、content provider 和广播接收器来限制其他应用与您的应用互动的方式。

查看其他应用的权限

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

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

    此屏幕会显示一系列权限组。系统会将应用所声明的权限整理到这些权限组内。

您还可以通过其他一些实用方式来检查权限:

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

限制与应用的 activity 的互动

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

限制与应用的服务的互动

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

限制与应用的 content provider 的互动

<provider> 标记使用 android:permission 属性,以限制哪些其他应用可以访问 ContentProvider 中的数据。(content provider 有重要的附加安全工具可供其使用,称为 URI 权限,将在下一部分介绍。)与其他组件不同,您可以为 content provider 设置两个单独的权限属性:android:readPermission,用于限制哪些其他应用可以从 provider 读取数据;以及 android:writePermission,用于限制哪些其他应用可以向其写入数据。请注意,如果某个 provider 有读取权限和写入权限保护,则仅拥有写入权限并不允许应用从该 provider 读取数据。

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

根据 URI 授予权限

您可以进一步对其他应用如何访问您应用的 content provider 进行精细控制。具体而言,您的 content provider 可以利用读取和写入权限保护自己,同时仍允许其直接客户端与其他应用共享特定 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 的读取、写入或读取/写入权限。无论从更笼统的角度来说其他应用是否有权访问 content provider 中的数据,它都会获得针对该 URI 的上述权限。

例如,假设用户正在使用您的应用查看包含图片附件的电子邮件。一般来说,其他应用本该无法访问电子邮件内容,但它们可能希望查看这张图片。您的应用可以结合使用 intent 和 Intent.FLAG_GRANT_READ_URI_PERMISSION intent 标志,以便图片查看应用能够查看这张图片。

另一个需要考虑的因素是应用可见性。如果您的应用以 Android 11(API 级别 30)或更高版本为目标平台,在默认情况下,系统会自动让部分应用对您的应用可见,并隐藏其他应用。如果您的应用具有 content provider,并且已向其他应用授予 URI 权限,那么您的应用会自动对该应用可见

如需了解详情,请查看介绍 grantUriPermission()revokeUriPermission()checkUriPermission() 方法的参考资料。

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

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

同样,您可以向 Context.registerReceiver() 提供权限,用于控制哪些其他应用可以向程序化地注册的接收器发送广播。另一方面,您可以在调用 Context.sendBroadcast() 时提供权限,用于限制哪些广播接收器可以接收广播。

请注意,接收器和广播方可能都需要权限。发生这种情况时,两项权限检查都必须顺利通过,系统才会将 intent 传递到关联的目标。如需了解详情,请参阅通过权限限制广播