权限不仅仅用于请求获取系统功能的使用权。您还可以限制其他应用与您的应用组件互动的方式。
本指南介绍了如何查看其他应用已声明的权限集,还介绍了如何配置 activity、服务、content provider 和广播接收器来限制其他应用与您的应用互动的方式。
查看其他应用的权限
如需查看其他应用声明的权限集,请使用设备或模拟器完成以下步骤:
- 打开应用的应用信息屏幕。
选择权限。系统会加载应用权限屏幕。
此屏幕会显示一系列权限组。系统会将应用所声明的权限整理到这些权限组内。
您还可以通过其他一些实用方式来检查权限:
- 在调用某项服务期间,将权限字符串传入
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 传递到关联的目标。如需了解详情,请参阅通过权限限制广播。