| 类别 | 类型 | 名称 |
|---|---|---|
| 核心功能 | 变更(所有应用) | ART 内部变更 Android 16 包含 Android 运行时 (ART) 的最新更新,可提升 Android 运行时 (ART) 的性能并支持更多 Java 功能。通过 Google Play 系统更新,这些改进还可供 10 亿多部搭载 Android 12(API 级别 31)及更高版本的设备使用。随着这些变更的发布,依赖于 ART 内部结构的库和应用代码可能无法在搭载 Android 16 的设备上正常运行,也可能无法在通过 Google Play 系统更新来更新 ART 模块的早期 Android 版本上正常运行。 |
| 核心功能 | 变更(所有应用) | JobScheduler 配额优化 Android 16 会根据以下几个因素调整常规作业和加急作业的执行运行时配额:应用所处的应用待机模式存储分区、作业是否在应用处于前台状态时开始执行,以及作业是否在运行前台服务时执行。 |
| 核心功能 | 变更(所有应用) | 已放弃的空作业停止原因 为了检测和减少已放弃的作业,应用应使用系统为已放弃的作业分配的新 STOP_REASON_TIMEOUT_ABANDONED 作业停止原因,而不是 STOP_REASON_TIMEOUT。 |
| 核心功能 | 变更(所有应用) | 有序广播优先级范围不再是全局的 在 Android 16 中,使用 android:priority 属性或 IntentFilter#setPriority() 在不同进程之间进行的广播传递顺序将无法得到保证。对于有序广播,广播优先级仅在同一应用进程内有效,而不会在所有系统进程中有效。 |
| 核心功能 | 变更(所有应用) | 16 KB 页面大小兼容模式 Android 15 引入了对 16 KB 内存页面的支持,以优化平台性能。Android 16 添加了兼容模式,允许部分为 4 KB 内存页面构建的应用在配置为 16 KB 内存页面的设备上运行。 |
| 核心功能 | 变更(以 Android 16 及更高版本为目标平台的应用) | 优化了固定速率工作调度 对于以 Android 16 或更高版本为目标平台的应用,当应用返回到有效的生命周期时,最多会立即执行一次错过的 scheduleAtFixedRate 执行。 |
| 核心功能 | 新功能和 API | 2025 年发布两个 Android API 版本 在 Android 16 中,预览版适用于计划于 2025 年第 2 季度发布的新 Android 主要版本。此版本与我们过去的所有 API 版本类似,其中可能包含与 targetSdkVersion 相关的计划行为变更。我们计划在 2025 年第 4 季度发布另一个版本,其中也将包含新的开发者 API。2025 年的 Q2 主要版本将是唯一包含可能会影响应用的计划行为变更的版本。 |
| 用户体验和系统界面 | 变更(所有应用) | 弃用干扰性无障碍功能公告 Android 16 弃用了无障碍功能公告,其特征是使用 announceForAccessibility 或调度 TYPE_ANNOUNCEMENT 无障碍功能事件。 |
| 用户体验和系统界面 | 变更(所有应用) | 支持三按钮导航 Android 16 为已正确迁移到预测性返回的应用的三按钮导航带来了预测性返回支持。 |
| 用户体验和系统界面 | 变更(所有应用) | 自动应用主题化图标 Android 16 会自动将主题应用于应用图标,以打造一致的主屏幕体验。 |
| 用户体验和系统界面 | 变更(以 Android 16 及更高版本为目标平台的应用) | 优雅字体 API 已弃用并停用 Android 16 弃用了 elegantTextHeight 属性,并且当您的应用以 Android 16 为目标平台后,系统会忽略该属性。 |
| 用户体验和系统界面 | 变更(以 Android 16 及更高版本为目标平台的应用) | 边缘到边缘选择退出即将弃用 对于以 Android 16 或更高版本为目标平台的应用,R.attr#windowOptOutEdgeToEdgeEnforcement 属性已被移除,因此使用该属性的应用需要处理窗口边衬区。 |
| 用户体验和系统界面 | 变更(以 Android 16 及更高版本为目标平台的应用) | 需要迁移或选择停用预测性返回功能 对于以 Android 16 为目标平台的应用,系统动画(例如"返回主屏幕"、跨任务和跨 activity 动画)现在默认会显示在应用中。为了在系统中反映这一点,android:enableOnBackInvokedCallback 的默认值现在为 true,并且对 OnBackPressed 和 KeyEvent.KEYCODE_BACK 的调用会被忽略。 |
| 用户体验和系统界面 | 新功能和 API | 预测性返回更新 Android 16 新增了多个 API,可帮助您在手势导航中启用预测性返回系统动画,例如"返回主屏幕"动画。Android 16 还添加了 finishAndRemoveTaskCallback() 和 moveTaskToBackCallback。 |
| 用户体验和系统界面 | 新功能和 API | 更丰富的触感反馈 Android 16 添加了触感反馈 API,可让应用定义触感反馈效果的振幅和频率曲线,同时抽象化设备功能之间的差异。 |
| 用户体验和系统界面 | 新功能和 API | 以进度为中心的通知 Android 16 引入了以进度为中心的通知,可帮助用户顺畅地跟踪用户发起的从开始到结束的完整流程。这些通知在系统界面上具有更高的可见性,并且在通知抽屉式导航栏中排名靠前。 |
| 用户体验和系统界面 | 新功能和 API | 动态壁纸的内容处理 在 Android 16 中,动态壁纸框架新增了一个内容 API,以应对动态的、由用户驱动的壁纸所带来的挑战。 |
| 安全 | 变更(所有应用) | 针对 Intent 重定向攻击的安全性得到提升 Android 16 引入了默认安全强化解决方案,以防范 Intent 重定向漏洞。 |
| 安全 | 变更(所有应用) | 配套应用不再收到发现超时通知 当找不到设备时,CDM 将不再通知应用。 |
| 安全 | 变更(以 Android 16 及更高版本为目标平台的应用) | MediaStore 版本锁定 对于以 Android 16 或更高版本为目标平台的应用,MediaStore#getVersion() 现在将对每个应用都是唯一的。 |
| 安全 | 变更(以 Android 16 及更高版本为目标平台的应用) | 更安全的 intent 对于以 Android 16 或更高版本为目标平台的应用,平台会针对 Android 的 intent 解析机制提供安全改进。 |
| 安全 | 变更(以 Android 16 及更高版本为目标平台的应用) | GPU 系统调用过滤 对于以 Android 16 或更高版本为目标平台的应用,系统会创建高级别 SEPolicy,以实现对 GPU 的精细 IOCTL 控制。 |
| 安全 | 新功能和 API | 密钥共享 API Android 16 添加了支持与其他应用共享对 Android Keystore 密钥的访问权限的 API。 |
| 设备规格 | 变更(所有应用) | 虚拟设备所有者替换 虚拟设备所有者(仅限部分受信任的特权应用)现在可以替换虚拟设备所有者所管理的设备上的应用设置。 |
| 设备规格 | 变更(以 Android 16 及更高版本为目标平台的应用) | 自适应布局 对于以 Android 16 或更高版本为目标平台的应用,平台会忽略限制屏幕方向、宽高比和尺寸可调整性的清单属性和运行时 API。 |
| 设备规格 | 新功能和 API | 适用于电视的标准化画质和音质框架 Android 16 引入了 MediaQuality 软件包,该软件包公开了一组标准化 API,用于访问音频和画质配置文件以及硬件相关设置。这样,流媒体应用就可以查询配置文件并将其动态应用于媒体。 |
| 连接 | 变更(所有应用) | 改进了连接丢失处理 Android 16 改进了对连接丢失事件的处理。 |
| 连接 | 变更(以 Android 16 及更高版本为目标平台的应用) | 用于处理连接丢失和加密变更的新 intent 对于以 Android 16 或更高版本为目标平台的应用,平台提供了两个用于处理连接丢失和加密变更的新 intent。 |
| 连接 | 变更(以 Android 16 及更高版本为目标平台的应用) | 移除蓝牙绑定的新方式 以 Android 16 或更高版本为目标平台的应用现在可以使用 removeBond API 来移除蓝牙绑定。 |
| 连接 | 新功能和 API | 测距功能,安全性更高 Android 16 在支持 Wi-Fi 6 802.11az 的设备上为 Wi-Fi 位置信息添加了对强大的安全功能的支持,使应用能够将该协议的更高准确度、更出色的可伸缩性和动态调度与安全增强功能(包括基于 AES-256 的加密和针对 MITM 攻击的保护)相结合。 |
| 连接 | 新功能和 API | 配套设备管理器设备存在情况 在 Android 16 中,我们引入了用于绑定配套应用服务的新 API。当 BLE 在范围内且蓝牙已连接时,服务将被绑定;当 BLE 超出范围或蓝牙已断开连接时,服务将被解除绑定。 |
| 连接 | 新功能和 API | 通用测距 API Android 16 包含新的 RangingManager,该 API 提供了一些方法来确定本地设备与远程设备之间在受支持硬件上的距离和角度。 |
| 健康与健身 | 变更(以 Android 16 及更高版本为目标平台的应用) | 健康与健身权限 对于以 Android 16 或更高版本为目标平台的应用,健康与健身权限即将过渡到 android.permissions.health 下一组更精细的权限,这些权限会被"健康数据共享"使用。 |
| 隐私权 | 变更(以 Android 16 及更高版本为目标平台的应用) | 本地网络权限 对于以 Android 16 或更高版本为目标平台的应用,平台将要求应用声明访问本地网络的权限。 |
| 隐私权 | 变更(以 Android 16 及更高版本为目标平台的应用) | 应用拥有的照片 以 Android 16 及更高版本为目标平台的应用现在会在照片选择器中预先选择应用拥有的照片和视频,允许用户取消选择项目以撤消应用未来的访问权限。 |
| 隐私权 | 新功能和 API | 健康数据共享更新 健康数据共享新增了 ACTIVITY_INTENSITY,这是一种根据世界卫生组织关于中等强度和高强度活动的指南定义的新数据类型。健康数据共享还包含支持健康记录的更新版 API。这样一来,应用便可在征得用户明确同意后,以 FHIR 格式读取和写入医疗记录。此 API 处于抢先体验计划中。如果您想参与,请注册加入我们的抢先体验计划。 |
| 隐私权 | 新功能和 API | Android 上的 Privacy Sandbox Android 16 纳入了最新版本的 Privacy Sandbox on Android,这是我们持续开发相关技术的一部分,旨在让用户知道自己的隐私受到保护。 |
| 性能和电池 | 新功能和 API | ApplicationStartInfo 中的启动组件 Android 16 添加了 getStartComponent(),用于区分触发启动的组件类型,这有助于优化应用的启动流程。 |
| 性能和电池 | 新功能和 API | 自适应刷新率 Android 16 引入了 hasArrSupport() 和 getSuggestedFrameRate(int),同时恢复了 getSupportedRefreshRates(),以便您的应用更轻松地利用 ARR。 |
| 性能和电池 | 新功能和 API | 更好的作业自省 在 Android 16 中,我们引入了 JobScheduler#getPendingJobReasons(),该方法会返回作业处于待处理状态的多个原因,包括开发者设置的显式限制和系统设置的隐式限制。我们还推出了 JobScheduler#getPendingJobReasonsHistory(),用于返回最近的待处理作业原因更改列表。 |
| 性能和电池 | 新功能和 API | 系统触发的性能分析 Android 16 引入了系统触发的性能分析,以改进 ProfilingManager。应用可以注册对接收某些触发器(例如冷启动 reportFullyDrawn 或 ANR)的跟踪信息感兴趣,然后系统会代表应用启动和停止跟踪。轨迹记录完成后,结果会传递到应用的数据目录。 |
| 性能和电池 | 新功能和 API | ADPF 中的裕度 API 在 Android 16 中,SystemHealthManager 引入了 getCpuHeadroom 和 getGpuHeadroom API,旨在为游戏和资源密集型应用提供可用 CPU 和 GPU 资源的估计值。 |
| 媒体 | 新功能和 API | 照片选择器改进 Android 16 改进了照片选择器,例如新增了 API,可让应用将照片选择器嵌入到其视图层次结构中;还新增了 API,可让 Android 照片选择器从云媒体提供程序中进行搜索。 |
| 媒体 | 新功能和 API | 高级专业视频 Android 16 引入了对高级专业视频 (APV) 编解码器的支持,该编解码器旨在用于专业级高质量视频录制和后期制作。 |
| 相机 | 新功能和 API | 精确的色温和色调调整 Android 16 新增了对精细色温和色调调整的相机支持,以更好地支持专业视频录制应用。 |
| 相机 | 新功能和 API | 混合自动曝光 Android 16 为 Camera2 添加了新的混合自动曝光模式,让您能够手动控制曝光的特定方面,同时让自动曝光 (AE) 算法处理其余方面。 |
| 相机 | 新功能和 API | 动态照片拍摄 intent 操作 Android 16 添加了标准 intent 操作(ACTION_MOTION_PHOTO_CAPTURE 和 ACTION_MOTION_PHOTO_CAPTURE_SECURE),这些操作会请求相机应用拍摄动态照片并返回。 |
| 相机 | 新功能和 API | 相机夜间模式场景检测 为了帮助您的应用了解何时切换到夜间模式相机会议以及何时从夜间模式相机会议切换回来,Android 16 添加了 EXTENSION_NIGHT_MODE_INDICATOR。如果受支持,您可以在 Camera2 中使用 CaptureResult。 |
| 相机 | 新功能和 API | UltraHDR 图片增强功能 Android 16 添加了对 HEIC 文件格式的 UltraHDR 图片的支持。 |
| 国际化 | 新功能和 API | 竖排文本 Android 16 添加了对竖排渲染和测量文本的低级别支持,为库开发者提供基本的竖排书写支持。 |
| 国际化 | 新功能和 API | 自定义计量系统 Android 16 新增了在"设置"中的"地区偏好设置"中自定义计量系统的功能。 |
| 无障碍 | 新功能和 API | 改进的无障碍功能 API Android 16 添加了更多 API 来增强界面语义,从而帮助依赖无障碍服务的用户(例如 TalkBack)获得更一致的体验。 |
| 无障碍 | 新功能和 API | 将手机作为 LEA 助听器的语音通话麦克风输入源 Android 16 新增了一项功能,可让 LE 音频助听器的用户在助听器的内置麦克风和手机麦克风之间切换,以进行语音通话。 |
| 无障碍 | 新功能和 API | LEA 助听器的环境音量控制 Android 16 新增了一项功能,可让 LE 音频助听器的用户调整助听器麦克风拾取的环境音量。 |
| 图形 | 新功能和 API | 使用 AGSL 实现自定义图形效果 Android 16 新增了 RuntimeColorFilter 和 RuntimeXfermode,让您可以创作阈值、棕褐色调和色调饱和度等复杂效果,并将其应用于绘制调用。 |
核心功能
Android 16(API 级别 36)包含以下变更,这些变更会修改或扩展 Android 系统的各种核心功能。
JobScheduler 配额优化
从 Android 16 开始,我们将根据以下因素调整常规作业和加急作业的执行运行时配额:
- 应用所处的应用待机存储分区:在 Android 16 中,活跃待机存储分区将开始通过宽松的运行时配额强制执行。
- 如果作业在应用处于前台状态时开始执行:在 Android 16 中,如果作业在应用对用户可见时开始执行,并在应用变为不可见后继续执行,则会遵守作业运行时配额。
- 如果作业在运行前台服务时执行 :在 Android 16 中,与前台服务同时执行的作业将遵守作业运行时配额。如果您利用作业进行用户发起的数据传输,请考虑改用用户发起的数据传输作业。
此变更会影响使用 WorkManager、JobScheduler 和 DownloadManager 调度的任务。如需调试作业停止的原因,我们建议您通过调用 WorkInfo.getStopReason()(对于 JobScheduler 作业,请调用 JobParameters.getStopReason())来记录作业停止的原因。
如需了解应用的状态如何影响其可使用的资源,请参阅电源管理资源限制。 如需详细了解电池优化方面的最佳实践,请参阅有关针对任务调度 API 优化电池使用的指南。
我们还建议利用 Android 16 中引入的新 JobScheduler#getPendingJobReasonsHistory API 来了解作业未执行的原因。
测试
如需测试应用的行为,只要应用在 Android 16 设备上运行,您就可以启用对某些作业配额优化功能的替换。
如需停用"顶级状态将遵守作业运行时配额"的强制执行,请运行以下 adb 命令:
bash
adb shell am compat enable OVERRIDE_QUOTA_ENFORCEMENT_TO_TOP_STARTED_JOBS APP_PACKAGE_NAME
如需停用"在与前台服务同时执行时,作业将遵守作业运行时配额"的强制执行,请运行以下 adb 命令:
bash
adb shell am compat enable OVERRIDE_QUOTA_ENFORCEMENT_TO_FGS_JOBS APP_PACKAGE_NAME
如需测试特定应用待机分桶行为,您可以使用以下 adb 命令设置应用的应用待机分桶:
bash
adb shell am set-standby-bucket APP_PACKAGE_NAME active|working_set|frequent|rare|restricted
如需了解应用所在的待机分桶,您可以使用以下 adb命令获取应用的待机分桶:
bash
adb shell am get-standby-bucket APP_PACKAGE_NAME
已放弃的空作业停止原因
如果与作业关联的 JobParameters 对象已被垃圾回收,但尚未调用 JobService#jobFinished(JobParameters, boolean) 来指示作业已完成,则会发生作业被废弃的情况。这表示作业可能会在应用不知情的情况下运行和重新调度。
依赖于 JobScheduler 的应用不会维护对 JobParameters 对象的强引用,并且超时现在将获得新的作业停止原因 STOP_REASON_TIMEOUT_ABANDONED,而不是 STOP_REASON_TIMEOUT。
如果新的作业被废弃停止原因频繁出现,系统会采取缓解措施来降低作业频率。
应用应使用新的停止原因来检测和减少被废弃的作业。
如果您使用的是 WorkManager、AsyncTask 或 DownloadManager,则不会受到影响,因为这些 API 会代表您的应用管理作业生命周期。
完全弃用 JobInfo#setImportantWhileForeground
JobInfo.Builder#setImportantWhileForeground(boolean) 方法用于在调度应用位于前台或暂时豁免于后台限制时指示作业的优先级。
自 Android 12(API 级别 31)起,此方法已废弃。从 Android 16 开始,它不再有效,系统会忽略调用此方法。
此功能移除也适用于 JobInfo#isImportantWhileForeground()。从 Android 16 开始,如果调用该方法,该方法会返回 false。
有序广播优先级范围不再是全局
Android 应用可以为广播接收器定义优先级,以控制接收器接收和处理广播的顺序。对于清单声明的接收器,应用可以使用 android:priority 属性来定义优先级;对于上下文注册的接收器,应用可以使用 IntentFilter#setPriority() API 来定义优先级。发送广播时,系统会按接收器的优先级(从高到低)将其传送给接收器。
在 Android 16 中,无法保证使用 android:priority 属性或 IntentFilter#setPriority() 在不同进程中传送广播的顺序。广播优先级仅在同一应用进程内有效,而不会跨所有进程有效。
此外,广播优先级将自动限制在 (SYSTEM_LOW_PRIORITY + 1, SYSTEM_HIGH_PRIORITY - 1) 的范围内。只有系统组件才能将 SYSTEM_LOW_PRIORITY、SYSTEM_HIGH_PRIORITY 设置为广播优先级。
如果您的应用执行以下任一操作,可能会受到影响:
- 您的应用声明了具有相同广播 intent 的多个进程,并且希望根据优先级以特定顺序接收这些 intent。
- 您的应用进程与其他进程交互,并期望以特定顺序接收广播 intent。
如果进程需要相互协调,则应使用其他协调渠道进行通信。
ART 内部变更
Android 16 包含 Android 运行时 (ART) 的最新更新,这些更新可提升 Android 运行时 (ART) 的性能,并支持更多 Java 功能。通过 Google Play 系统更新,搭载 Android 12(API 级别 31)及更高版本的 10 亿多部设备也将受益于这些改进。
发布这些变更后,依赖于 ART 内部结构的库和应用代码在搭载 Android 16 的设备以及通过 Google Play 系统更新来更新 ART 模块的较低 Android 版本上可能无法正常运行。
依赖于内部结构(例如非 SDK 接口)始终会导致兼容性问题,但避免依赖于利用内部 ART 结构的代码(或包含代码的库)尤为重要,因为 ART 更改与设备所运行的平台版本无关,并且会通过 Google Play 系统更新推送到超过 10 亿部设备。
所有开发者都应在 Android 16 上对其应用进行全面测试,以检查其应用是否受到影响。此外,请查看已知问题,了解您的应用是否依赖于我们发现的任何依赖于内部 ART 结构的库。如果您的应用代码或库依赖项受到影响,请尽可能寻找公共 API 替代方案,并在问题跟踪器中创建功能请求,为新用例请求公共 API。
16 KB 页面大小兼容模式
Android 15 引入了对 16 KB 内存页面的支持,以优化平台性能。Android 16 添加了兼容模式,让一些针对 4 KB 内存页面构建的应用可以在配置为 16 KB 内存页面的设备上运行。
当您的应用在搭载 Android 16 或更高版本的设备上运行时,如果 Android 检测到您的应用具有 4 KB 对齐的内存页面,则会自动使用兼容模式并向用户显示通知对话框。在 AndroidManifest.xml 中设置 android:pageSizeCompat 属性以启用向后兼容模式,将会阻止应用启动时显示对话框。如需使用 android:pageSizeCompat 属性,请使用 Android 16 SDK 编译您的应用。
为了实现最佳性能、可靠性和稳定性,应用仍应以 16 KB 对齐。如需了解详情,请参阅我们近期发布的博文,了解如何更新应用以支持 16 KB 的内存页面。
用户体验和系统界面
Android 16(API 级别 36)包含以下变更,旨在打造更一致、更直观的用户体验。
弃用干扰性无障碍功能公告
Android 16 废弃了无障碍功能通告,其特征是使用 announceForAccessibility 或调度 TYPE_ANNOUNCEMENT 无障碍功能事件。这可能会给 TalkBack 和 Android 屏幕阅读器用户带来不一致的用户体验,而替代方案可以更好地满足各种 Android 辅助技术的用户需求。
替代方案示例:
- 对于窗口更改等重大界面更改,请使用 Activity.setTitle(CharSequence) 和 setAccessibilityPaneTitle(java.lang.CharSequence)。在 Compose 中,使用 Modifier.semantics { paneTitle = "paneTitle" }
- 如需向用户告知关键界面的更改,请使用 setAccessibilityLiveRegion(int)。在 Compose 中,请使用 Modifier.semantics { liveRegion = LiveRegionMode.[Polite|Assertive]}。应谨慎使用这些事件,因为它们可能会在每次更新视图时生成通知。
- 如需向用户发送错误通知,请发送类型为 AccessibilityEvent#CONTENT_CHANGE_TYPE_ERROR 的
AccessibilityEvent并设置 AccessibilityNodeInfo#setError(CharSequence),或使用 TextView#setError(CharSequence)。
已废弃的 announceForAccessibility API 的参考文档中包含有关建议替代方案的更多详细信息。
支持"三按钮"导航
Android 16 为已正确迁移到预测性返回的应用的三按钮导航栏引入了预测性返回支持。长按返回按钮会启动预测性返回动画,让您预览返回滑动手势会打开的界面。
此行为适用于系统中支持预测性返回动画的所有区域,包括系统动画(返回主屏幕、跨任务和跨 activity)。
自动带主题的应用图标
从 Android 16 QPR 2 开始,Android 会自动将主题应用于应用图标,以打造一致的主屏幕体验。如果应用未提供自己的带主题的应用图标,就会发生这种情况。应用可以通过在自适应图标中添加单色图层来控制主题化应用图标的设计,并在 Android Studio 中预览应用图标的外观。
设备规格
Android 16(API 级别 36)在虚拟设备所有者将应用投影到显示屏时,对应用做出了以下更改。
虚拟设备所有者替换项
虚拟设备所有者是创建和管理虚拟设备的受信任应用或特权应用。虚拟设备所有者在虚拟设备上运行应用,然后将应用投影到远程设备的显示屏上,例如个人电脑、虚拟现实设备或车载信息娱乐系统。虚拟设备所有者位于本地设备上,例如手机。
按应用替换项
在搭载 Android 16(API 级别 36)的设备上,虚拟设备所有者可以替换其管理的特定虚拟设备上的应用设置。例如,为了改进应用布局,虚拟设备所有者在将应用投影到外部显示屏上时,可以忽略屏幕方向、宽高比和可调整大小性限制。
常见的重大更改
Android 16 的行为可能会影响应用在汽车显示屏或 Chromebook 等大屏幕设备上的界面,尤其是那些专为竖屏小显示屏设计的布局。如需了解如何让应用适应所有设备类型,请参阅自适应布局简介。
参考文档
安全
Android 16(API 级别 36)包含多项变更,旨在提升系统安全性,帮助保护应用和用户免受恶意应用的侵害。
安全性更强,可防范 Intent 重定向攻击
Android 16 提供了针对一般 Intent 重定向攻击的默认安全性,并且只需进行最低限度的兼容性更改和开发者更改。
我们正在引入默认安全强化解决方案,以应对Intent重定向漏洞。在大多数情况下,使用 intent 的应用通常不会遇到任何兼容性问题;我们在整个开发过程中收集了指标,以监控哪些应用可能会出现中断。
当攻击者可以部分或完全控制用于在存在漏洞的应用上下文中启动新组件的 intent 内容时,就会出现 Android 中的 intent 重定向问题,而受害应用会在("顶级")intent 的 extras 字段中启动不可信的子级 intent。这可能会导致攻击者应用在受害者应用的上下文中启动私有组件、触发特权操作或获得对敏感数据的 URI 访问权限,从而可能导致数据窃取和任意代码执行。
选择停用 intent 重定向处理
Android 16 引入了一项新 API,允许应用选择停用启动安全保护功能。在默认安全行为会干扰正当应用用例的特定情况下,这可能是必要的。
重要提示: 退出安全保护功能时应谨慎行事,并且仅在绝对必要时才应这样做,因为这可能会增加出现安全漏洞的风险。请在调用此 API 之前仔细评估其对应用安全性的潜在影响。
对于针对 Android 16(API 级别 36)SDK 或更高版本进行编译的应用
您可以直接对 Intent 对象使用 removeLaunchSecurityProtection() 方法。
val i = intent
val iSublevel: Intent? = i.getParcelableExtra("sub_intent")
iSublevel?.removeLaunchSecurityProtection() // Opt out from hardening
iSublevel?.let { startActivity(it) }
对于针对 Android 15(API 级别 35)或更低版本进行编译的应用
虽然不建议这样做,但您可以使用反射来访问 removeLaunchSecurityProtection() 方法。
Kotlin
val i = intent
val iSublevel: Intent? = i.getParcelableExtra("sub_intent", Intent::class.java)
try {
val removeLaunchSecurityProtection = Intent::class.java.getDeclaredMethod("removeLaunchSecurityProtection")
removeLaunchSecurityProtection.invoke(iSublevel)
} catch (e: Exception) {
// Handle the exception, e.g., log it
} // Opt-out from the security hardening using reflection
iSublevel?.let { startActivity(it) }
不再向配套应用通知发现超时
Android 16 在配套设备配对流程期间引入了一种新行为,以防恶意应用侵犯用户的位置信息隐私。在 Android 16 上运行的所有配套应用都不再直接通过 RESULT_DISCOVERY_TIMEOUT 收到发现超时通知。而是通过可视对话框通知用户超时事件。当用户关闭对话框时,系统会通过 RESULT_USER_REJECTED 提醒应用关联失败。
搜索时长也从原来的 20 秒延长到了 30 秒,并且用户可以在搜索期间的任何时间停止设备发现。如果在开始搜索的前 20 秒内发现了至少 1 部设备,CDM 会停止搜索其他设备。
连接
Android 16(API 级别 36)在蓝牙堆栈中进行了以下更改,以改善与外围设备的连接。
用于处理绑定丢失和加密更改的新 intent
作为改进了对键值对丢失的处理的一部分,Android 16 还引入了 2 个新 intent,以便应用更好地了解键值对丢失和加密更改。
以 Android 16 为目标平台的应用现在可以:
- 在检测到远程键盘连接丢失时接收 ACTION_KEY_MISSING intent,以便提供更具信息量的用户反馈并采取适当的措施。
- 每当链接的加密状态发生变化时,都会收到 ACTION_ENCRYPTION_CHANGE intent。这包括加密状态更改、加密算法更改和加密密钥大小更改。如果应用在稍后收到 ACTION_ENCRYPTION_CHANGE intent 时成功加密了链接,则必须将该绑定视为已恢复。
适应不同的 OEM 实现
虽然 Android 16 引入了这些新 intent,但其实现和广播可能会因不同的设备制造商 (OEM) 而异。为了确保您的应用在所有设备上都能提供一致且可靠的体验,开发者应设计其绑定丢失处理机制,以妥善适应这些潜在的变化。
我们建议您采用以下应用行为:
-
如果广播 ACTION_KEY_MISSING intent:
系统会断开 ACL(异步无连接)链接,但会保留设备的配对信息(如此处所述)。
您的应用应将此 intent 用作检测配对丢失的主要信号,并在发起设备忘记或重新配对之前引导用户确认远程设备是否在范围内。
如果设备在收到 ACTION_KEY_MISSING 后断开连接,您的应用应谨慎重新连接,因为设备可能已不再与系统绑定。
-
如果未广播 ACTION_KEY_MISSING intent:
ACL 链接将保持连接状态,系统会移除设备的配对信息,与 Android 15 中的行为相同。
在这种情况下,您的应用应继续使用与之前的 Android 版本相同的现有配对丢失处理机制,以检测和管理配对丢失事件。
移除蓝牙绑定的新方法
现在,以 Android 16 为目标平台的所有应用都可以使用 CompanionDeviceManager 中的公共 API 解除蓝牙设备配对。如果配套设备作为 CDM 关联进行管理,则应用可以在关联的设备上使用新的 removeBond(int) API 触发蓝牙配对的移除。该应用可以通过监听蓝牙设备广播事件 ACTION_BOND_STATE_CHANGED 来监控配对状态变化。
健康与健身
Android 16(API 级别 36)包含与健康和健身数据相关的以下变更。
健康与健身权限
对于以 Android 16(API 级别 36)或更高版本为目标平台的应用,BODY_SENSORS 权限使用 android.permissions.health 下更精细的权限,健康数据共享也使用这些权限。自 Android 16 起,凡是以前需要具有 BODY_SENSORS 或 BODY_SENSORS_BACKGROUND 权限的 API,现在都需要获取相应的 android.permissions.health 权限。这会影响以下数据类型、API 和前台服务类型:
- 从 Wear OS 上的健康服务中获取 HEART_RATE_BPM
- 来自 Android Sensor Manager 的 Sensor.TYPE_HEART_RATE
- 在 Wear OS 上,
ProtoLayout中的 heartRateAccuracy 和 heartRateBpm - FOREGROUND_SERVICE_TYPE_HEALTH,其中需要使用相应的
android.permission.health权限来代替BODY_SENSORS
如果您的应用使用这些 API,则应请求相应的精细权限:
- 对于使用期间的心率、血氧饱和度或体表温度监测:请求
android.permissions.health下的精细权限,例如 READ_HEART_RATE,而不是 BODY_SENSORS。 - 对于后台传感器访问权限:请求 READ_HEALTH_DATA_IN_BACKGROUND 而不是 BODY_SENSORS_BACKGROUND。
这些权限与用于保护对 Health Connect(Android 健康、健身和身心状态数据存储区)中读取数据的访问权限相同。
移动应用
迁移到使用 READ_HEART_RATE 和其他精细权限的移动应用还必须声明 activity 以显示应用的隐私权政策。此要求与健康数据共享的要求相同。
隐私权
Android 16(API 级别 36)包含以下隐私权方面的变更。
本地网络权限
具有 INTERNET 权限的任何应用都可以访问局域网上的设备。 这使得应用可以轻松连接到本地设备,但也存在隐私影响,例如形成用户指纹,以及成为位置信息的代理。
本地网络保护项目旨在通过在新的运行时权限后限制对本地网络的访问,来保护用户的隐私。
发布计划
此变更将分别在 25Q2 和 26Q2 这两个版本之间部署。 开发者必须遵循 25Q2 的相关指南并分享反馈,因为这些保护措施将在后续 Android 版本中强制执行。此外,他们还需要按照以下指南更新依赖于隐式本地网络访问权限的场景,并为用户拒绝和撤消新权限做好准备。
影响
在当前阶段,LNP 是一项选择启用功能,这意味着只有选择启用的应用会受到影响。选择启用阶段的目标是让应用开发者了解应用的哪些部分依赖于隐式本地网络访问权限,以便他们可以为下一个版本做好权限保护准备。
如果应用使用以下方式访问用户的本地网络,则会受到影响:
- 在本地网络地址(例如 mDNS 或 SSDP 服务发现协议)上直接或通过库使用原始套接字
- 使用可访问本地网络的框架级类(例如 NsdManager)
向 本地网络地址发送流量和从本地网络地址接收流量需要本地网络访问权限。下表列出了一些常见情况:
| 应用低级层网络操作 | 需要本地网络权限 |
|---|---|
| 建立出站 TCP 连接 | 是 |
| 接受传入的 TCP 连接 | 是 |
| 发送 UDP 单播、多播、广播 | 是 |
| 接收传入的 UDP 单播、多播、广播 | 是 |
这些限制是在网络堆栈深处实现的,因此适用于所有网络 API。这包括在原生代码或受管理代码中创建的套接字、Cronet 和 OkHttp 等网络库,以及基于这些库实现的任何 API。尝试解析本地网络上的服务(即带有 .local 后缀的服务)将需要本地网络权限。
注意: 源自需要本地网络访问权限的 Android WebView 的流量将继承宿主应用的权限状态
上述规则的例外情况:
- 如果设备的 DNS 服务器位于本地网络上,则进出该服务器(位于端口 53)的流量不需要本地网络访问权限。
- 如果应用使用输出切换器作为其应用内选择器,则无需本地网络权限(更多指南将在 2025 年第 4 季度发布)。
注意: 许多媒体投屏场景都依赖于对本地网络的访问权限,因此会受到此变更的影响。不过,并非所有提供投屏功能的应用都需要请求新权限。我们将在 25Q4 中提供未来 API 和处理投屏场景的指南。
开发者指南(选择启用)
如需选择启用本地网络限制,请执行以下操作:
-
将设备刷写到 25Q2 Beta 3 或更高版本的 build。
-
安装要测试的应用。
-
在 adb 中切换 Appcompat 标志:
adb shell am compat enable RESTRICT_LOCAL_NETWORK <package_name> -
重启设备
现在,您的应用对本地网络的访问受到限制,任何访问本地网络的尝试都会导致套接字错误。如果您使用的 API 在应用进程之外执行本地网络操作(例如:NsdManager),在选择启用阶段,这些 API 不会受到影响。
如需恢复访问权限,您必须向应用授予 NEARBY_WIFI_DEVICES 权限。
- 确保应用在其清单中声明了
NEARBY_WIFI_DEVICES权限。 - 依次前往设置 > 应用 > [应用名称] > 权限 > 附近的设备 > 允许。
注意 : 在未来的 Android 版本中,此功能将受"附近的设备"权限组中的新权限保护
现在,应用对本地网络的访问权限应该已恢复,并且所有场景都应像选择启用应用之前一样正常运行。
本地网络保护功能开始强制执行后,应用的网络流量将受到以下影响。
| 权限 | 出站 LAN 请求 | 出站/入站互联网请求 | 入站 LAN 请求 |
|---|---|---|---|
| 已授予 | Works | Works | Works |
| 未授予 | 最差排行榜 | Works | 最差排行榜 |
使用以下命令切换关闭应用兼容性标志
adb shell am compat disable RESTRICT_LOCAL_NETWORK <package_name>
错误
每当调用套接字调用 send 或 send 变体向本地网络地址发送数据时,系统都会向该套接字返回因这些限制而产生的错误。
错误示例:
sendto failed: EPERM (Operation not permitted)
sendto failed: ECONNABORTED (Operation not permitted)
本地网络定义
此项目中的本地网络是指使用支持广播的网络接口(例如 Wi-Fi 或以太网)的 IP 网络,但不包括移动网络 (WWAN) 或 VPN 连接。
以下网络被视为本地网络:
IPv4:
- 169.254.0.0/16 // 链路本地
- 100.64.0.0/10 // CGNAT
- 10.0.0.0/8 // RFC1918
- 172.16.0.0/12 // RFC1918
- 192.168.0.0/16 // RFC1918
IPv6:
- 链路本地
- 直接连接的路线
- Thread 等桩网络
- 多个子网(待定)
此外,多播地址 (224.0.0.0/4、ff00::/8) 和 IPv4 广播地址 (255.255.255.255) 都归类为本地网络地址。
应用拥有的照片
当面向 SDK 36 或更高版本的应用在搭载 Android 16 或更高版本的设备上提示用户授予照片和视频权限时,如果用户选择限制对所选媒体的访问权限,则会在照片选择器中看到该应用拥有的所有照片。用户可以取消选择任何这些预选项,这会撤消该应用对这些照片和视频的访问权限。
Android 16 中有关限制非 SDK 接口的更新
Android 16 包含更新后的受限非 SDK 接口列表(基于与 Android 开发者之间的协作以及最新的内部测试)。 在限制使用非 SDK 接口之前,我们会尽可能确保提供可用的公开替代方案。
如果您的应用并非以 Android 16(API 级别 36)为目标平台,那么部分变更可能不会立即对您产生影响。不过,虽然您的应用可以访问某些非 SDK 接口(具体取决于应用的目标 API 级别),但只要您使用任何非 SDK 方法或字段,就始终会有很高风险导致应用功能异常。
如果您不确定自己的应用是否使用了非 SDK 接口,则可以通过测试该应用来进行确认。如果您的应用依赖非 SDK 接口,则应开始计划迁移到 SDK 替代方案。不过,我们知道某些应用存在使用非 SDK 接口的合理场景。如果您无法为应用中的某项功能找到使用非 SDK 接口的替代方案,则应该请求新的公共 API。