行为变更:以 API 29 及更高级别为目标平台的应用

Android 10 包含更新后的系统行为变更,这些变更可能会影响您的应用。本页列出的变更仅适用于以 API 29 或更高版本为目标平台的应用。如果您的应用将 targetSdkVersion 设为“29”或更高级别,您应该修改自己的应用以适当地支持这些行为(如果适用)。

此外,请务必查看对 Android 10 上运行的所有应用都有影响的行为变更列表。

注意 :除了本页面所列的变更以外,Android 10 还引入了大量基于隐私权的变更和限制,其中包括:

  • 分区存储
  • 获取 USB 设备序列号
  • 能够启用、停用和配置 Wi-Fi
  • 连接 API 的位置信息权限

这些变更会影响以 API 级别 29 或更高级别为目标平台的应用,从而加强用户隐私保护。如需详细了解如何支持这些变更,请参阅隐私权变更页面。

有关限制非 SDK 接口的更新

为了帮助确保应用稳定性和兼容性,Android 平台开始限制您的应用可在 Android 9(API 级别 28)中使用哪些非 SDK 接口。Android 10 包含更新后的受限制非 SDK 接口列表(基于与 Android 开发者之间的协作以及最新的内部测试)。我们的目标是在限制使用非 SDK 接口之前,确保有可用的公开替代方案。

如果您不以 Android 10(API 级别 29)为目标平台,那么其中一些变更可能不会立即对您产生影响。然而,虽然您目前仍可以使用一些非 SDK 接口(具体取决于应用的目标 API 级别),但只要您使用任何非 SDK 方法或字段,终归存在导致应用出问题的显著风险。

如果您不确定自己的应用是否使用了非 SDK 接口,则可以测试该应用进行确认。如果您的应用依赖于非 SDK 接口,您应开始计划迁移到 SDK 替代方案。然而,我们知道某些应用具有使用非 SDK 接口的有效用例。如果您无法为应用中的功能找到使用非 SDK 接口的替代方案,则应该请求新的公共 API

如需了解详情,请参阅 Android 10 中有关限制非 SDK 接口的更新以及对非 SDK 接口的限制

共享内存

Ashmem 更改了 /proc/<pid>/maps 中 dalvik 映射的格式,这影响了直接解析映射文件的应用。如果应用依赖于 dalvik 映射格式,则应用开发者应在搭载 Android 10 或更高版本的设备上测试 /proc/<pid>/maps 格式并相应地进行解析。

以 Android 10 为目标平台的应用无法直接使用 ashmem (/dev/ashmem),而必须通过 NDK 的 ASharedMemory访问共享内存。此外,应用无法直接对现有的 ashmem 文件描述符进行 IOCTL,而必须改用 NDK 的 ASharedMemory 类或 Android Java API 来创建共享内存区域。此项变更可提高使用共享内存时的安全性和稳健性,从而提高 Android 的整体性能和安全性。

移除了应用主目录的执行权限

从可写的应用主目录执行文件违反了 W^X。应用应仅加载嵌入到应用 APK 文件中的二进制代码。

以 Android 10 为目标平台的不可信应用无法直接对应用主目录中的文件调用 execve()

此外,以 Android 10 为目标平台的应用无法针对通过 dlopen() 打开的文件中的可执行代码进行内存中修改,并期望这些更改写入磁盘,因为无法通过可写文件描述符映射 PROT_EXEC。其中包括含有文本重定位的所有共享对象 (.so) 文件。

Android 运行时只接受系统生成的 OAT 文件

Android 运行时 (ART) 不再从应用进程调用 dex2oat。这项变更意味着 ART 将仅接受系统生成的 OAT 文件。

在 ART 中强制要求 AOT 正确性

过去,如果编译时和运行时的类路径环境不同,Android 运行时 (ART) 执行的预先 (AOT) 编译可能会导致运行时崩溃。Android 10 及更高版本始终要求这些环境上下文相同,因此导致行为发生了以下变化:

  • 自定义类加载器(即应用编写的类加载器,与 dalvik.system 软件包中的类加载器不同)不是 AOT 编译的。这是因为 ART 无法在运行时了解自定义类查找实现。
  • 辅助 dex 文件(即由主 APK 之外的应用手动加载的 dex 文件)是在后台 AOT 编译的。这是因为首次使用编译可能代价过高,导致在执行之前出现意外的延迟。请注意,对于应用,建议采用拆分并弃用辅助 dex 文件。
  • Android 中的共享库(Android 清单中的 <library> 和 <uses-library> 条目)是在实现时使用的类加载器层次结构,而不是先前版本平台中使用的类加载器层次结构。

针对全屏 Intent 的权限变更

如果应用以 Android 10 或更高版本为目标平台并使用通过全屏 intent 的通知,则必须在其应用的清单文件中请求 USE_FULL_SCREEN_INTENT 权限。这是普通权限,因此,系统会自动为请求权限的应用授予此权限。

如果以 Android 10 或更高版本为目标平台的应用尝试在没有请求必要权限的情况下创建包含全屏 intent 的通知,系统会忽略该全屏 intent 并输出以下日志消息:

Package your-package-name: Use of fullScreenIntent requires the USE_FULL_SCREEN_INTENT permission

支持可折叠设备

Android 10 包含支持可折叠设备和大屏设备的变更。

当应用在 Android 10 上运行时,onResume()onPause() 方法的工作方式有所不同。当多个应用在多窗口模式或多显示屏模式下同时出现时,可见堆栈中所有可聚焦的顶层 activity 都处于已恢复状态,但实际上只有一个“在最顶层处于已恢复状态”的 activity 才具有焦点。在 Android 10 之前的版本上运行时,一次只能恢复系统中的一个 activity,所有其他可见 activity 都会暂停。

请不要将“焦点位于”的 Activity 与“在最顶层处于已恢复状态”的 Activity 混淆。系统会根据 Z 轴顺序为 activity 分配优先级,以便为用户最后互动过的 activity 提供更高的优先级。activity 可以在顶部恢复,但不具有焦点(例如,如果通知栏展开)。

在 Android 10(API 级别 29)及更高版本中,您可以订阅 onTopResumedActivityChanged() 回调,以便在 activity 获取或失去在最顶层的恢复位置时收到通知。这相当于 Android 10 之前的“已恢复”状态,如果您的应用使用的专用或单例资源可能需要与其他应用共享,这可以作为有用的提示。

resizeableActivity 清单属性的行为也发生了变化。如果某个应用在 Android 10(API 级别 29)或更高版本中设置 resizeableActivity=false,则当可用屏幕尺寸发生变化或该应用从一个屏幕移到另一个屏幕时,它可能会进入兼容模式。

应用可以使用 Android 10 中引入的 android:minAspectRatio 属性来指明应用支持的屏幕宽高比

从版本 3.5 开始,Android Studio 的模拟器工具将包含 7.3 英寸和 8 英寸的虚拟设备,以用于在更大屏幕上测试代码。

如需了解详情,请参阅针对可折叠设备设计应用