行为变更:以 Android 16 或更高版本为目标平台的应用

与早期版本一样,Android 16 包含一些行为变更,这些变更可能会影响您的应用。以下行为变更仅影响以 Android 16 或更高版本为目标平台的应用。如果您的应用以 Android 16 或更高版本为目标平台,您应该修改自己的应用以支持这些行为(如果适用)。

请务必查看对 Android 16 上运行的所有应用都有影响的行为变更列表(无论应用的 targetSdkVersion 如何)。

用户体验和系统界面

Android 16(API 级别 36)进行了以下更改,旨在打造更一致、更直观的用户体验。

无边框设计停用退出选项

Android 15 enforced edge-to-edge for apps targeting Android 15 (API level 35), but your app could opt-out by setting R.attr#windowOptOutEdgeToEdgeEnforcement to true. For apps targeting Android 16 (API level 36), R.attr#windowOptOutEdgeToEdgeEnforcement is deprecated and disabled, and your app can't opt-out of going edge-to-edge.

  • If your app targets Android 16 (API level 36) and is running on an Android 15 device, R.attr#windowOptOutEdgeToEdgeEnforcement continues to work.
  • If your app targets Android 16 (API level 36) and is running on an Android 16 device, R.attr#windowOptOutEdgeToEdgeEnforcement is disabled.

For testing in Android 16 Beta 3, ensure your app supports edge-to-edge and remove any use of R.attr#windowOptOutEdgeToEdgeEnforcement so that your app also supports edge-to-edge on an Android 15 device. To support edge-to-edge, see the Compose and Views guidance.

必须迁移或停用预测性返回

对于以 Android 16(API 级别 36)或更高版本为目标平台且在 Android 16 或更高版本的设备上运行的应用,预测性返回系统动画(返回主屏幕、跨任务和跨 activity)默认处于启用状态。此外,系统不会调用 onBackPressed,也不会再调度 KeyEvent.KEYCODE_BACK

如果您的应用拦截了返回事件,并且您尚未迁移到预测性返回,请更新应用以使用受支持的返回导航 API;或者,在应用的 AndroidManifest.xml 文件的 <application><activity> 标记中将 android:enableOnBackInvokedCallback 属性设置为 false,以暂时停用此功能。

“返回主页”预测性返回动画。
预测性跨 activity 动画。
预测性跨任务动画。

优雅字体 API 已废弃并停用

以 Android 15(API 级别 35)为目标平台的应用的 elegantTextHeight TextView 属性默认设置为 true,从而将紧凑字体替换为更易于阅读的字体。您可以通过将 elegantTextHeight 属性设置为 false 来替换此设置。

Android 16 弃用了 elegantTextHeight 属性,并且在您的应用以 Android 16 为目标平台后,系统会忽略该属性。这些 API 控制的“界面字体”即将停用,因此您应调整所有布局,以确保以阿拉伯语、老挝语、缅甸语、泰米尔语、古吉拉特语、卡纳达语、马拉雅拉姆语、奥里亚语、泰卢固语或泰语呈现一致且可持续的文字。

对于以 Android 14(API 级别 34)及更低版本为目标平台的应用,或者对于以 Android 15(API 级别 35)为目标平台且通过将 elegantTextHeight 属性设为 false 替换了默认值的应用,elegantTextHeight 行为。
对于以 Android 16 为目标平台的应用,或者对于未通过将 elegantTextHeight 属性设置为 false 来替换默认值的以 Android 15(API 级别 35)为目标平台的应用,elegantTextHeight 行为。

核心功能

Android 16(API 级别 36)包含以下更改,用于修改或扩展 Android 系统的各种核心功能。

固定费率工作调度优化

在以 Android 16 为目标平台之前,如果 scheduleAtFixedRate 因不在有效的进程生命周期内而错过了任务执行,则当应用返回到有效的生命周期时,所有错过的执行会立即执行。

以 Android 16 为目标平台时,当应用返回到有效的生命周期时,系统会立即执行最多 1 次未执行的 scheduleAtFixedRate 执行。此行为变更预计会提升应用性能。在您的应用中测试此行为,检查您的应用是否受到影响。您还可以使用应用兼容性框架并启用 STPE_SKIP_MULTIPLE_MISSED_PERIODIC_TASKS 兼容性标志进行测试。

设备规格

Android 16(API 级别 36)对应用在大屏设备上显示时做出了以下更改。

自适应布局

现在,Android 应用可在各种设备(例如手机、平板电脑、可折叠设备、桌面设备、汽车和电视)上运行,并且在大屏设备上支持多种窗口模式(例如分屏和桌面窗口模式),因此开发者应构建能够适应任何屏幕和窗口大小的 Android 应用,无论设备屏幕方向如何。在当今的多设备时代,限制屏幕方向和尺寸调整等范式过于严格。

忽略屏幕方向、尺寸可调整性和宽高比限制

对于以 Android 16(API 级别 36)为目标平台的应用,Android 16 对系统管理屏幕方向、尺寸调整和宽高比限制的方式进行了更改。在最小宽度大于等于 600dp 的显示屏上,这些限制不再适用。无论宽高比或用户的首选屏幕方向如何,应用都会填满整个显示窗口,并且不会使用信箱模式。

此变更引入了新的标准平台行为。Android 正在朝着一种模式发展,即应用应适应各种屏幕方向、显示大小和宽高比。固定屏幕方向或尺寸可调整性受限等限制会妨碍应用自适应,因此我们建议让应用自适应,以提供尽可能出色的用户体验。

您还可以使用应用兼容性框架并启用 UNIVERSAL_RESIZABLE_BY_DEFAULT 兼容性标志来测试此行为。

常见的破坏性更改

忽略屏幕方向、可调整大小和宽高比限制可能会影响应用在某些设备上的界面,尤其是专为锁定在纵向模式的小布局设计的元素:例如,拉伸的布局、屏幕外动画和组件等问题。对宽高比或屏幕方向做出的任何假设都可能会导致应用出现视觉问题。详细了解如何避免这些问题并改进应用的自适应行为。

允许设备旋转会导致重新创建更多 activity,如果未正确保留用户状态,可能会导致丢失用户状态。如需了解如何正确保存界面状态,请参阅保存界面状态

实现细节

在大屏设备上,以下清单属性和运行时 API 会在全屏和多窗口模式下被忽略:

系统会忽略 screenOrientationsetRequestedOrientation()getRequestedOrientation() 的以下值:

  • portrait
  • reversePortrait
  • sensorPortrait
  • userPortrait
  • landscape
  • reverseLandscape
  • sensorLandscape
  • userLandscape

关于显示屏可调整大小,android:resizeableActivity="false"android:minAspectRatioandroid:maxAspectRatio 没有任何影响。

对于以 Android 16(API 级别 36)为目标平台的应用,系统会默认在大屏设备上忽略应用屏幕方向、可调整大小和宽高比限制,但所有尚未完全准备就绪的应用都可以通过选择停用此功能来暂时替换此行为(这会导致应用进入兼容模式,即之前的行为)。

异常

在以下情况下,Android 16 的屏幕方向、尺寸调整和宽高比限制不适用:

  • 游戏(基于 android:appCategory 标志)
  • 用户在设备的宽高比设置中明确选择启用应用的默认行为
  • 小于 sw600dp 的屏幕

暂时停用

如需停用特定 activity,请声明 PROPERTY_COMPAT_ALLOW_RESTRICTED_RESIZABILITY 清单属性:

<activity ...>
  <property android:name="android.window.PROPERTY_COMPAT_ALLOW_RESTRICTED_RESIZABILITY" android:value="true" />
  ...
</activity>

如果应用的太多部分不支持 Android 16,您可以在应用级别应用相同的属性,以完全停用该功能:

<application ...>
  <property android:name="android.window.PROPERTY_COMPAT_ALLOW_RESTRICTED_RESIZABILITY" android:value="true" />
</application>

健康与健身

Android 16(API 级别 36)包含与健康与健身数据相关的以下变更。

健康与健身权限

对于以 Android 16(API 级别 36)或更高版本为目标平台的应用,BODY_SENSORS 权限即将过渡到 android.permissions.health 下的精细权限,这些权限也会被 Health Connect 使用。凡是以前需要具有 BODY_SENSORSBODY_SENSORS_BACKGROUND 权限的 API,现在都需要获取相应的 android.permissions.health 权限。这会影响以下数据类型、API 和前台服务类型:

如果您的应用使用这些 API,则现在应请求相应的精细权限:

这些权限与用于保护对 Health Connect(用于存储健康、健身和身心健康数据的 Android 数据存储区)读取数据的权限相同。

移动应用

迁移到使用 READ_HEART_RATE 和其他精细权限的移动应用还必须声明 activity 以显示应用的隐私权政策。这与 Health Connect 的要求相同。

连接

Android 16(API 级别 36)在蓝牙堆栈中进行了以下更改,以改善与外围设备的连接。

用于处理键绑定丢失和加密更改的新 intent

作为改进了对键值对丢失的处理的一部分,Android 16 还引入了 2 个新 intent,以便应用更好地了解键值对丢失和加密更改。

以 Android 16 为目标平台的应用现在可以:

  • 在检测到远程键盘连接丢失时接收 ACTION_KEY_MISSING intent,以便提供更具信息量的用户反馈并采取适当的措施。
  • 每当链接的加密状态发生变化时,都会收到 ACTION_ENCRYPTION_CHANGE intent。这包括加密状态更改、加密算法更改和加密密钥大小更改。如果应用在稍后收到 ACTION_ENCRYPTION_CHANGE intent 时成功加密了链接,则必须将该绑定视为已恢复。

如果您的应用目前使用自定义机制来处理键盘键失效,请迁移到新的 intent ACTION_KEY_MISSING 以检测和管理键盘键失效事件。我们建议您的应用在发起设备忘记和重新配对之前,引导用户确认远程设备是否在有效范围内。

此外,如果设备在收到 ACTION_KEY_MISSING intent 后断开连接,您的应用应注意重新连接到设备,因为该设备可能已不再与系统绑定。

安全

Android 16(API 级别 36)包含安全方面的以下变更。

MediaStore 版本锁定

对于以 Android 16 或更高版本为目标平台的应用,MediaStore#getVersion() 现在将是每个应用的唯一标识。这会从版本字符串中移除标识属性,以防止滥用和用于指纹识别技术。应用不应对此版本的格式做出任何假设。在使用此 API 时,应用应已处理版本变更,并且在大多数情况下无需更改其当前行为,除非开发者尝试推断超出此 API 预期范围的其他信息。

更安全的 intent

“更安全的 intent”功能是一项分阶段的安全计划,旨在提高 Android intent 解析机制的安全性。目的是在 intent 处理期间添加检查并过滤不符合特定条件的 intent,以保护应用免受恶意操作的侵害。

Android 15 中,该功能侧重于发送应用,而现在在 Android 16 中,该功能会将控制权转移到接收应用,让开发者可以选择使用应用清单启用严格的 intent 解析。

我们将实施以下两项重大变更:

  1. 显式 intent 必须与目标组件的 intent 过滤器相匹配:如果 intent 明确定位到某个组件,则应与该组件的 intent 过滤器相匹配。

  2. 没有操作的 intent 无法与任何 intent 过滤器匹配:未指定操作的 intent 不应解析为任何 intent 过滤器。

这些更改仅适用于涉及多个应用的情况,不会影响单个应用内的 intent 处理。

影响

这种“用户选择启用”属性意味着,开发者必须在应用清单中明确启用该功能,才能使其生效。因此,只有开发者符合以下条件的应用会受到该功能的影响:

  • 了解“更安全的 intent”功能及其优势。
  • 主动选择在应用中采用更严格的 intent 处理做法。

这种“用户选择接受”方法可最大限度地降低破坏可能依赖于当前安全性较低的 intent 解析行为的现有应用的风险。

虽然在 Android 16 中的初始影响可能有限,但“更安全的 intent”计划制定了路线图,以便在未来的 Android 版本中产生更广泛的影响。我们的计划是最终将严格的 intent 解析设为默认行为。

通过提高恶意应用利用 intent 解析机制中的漏洞的难度,更安全的 intent 功能有望显著增强 Android 生态系统的安全性。

不过,必须谨慎管理向“用户选择拒绝才无效”和强制执行过渡,以解决与现有应用的潜在兼容性问题。

实现

开发者需要在应用清单中使用 intentMatchingFlags 属性明确启用更严格的 intent 匹配。以下示例展示了如何为整个应用选择启用该功能,但在接收器上停用/选择停用该功能:

<application android:intentMatchingFlags="enforceIntentFilter">
    <receiver android:name=".MyBroadcastReceiver" android:exported="true" android:intentMatchingFlags="none">
        <intent-filter>
            <action android:name="com.example.MY_CUSTOM_ACTION" />
        </intent-filter>
        <intent-filter>
            <action android:name="com.example.MY_ANOTHER_CUSTOM_ACTION" />
        </intent-filter>
    </receiver>
</application>

有关支持的标志的更多信息:

标志名称 说明
enforceIntentFilter 对传入 intent 强制执行更严格的匹配
none 停用针对传入 intent 的所有特殊匹配规则。指定多个标志时,系统会通过将“none”标志的优先级设为最高来解析冲突的值
allowNullAction 放宽匹配规则,以允许没有匹配操作的 intent。此标志应与“enforceIntentFilter”结合使用,以实现特定行为

测试和调试

强制执行生效后,如果 intent 调用方已正确填充 intent,应用应能正常运行。不过,被屏蔽的 intent 会触发带有标记 "PackageManager." 的警告日志消息,例如 "Intent does not match component's intent filter:""Access blocked:"。这表示可能存在影响应用且需要注意的潜在问题。

Logcat 过滤条件:

tag=:PackageManager & (message:"Intent does not match component's intent filter:" | message: "Access blocked:")

隐私设置

Android 16(API 级别 36)包含以下隐私权变更。

本地网络权限

Devices on the LAN can be accessed by any app that has the INTERNET permission. This makes it easy for apps to connect to local devices but it also has privacy implications such as forming a fingerprint of the user, and being a proxy for location.

The Local Network Protections project aims to protect the user's privacy by gating access to the local network behind a new runtime permission.

Release plan

This change will be deployed between two releases, 25Q2 and TBD respectively. It is imperative that developers follow this guidance for 25Q2 and share feedback because these protections will be enforced at a later Android release. Moreover, they will need to update scenarios which depend on implicit local network access by using the following guidance and prepare for user rejection and revocation of the new permission.

Impact

At the current stage, LNP is an opt-in feature which means only the apps that opt in will be affected. The goal of the opt-in phase is for app developers to understand which parts of their app depend on implicit local network access such that they can prepare to permission guard them for the next release.

Apps will be affected if they access the user's local network using:

  • Direct or library use of raw sockets on local network addresses (e.g. mDNS or SSDP service discovery protocol)
  • Use of framework level classes that access the local network (e.g. NsdManager)

Traffic to and from a local network address requires local network access permission. The following table lists some common cases:

App Low Level Network Operation Local Network Permission Required
Making an outgoing TCP connection yes
Accepting incoming TCP connections yes
Sending a UDP unicast, multicast, broadcast yes
Receiving an incoming UDP unicast, multicast, broadcast yes

These restrictions are implemented deep in the networking stack, and thus they apply to all networking APIs. This includes sockets created in native or managed code, networking libraries like Cronet and OkHttp, and any APIs implemented on top of those. Trying to resolve services on the local network (i.e. those with a .local suffix) will require local network permission.

Exceptions to the rules above:

  • If a device's DNS server is on a local network, traffic to or from it (at port 53) doesn't require local network access permission.
  • Applications using Output Switcher as their in-app picker won't need local network permissions (more guidance to come in 2025Q4).

Developer Guidance (Opt-in)

To opt into local network restrictions, do the following:

  1. Flash the device to a build with 25Q2 Beta 3 or later.
  2. Install the app to be tested.
  3. Toggle the Appcompat flag in adb:

    adb shell am compat enable RESTRICT_LOCAL_NETWORK <package_name>
    
  4. Reboot The device

Now your app's access to the local network is restricted and any attempt to access the local network will lead to socket errors. If you are using APIs that perform local network operations outside of your app process (ex: NsdManager), they won't be impacted during the opt-in phase.

To restore access, you must grant your app permission to NEARBY_WIFI_DEVICES.

  1. Ensure the app declares the NEARBY_WIFI_DEVICES permission in its manifest.
  2. Go to Settings > Apps > [Application Name] > Permissions > Nearby devices > Allow.

Now your app's access to the local network should be restored and all your scenarios should work as they did prior to opting the app in.

Once enforcement for local network protection begins, here is how the app network traffic will be impacted.

Permission Outbound LAN Request Outbound/Inbound Internet Request Inbound LAN Request
Granted Works Works Works
Not Granted Fails Works Fails

Use the following command to toggle-off the App-Compat flag

adb shell am compat disable RESTRICT_LOCAL_NETWORK <package_name>

Errors

Errors arising from these restrictions will be returned to the calling socket whenever it invokes send or a send variant to a local network address.

Example errors:

sendto failed: EPERM (Operation not permitted)

sendto failed: ECONNABORTED (Operation not permitted)

Local Network Definition

A local network in this project refers to an IP network that utilizes a broadcast-capable network interface, such as Wi-Fi or Ethernet, but excludes cellular (WWAN) or VPN connections.

The following are considered local networks:

IPv4:

  • 169.254.0.0/16 // Link Local
  • 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:

  • Link-local
  • Directly-connected routes
  • Stub networks like Thread
  • Multiple-subnets (TBD)

Additionally, both multicast addresses (224.0.0.0/4, ff00::/8) and the IPv4 broadcast address (255.255.255.255) are classified as local network addresses.