行为变更:面向 API 29 及更高版本的应用

Android 10 包含更新的系统行为变更,这些变更可能会影响您的应用。此页面上列出的变更仅适用于面向 API 29 或更高版本的应用。如果您的应用将 targetSdkVersion 设置为“29”或更高版本,则应在适用情况下修改您的应用以正确支持这些行为。

请务必还查看 影响在 Android 10 上运行的所有应用的行为变更 列表。

注意: 除了此页面上列出的变更之外,Android 10 还引入了大量基于隐私的变更和限制,包括以下内容

  • 范围存储
  • 访问 USB 设备序列号
  • 启用、禁用和配置 Wi-Fi 的能力
  • 连接性 API 的位置权限

这些变更(影响面向 API 级别 29 或更高版本的应用)增强了用户隐私。要详细了解如何支持这些变更,请参阅 隐私变更 页面。

对非 SDK 接口限制的更新

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

如果您不会面向 Android 10(API 级别 29),则其中一些变更可能不会立即影响您。但是,虽然您目前可以使用一些非 SDK 接口(具体取决于应用的目标 API 级别),但使用任何非 SDK 方法或字段始终存在导致应用崩溃的高风险。

如果您不确定您的应用是否使用了非 SDK 接口,您可以 测试您的应用 以了解情况。如果您的应用依赖于非 SDK 接口,则应开始计划迁移到 SDK 替代方案。但是,我们了解某些应用有使用非 SDK 接口的有效用例。如果您无法找到应用中功能的非 SDK 接口的替代方案,则应 请求新的公共 API

要详细了解,请参阅 Android 10 中对非 SDK 接口限制的更新 并参阅 对非 SDK 接口的限制

共享内存

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

面向 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>条目)使用与平台先前版本中使用的不同的类加载器层次结构来实现。

全屏意图的权限更改

以 Android 10 或更高版本为目标并使用带有全屏意图的通知的应用程序必须在其应用程序的清单文件中请求USE_FULL_SCREEN_INTENT权限。这是一个普通权限,因此系统会自动将其授予请求该权限的应用程序。

如果以 Android 10 或更高版本为目标的应用程序尝试创建具有全屏意图的通知,但未请求必要的权限,则系统会忽略全屏意图并输出以下日志消息。

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

折叠屏的支持

Android 10 进行了支持折叠屏和大型屏幕设备的更改。

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

不要将“焦点”与“最顶层恢复”活动混淆。系统根据 z 顺序为活动分配优先级,以便优先考虑用户最后交互的活动。活动可以是最顶层恢复的,但没有焦点(例如,如果通知栏已展开)。

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

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

应用程序可以使用 Android 10 中引入的android:minAspectRatio属性来指示其支持的屏幕比例

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

有关更多信息,请参阅为折叠屏设计您的应用程序