在您的应用中声明权限之前,请考虑您是否需要这样做。如果应用声明权限,那么每当用户尝试使用需要运行时权限的应用功能时,应用便不得不中断用户的操作,请求相应权限。然后,用户必须做出决定。如果用户不能理解您的应用为何请求特定权限,可能就会拒绝授予该权限,甚至卸载您的应用。
想想是否有其他已安装的应用能够代您的应用执行相应功能。如果有的话,您应使用 intent 将任务委托给其他应用。这样您就不必声明所需的权限,因为其他应用会声明该权限。
声明权限的替代方案
本部分将介绍您的应用可在不声明任何权限的情况下实现的几个用例。
显示附近的地点
您的应用可能需要了解用户的大致位置。对于显示位置感知信息(如附近的餐馆)而言,这非常有用。
在某些用例中,您的应用需要粗略的设备位置估算值。在这类情况下,请根据应用需要位置感知信息的频率,执行以下某项操作:
- 如果您的应用需要更频繁地获取位置信息,请声明
ACCESS_COARSE_LOCATION
权限。该权限提供根据位置信息服务推测的设备位置信息,如介绍大致位置信息精确度的文档中所述。 - 如果您的应用需要获取位置信息的频率较低,或只需要获取一次,请考虑改为让用户输入地址或邮政编码。
在其他用例中,您的应用需要更确切的设备位置估算值。仅在这类情况下,您可以声明 ACCESS_FINE_LOCATION
权限。
拍摄照片
用户可能会在您的应用中使用预安装的系统相机应用来拍摄照片。
在这种情况下,请勿声明 CAMERA
权限,而是改为调用 ACTION_IMAGE_CAPTURE
intent 操作。
录制视频
用户可能会在您的应用中使用预安装的系统相机应用来录制视频。
在这种情况下,请勿声明 CAMERA
权限,而是改为调用 ACTION_VIDEO_CAPTURE
intent 操作。
打开您的应用创建的媒体
您的应用可能会显示用户在使用您的应用时创建的媒体内容,例如照片或视频。在这种情况下,只要您的应用以 Android 10 或更高版本为目标平台,您就无需在搭载 Android 10(API 级别 29)或更高版本的设备上使用 READ_EXTERNAL_STORAGE
权限。如果您的应用以 Android 10 为目标平台,请停用分区存储功能。
为了与旧设备兼容,请声明 READ_EXTERNAL_STORAGE
权限,并将 android:maxSdkVersion
设置为 28
。
在媒体库所熟知的下列某个集合中找到该文件:
您可以使用 ContentResolver
直接从媒体库查询媒体内容,而不是尝试自行发现媒体内容。
打开文档
您的应用可能会显示用户在您的应用或其他应用中创建的文档。一个常见的示例是文本文件。
在这种情况下,只要您的应用以 Android 10 或更高版本为目标平台,您就无需在搭载 Android 10 或更高版本的设备上使用 READ_EXTERNAL_STORAGE
权限。如果您的应用以 Android 10 为目标平台,请停用分区存储功能。
为了与旧设备兼容,请声明 READ_EXTERNAL_STORAGE
权限,并将 android:maxSdkVersion
设置为 28
。
根据创建文档的是哪个应用,执行下列操作之一:
识别正在运行应用的某个实例的设备
您的应用的特定实例可能需要知道它正在哪个设备上运行。对于采用设备专属偏好设置或提供消息功能(如面向电视设备和穿戴式设备提供不同的播放列表)的应用而言,这非常有用。
在这种情况下,请勿直接获取设备的 IMEI。实际上,从 Android 10 开始,您已无法这样做。请改用以下方法之一:
- 使用实例 ID 库获取应用实例的唯一设备标识符。
- 创建您自己的标识符,将其存储在您的应用存储空间。使用基本系统函数,例如
randomUUID()
。
通过蓝牙与设备配对
通过利用蓝牙将数据传输到其他设备,您的应用或许能提供更好的体验。
如需支持此功能,请勿声明 ACCESS_FINE_LOCATION
、ACCESS_COARSE_LOCATIION
或 BLUETOOTH_ADMIN
权限,而是改用配套设备配对。
在应用中断运行时暂停媒体
在用户接听电话或用户配置的闹钟触发时,您的应用应暂停播放所有媒体,直到其重新获得音频焦点再恢复播放。
如需支持此功能,请勿声明 READ_PHONE_STATE
权限,而是改为实现 onAudioFocusChange()
事件处理程序,它会在系统转换其音频焦点时自动运行。
详细了解如何实现音频焦点。
过滤来电
为了给用户最大限度地减少不必要的干扰,您的应用可能会过滤掉垃圾来电。
如需支持此功能,请勿声明 READ_PHONE_STATE
权限,而是改用 CallScreeningService
API。