- 1:隐私和更新
- 1.1:分区存储强制执行
- 1.2:权限
- 1.3:前台服务类型
- 2:功能和API
- 2.1:消息框
- 2.2:无线调试
最近,Android 11 Beta 版已经发布,可供开发、测试和反馈。可以在 Pixel 2、Pixel 3、Pixel 3a 或 Pixel 4上使用。在本文中,将着重介绍Android 11 中的部分功能和API变更。
隐私和更新
Android 11 基于 Android 早期版本构建,增加了多种功能和更新,以保障用户安全并提高透明度和可控性。在 Android 11 中的主要变更如下:
隐私权变更 | 受影响的应用 | 解决方法 |
强制执行分区存储机制:以 Android 11 为目标平台的应用始终会受分区存储行为的影响 | 以 Android 11 为目标平台的应用,以及以 Android 10 为目标平台且未将 requestLegacyExternalStorage 设为 true 以停用分区存储的应用 | 更新应用以使用分区存储 |
一次性权限:通过一次性权限,用户可以授予对位置信息,麦克风和摄像头的临时访问权限 | 以任何版本为目标平台且请求位置信息、麦克风或摄像头权限的应用 | 在尝试访问受某项权限保护的数据之前,检查应用是否具有该权限 |
自动重置权限:如果用户在 Android 11 上几个月未与应用互动,系统会自动重置应用的敏感权限 | 以 Android 11 为目标平台且在后台执行大部分工作的应用 | 要求用户阻止系统重置应用的权限 |
后台位置信息访问权限:Android 11 更改了用户向应用授予后台位置信息权限的方式 | 以Android 11为目标平台且需要访问后台位置信息的应用 | 通过对权限请求方法的多次单独调用,逐步请求前台(粗略或精确)和后台位置权限。必要时,说明用户授予该权限所能得到的益处 |
软件包可见性:Android 11 更改了应用查询同一设备上的其他已安装应用及与之互动的方式 | 以 Android 11 为目标平台且与设备上的其他已安装应用交互的应用 | 将 <queries> 元素添加到应用的清单 |
前台服务类型:Android 11 更改了前台服务访问摄像头和麦克风数据的方式 | 以 Android 11 为目标平台且在前台服务中访问摄像头或麦克风的应用 | 分别在访问摄像头数据和麦克风数据的服务中声明 camera 和 microphone 前台服务类型 |
分区存储强制执行
以 Android 10(API 级别 29)为目标平台的应用仍可请求 requestLegacyExternalStorage 属性。应用可以利用此标记暂时停用与分区存储相关的变更,例如授予对不同目录和不同类型的媒体文件的访问权限。当将应用更新为以 Android 11 为目标平台后,系统会忽略 requestLegacyExternalStorage 标记。
如果应用在 Android 10 设备上运行时选择退出分区存储,建议继续在应用的清单文件中将 requestLegacyExternalStorage
设为 true
。这样,应用就可以在运行 Android 10 的设备上继续按预期运行。
如果应用使用旧版存储模型且之前以 Android 10 或更低版本为目标平台,可能会将数据存储到启用分区存储模型后应用无法访问的目录中。在以 Android 11 为目标平台之前,请将数据迁移到与分区存储兼容的目录。在大多数情况下,可以将数据迁移到应用专用目录。
执行批量操作
为实现各种设备之间的一致性和增加用户便利性,Android 11向MediaStore API中添加了多种方法。对于希望简化特定媒体文件更改流程(例如在原位置编辑照片)的应用而言,这些方法尤为有用。
方法 | 说明 |
createWriteRequest() | 用户向应用授予对指定媒体文件组的写入访问权限的请求。 |
createFavoriteRequest() | 用户将设备上指定的媒体文件标记为“收藏”的请求。对该文件具有读取访问权限的任何应用都可以看到用户已将该文件标记为“收藏”。 |
createTrashRequest() | 用户将指定的媒体文件放入设备垃圾箱的请求。垃圾箱中的内容会在系统定义的时间段后被永久删除。 |
createDeleteRequest() | 用户立即永久删除指定的媒体文件(而不是先将其放入垃圾箱)的请求。 |
系统在调用以上任何一个方法后,会构建一个 PendingIntent 对象。应用调用此 intent 后,用户会看到一个对话框,请求用户同意应用更新或删除指定的媒体文件。
例如,以下是构建 createWriteRequest() 调用的方法:
val urisToModify = /* 要修改的内容URI的集合。*/
val editPendingIntent = MediaStore.createWriteRequest(contentResolver,
urisToModify)
// 启动系统提示,请求用户对该操作的许可。
startIntentSenderForResult(editPendingIntent.intentSender, EDIT_REQUEST_CODE,
null, 0, 0, 0)
评估用户的响应,然后继续操作,或者在用户不同意时向用户说明应用为何需要获取权限:
override fun onActivityResult(requestCode: Int, resultCode: Int,
data: Intent?) {
...
when (requestCode) {
EDIT_REQUEST_CODE ->
if (resultCode == Activity.RESULT_OK) {
/* 授予编辑请求;继续。*/
} else {
/* 编辑请求未获批准; 向用户解释。 */
}
}
}
权限
在 Android 11 中,用户能够针对位置信息、麦克风和摄像头指定更精细的权限。此外,系统会重置以 Android 11 为目标平台的未使用应用的权限。如果应用读取与电话号码相关的信息,则可能需要更新其权限声明。
单次授权
在 Android 11 中,每当应用请求与位置信息、麦克风或摄像头相关的权限时,面向用户的权限对话框会包含仅限这一次选项。如果用户在对话框中选择此选项,系统会向应用授予临时的单次授权。
然后,应用可以在一段时间内访问相关数据,具体时间取决于应用的行为和用户的操作:
- 当应用的 Activity 可见时,应用可以访问相关数据。
- 如果用户将应用转为后台运行,应用可以在短时间内继续访问相关数据。
- 如果在 Activity 可见时启动了一项前台服务,并且用户随后将应用转到后台,那么应用可以继续访问相关数据,直到该前台服务停止。
- 如果用户撤消单次授权(例如在系统设置中撤消),无论否启动了前台服务,应用都无法访问相关数据。与任何权限一样,如果用户撤消了应用的单次授权,应用进程就会终止 。
当用户下次打开应用并且应用中的某项功能请求访问位置信息、麦克风或摄像头时,系统会再次提示用户授予权限。
自动重置未使用的应用的权限
如果应用以 Android 11 为目标平台并且数月未使用,系统会通过自动重置用户已授予应用的运行时敏感权限来保护用户数据。此操作与用户在系统设置中查看权限并将应用的访问权限级别更改为拒绝的做法效果一样。如果应用已遵循有关在运行时请求权限的最佳做法,那么不必对应用进行任何更改。这是因为,当用户与应用中的功能互动时,应该会验证相关功能是否具有所需权限。
如果需要,可以要求用户阻止系统重置应用的权限。如果用户希望应用主要在后台运行,即使用户不与应用互动,应用也能正常工作,那么此做法就非常有用。此类使用场景的示例如下:
- 为家人的安全提供保障
- 同步数据
- 与智能设备通信
- 与配套设备配对
要将用户定向到系统设置中应用的页面,调用包含Settings.ACTION_APPLICATION_DETAILS_SETTINGS Intent 操作的 Intent。在此屏幕中,用户可以通过执行以下操作来阻止系统重置应用的权限:
- 点按权限,系统会加载应用权限设置屏幕。
- 关闭如果未使用此应用,则移除相关权限选项
电话号码
Android 11 更改了应用在读取电话号码时使用的与电话相关的权限。
如果应用以 Android 11 为目标平台,并且需要访问以下列表中显示的电话号码 API,则必须请求 READ_PHONE_NUMBERS
权限,而不是 READ_PHONE_STATE
权限。
TelephonyManager
类和TelecomManager
类中的getLine1Number()
方法。TelephonyManager
类中不受支持的getMsisdn()
方法。
如果声明 READ_PHONE_STATE
以调用前面列表中的方法以外的方法,可以继续在所有 Android 版本中请求 READ_PHONE_STATE
。不过,如果仅对前面列表中的方法使用 READ_PHONE_STATE
权限,请按以下方式更新的清单文件:
- 更改
READ_PHONE_STATE
的声明,以使应用仅在 Android 10(API 级别 29)及更低版本中使用该权限。 - 添加
READ_PHONE_NUMBERS
权限。
以下清单声明代码段演示了此过程:
<manifest>
<!-- 仅在运行的设备上授予READ_PHONE_STATE权限
Android 10(API级别29)及更低版本。-->
<uses-permission android:name="READ_PHONE_STATE"
android:maxSdkVersion="29" />
<uses-permission android:name="READ_PHONE_NUMBERS" />
</manifest>
软件包可见性
Android 11 更改了应用查询用户已在设备上安装的其他应用以及与之交互的方式。使用新的 <queries>
元素,应用可以定义一组自身可访问的其他应用。通过告知系统应向您的应用显示哪些其他应用,此元素有助于鼓励最小权限原则。此外,此元素还可帮助 Google Play 等应用商店评估应用为用户提供的隐私权和安全性。
如果应用以 Android 11 为目标平台,可能需要在应用的清单文件中添加 <queries>
元素。在 <queries>
元素中,可以按软件包名称或按 intent 签名指定应用。返回其他应用相关结果的 PackageManager
方法(如 queryIntentActivities()
)会根据发起调用的应用的 <queries>
声明进行过滤。与其他应用的显式交互(如 startService()
)还要求目标应用与 <queries>
中的某项声明相符。
- 查询特定软件包及与之交互
<manifest package="com.example.game">
<queries>
<package android:name="com.example.store" />
<package android:name="com.example.services" />
</queries>
...
</manifest>
- 在给定 intent 过滤器的情况下查询应用及与之交互
应用可能需要查询一组具有特定用途的应用或与之交互,但可能不知道要添加的具体软件包名称。在这种情况下,您可以在 <queries>
元素中列出 intent 过滤器签名。然后,应用就可以发现具有匹配的 <intent-filter>
元素的应用。
<manifest package="com.example.game">
<queries>
<intent>
<action android:name="android.intent.action.SEND" />
<data android:mimeType="image/jpeg" />
</intent>
</queries>
...
</manifest>
前台服务类型
从 Android 9 开始,应用仅限于在前台访问摄像头和麦克风。为了进一步保护用户,Android 11 更改了前台服务访问摄像头和麦克风相关数据的方式。如果应用以 Android 11 为目标平台并且在某项前台服务中访问这些类型的数据,需要在该前台服务的声明的 foregroundServiceType 属性中添加新的 camera 和 microphone 类型。
<manifest>
...
<service ...
android:foregroundServiceType="location|camera|microphone" />
</manifest>
功能和API
消息框
Android 11 为了保护用户而弃用了自定义消息框视图。为了给开发者更多的时间适应这些变更,只有在应用以 Android 11 为目标平台时,这些变更才会生效。
出于安全方面的考虑,同时也为了保持良好的用户体验,如果包含自定义视图的消息框是以 Android 11 为目标平台的应用从后台发送的,系统会屏蔽这些消息框。请注意,仍允许使用文本消息框;此类消息框是使用 Toast.makeText()
创建的,并不调用 setView()
。
如果应用仍尝试从后台发布包含自定义视图的消息框,系统不会向用户显示相应的消息,而是会在 logcat 中记录以下消息:
W/NotificationService: Blocking custom toast from package \
<package> due to package not in the foreground
无线调试
Android 11 支持通过 Android 调试桥 (adb) 从工作站以无线方式部署和调试应用。例如,可以将可调试的应用部署到多台远程设备,而无需通过 USB 实际连接设备,从而避免常见的 USB 连接问题(例如驱动程序安装方面的问题)。
如需使用无线调试,需要使用配对码将设备与工作站配对。工作站和设备必须连接到同一无线网络。如需连接到设备,请按以下步骤操作:
- 在工作站上,更新到最新版本的 SDK 平台工具。
- 在设备上启用开发者选项。
- 启用无线调试选项。
- 在询问要在此网络上允许无线调试吗?的对话框中,点击允许。
- 选择使用配对码配对设备。记下设备上显示的配对码、IP 地址和端口号。
- 在工作站上,打开一个终端并导航到
android_sdk/platform-tools
。 - 运行
adb pair ipaddr:port
。使用第 5 步中的 IP 地址和端口号。 - 当系统提示时,输入在第 5 步中获得的配对码。系统会显示一条消息,表明设备已成功配对。
- (仅适用于 Linux 或 Microsoft Windows)运行
adb connect ipaddr:port
。使用无线调试下的 IP 地址和端口。