与早期版本一样,Android 12 包含可能影响您应用的行为变更。以下行为变更仅适用于面向 Android 12 或更高版本的应用。如果您的应用面向 Android 12,则应在适用的情况下修改您的应用以正确支持这些行为。
请务必还查看 影响在 Android 12 上运行的所有应用的行为变更 列表。
用户体验
自定义通知
Android 12 更改了完全 自定义通知 的外观和行为。以前,自定义通知能够使用整个通知区域并提供自己的布局和样式。这导致了一些反模式,可能会让用户感到困惑或在不同设备上导致布局兼容性问题。
对于面向 Android 12 的应用,使用自定义内容视图的通知将不再使用完整的通知区域;相反,系统会应用标准模板。此模板确保自定义通知在所有状态下都具有与其他通知相同的装饰,例如通知的图标和展开控件(在折叠状态下)以及通知的图标、应用名称和折叠控件(在展开状态下)。此行为与 Notification.DecoratedCustomViewStyle
的行为几乎相同。
通过这种方式,Android 12 使所有通知在视觉上保持一致且易于扫描,并为用户提供可发现且熟悉的通知展开功能。
下图显示了标准模板中的自定义通知
以下示例显示了自定义通知在折叠和展开状态下的渲染方式
Android 12 中的更改会影响定义 Notification.Style
的自定义子类或使用 Notification.Builder
的方法 setCustomContentView(RemoteViews)
、setCustomBigContentView(RemoteViews)
和 setCustomHeadsUpContentView(RemoteViews)
的应用。
如果您的应用正在使用完全自定义的通知,我们建议尽快使用新模板进行测试。
启用自定义通知更改
- 将应用的
targetSdkVersion
更改为S
以启用新行为。 - 重新编译。
- 将您的应用安装在运行 Android 12 的设备或模拟器上。
- 将应用的
测试所有使用自定义视图的通知,确保它们在通知栏中的外观符合您的预期。在测试过程中,请考虑以下因素并进行必要的调整
自定义视图的尺寸已更改。通常,分配给自定义通知的高度比以前要小。在折叠状态下,自定义内容的最大高度已从 106dp 减少到 48dp。此外,水平空间也减少了。
对于面向 Android 12 的应用,所有通知都是可展开的。通常,这意味着如果您使用的是
setCustomContentView
,您可能也希望使用setBigCustomContentView
以确保折叠和展开状态一致。为了确保“悬浮”状态的外观符合您的预期,请不要忘记将通知频道的优先级提高到“高”(在屏幕上弹出)。
Android 应用链接验证更改
在面向 Android 12 或更高版本的应用上,系统对 Android 应用链接的验证方式 进行了一些更改。这些更改提高了应用链接体验的可靠性,并为应用开发者和最终用户提供了更多控制权。
如果您依赖 Android 应用链接验证在应用中打开网络链接,请检查您在 添加 Android 应用链接验证的意图过滤器 时是否使用了正确的格式。特别是,请确保这些意图过滤器包含 BROWSABLE
类别并支持 https
方案。
您还可以 手动验证 应用的链接以测试声明的可靠性。
画中画行为改进
Android 12 引入了画中画 (PiP) 模式下的行为改进,以及针对手势导航和元素导航的过渡动画的推荐美学改进。
有关详细信息,请参阅画中画改进。
Toast 重设计
在 Android 12 中,Toast 视图已重新设计。Toast 现在限制为两行文本,并在文本旁边显示应用程序图标。
有关更多详细信息,请参阅Toast 概述。
安全与隐私
近似位置
在运行 Android 12 或更高版本的设备上,用户可以为您的应用请求近似位置精度。
WebView 中的现代 SameSite Cookie
Android 的 WebView 组件基于Chromium,这是一个为 Google Chrome 浏览器提供支持的开源项目。Chromium 对第三方 Cookie 的处理方式进行了更改,以提供更高的安全性和隐私性,并为用户提供更多透明度和控制权。从 Android 12 开始,当应用以 Android 12(API 级别 31)或更高版本为目标时,这些更改也包含在WebView
中。
Cookie 的SameSite
属性控制它是否可以与任何请求一起发送,或者仅与同站点请求一起发送。以下隐私保护更改改进了第三方 Cookie 的默认处理方式,并有助于防止意外的跨站点共享
- 没有
SameSite
属性的 Cookie 将被视为SameSite=Lax
。 - 具有
SameSite=None
属性的 Cookie 还必须指定Secure
属性,这意味着它们需要安全上下文,并且应通过 HTTPS 发送。 - 站点 HTTP 和 HTTPS 版本之间的链接现在被视为跨站点请求,因此除非 Cookie 被适当地标记为
SameSite=None; Secure
,否则不会发送 Cookie。
对于开发者,一般的指导原则是识别关键用户流程中的跨站点 Cookie 依赖项,并确保在需要的地方显式设置SameSite
属性并使用适当的值。您必须显式指定允许跨网站或跨从 HTTP 转到 HTTPS 的同站点导航工作的 Cookie。
有关 Web 开发人员对这些更改的完整指南,请参阅SameSite Cookie 解释和Schemeful SameSite。
测试应用中的 SameSite 行为
如果您的应用使用 WebView,或者您管理使用 Cookie 的网站或服务,我们建议您在 Android 12 WebView 上测试您的流程。如果您发现问题,您可能需要更新您的 Cookie 以支持新的 SameSite 行为。
注意登录和嵌入内容中的问题,以及登录流程、购买和其他身份验证流程,其中用户从不安全页面过渡到安全页面。
要使用 WebView 测试应用,您必须为要测试的应用启用新的 SameSite 行为,方法是完成以下任一步骤
通过在 WebView 开发工具中切换 UI 标志 webview-enable-modern-cookie-same-site,在测试设备上手动启用 SameSite 行为。WebView 开发工具。
这种方法允许您在任何运行 Android 5.0(API 级别 21)或更高版本(包括 Android 12)的设备以及 WebView 版本 89.0.4385.0 或更高版本上进行测试。
通过
targetSdkVersion
编译您的应用以面向 Android 12(API 级别 31)。如果您使用此方法,则必须使用运行 Android 12 的设备。
有关 Android 上 WebView 远程调试的信息,请参阅Android 设备远程调试入门。
其他资源
有关 SameSite 现代行为以及 Chrome 和 WebView 推出的更多信息,请访问Chromium SameSite 更新页面。如果您在 WebView 或 Chromium 中发现错误,您可以在公共Chromium 问题跟踪器中报告它。
运动传感器受速率限制
为了保护用户可能敏感的信息,如果您的应用以 Android 12 或更高版本为目标,系统会限制某些运动传感器和位置传感器数据的刷新率。
详细了解传感器速率限制。
应用休眠
Android 12 扩展了在 Android 11(API 级别 30)中引入的权限自动重置行为。如果您的应用以 Android 12 为目标,并且用户几个月内没有与您的应用交互,系统会自动重置任何已授予的权限并将您的应用置于休眠状态。
在指南中详细了解应用休眠。
数据访问审计中的归因声明
在 Android 11(API 级别 30)中引入的数据访问审计 API 允许您根据您的应用用例创建归因标签。这些标签使您更容易确定应用的哪个部分执行特定类型的数据访问。
如果您的应用以 Android 12 或更高版本为目标,则必须在应用的清单文件中声明这些归因标签。
ADB 备份限制
为了帮助保护私有应用数据,Android 12 更改了adb backup
命令的默认行为。对于以 Android 12(API 级别 31)或更高版本为目标的应用,当用户运行adb backup
命令时,应用数据将从设备中导出的任何其他系统数据中排除。
如果您的测试或开发工作流程依赖于使用adb backup
的应用数据,您现在可以通过将应用清单文件中的android:debuggable
设置为true
来选择导出应用的数据。
更安全的组件导出
如果您的应用以 Android 12 或更高版本为目标,并且包含使用意图过滤器的活动、服务或广播接收器,则必须为这些应用组件显式声明android:exported
属性。
如果应用组件包含LAUNCHER
类别,请将android:exported
设置为true
。在大多数其他情况下,请将android:exported
设置为false
。
以下代码片段显示了一个包含意图过滤器且其android:exported
属性设置为false
的服务示例
<service android:name="com.example.app.backgroundService" android:exported="false"> <intent-filter> <action android:name="com.example.app.START_BACKGROUND" /> </intent-filter> </service>
Android Studio 中的消息
如果您的应用包含使用意图过滤器但未声明android:exported
的活动、服务或广播接收器,则会根据您使用的 Android Studio 版本显示以下警告消息
Android Studio 2020.3.1 Canary 11 或更高版本
将显示以下消息
清单文件中将显示以下 Lint 警告
When using intent filters, please specify android:exported as well
当您尝试编译应用时,将显示以下构建错误消息
Manifest merger failed : Apps targeting Android 12 and higher are required \ to specify an explicit value for android:exported when the corresponding \ component has an intent filter defined.
旧版 Android Studio
如果尝试安装应用,Logcat将显示以下错误消息
Installation did not succeed.
The application could not be installed: INSTALL_FAILED_VERIFICATION_FAILURE
List of apks:
[0] '.../build/outputs/apk/debug/app-debug.apk'
Installation failed due to: 'null'
挂起意图的可变性
如果您的应用以 Android 12 为目标,则必须指定应用创建的每个PendingIntent
对象的可变性。此额外要求提高了应用的安全性。
测试挂起意图的可变性更改
要确定您的应用是否缺少可变性声明,请在 Android Studio 中查找以下Lint 警告
Warning: Missing PendingIntent mutability flag [UnspecifiedImmutableFlag]
不安全的意图启动
为了提高平台安全性,Android 12 及更高版本提供了一个调试功能,该功能检测意图的不安全启动。当系统检测到此类不安全启动时,将发生StrictMode违规。
性能
前台服务启动限制
以 Android 12 或更高版本为目标的应用无法在后台运行时启动前台服务,除了少数特殊情况。如果应用尝试在后台运行时启动前台服务,则会发生异常(除了少数特殊情况)。
考虑使用 WorkManager 调度和启动快速工作,同时您的应用在后台运行。要完成用户请求的时间敏感操作,请在精确闹钟内启动前台服务。
精确闹钟权限
为了鼓励应用节省系统资源,以 Android 12 及更高版本为目标并设置精确闹钟的应用必须能够访问系统设置中“特殊应用访问”屏幕中显示的“闹钟和提醒”功能。
要获取此特殊应用访问权限,请在清单中请求SCHEDULE_EXACT_ALARM
权限。
精确闹钟应仅用于面向用户的功能。详细了解设置精确闹钟的可接受使用案例。
禁用行为更改
在准备您的应用以适配 Android 12 时,您可以暂时在可调试的构建变体中禁用行为更改以进行测试。为此,请完成以下任务之一
- 在开发者选项设置屏幕中,选择应用兼容性更改。在出现的屏幕上,点击您的应用名称,然后关闭REQUIRE_EXACT_ALARM_PERMISSION。
在开发机器上的终端窗口中,运行以下命令
adb shell am compat disable REQUIRE_EXACT_ALARM_PERMISSION PACKAGE_NAME
通知跳板限制
当用户与通知交互时,某些应用会通过启动一个最终启动用户最终看到并与其交互的活动的应用组件来响应通知点击。此应用组件称为通知跳板。
为了提高应用性能和用户体验,以 Android 12 或更高版本为目标的应用无法从用作通知跳板的服务或广播接收器中启动活动。换句话说,在用户点击通知或通知内的操作按钮后,您的应用不能在服务或广播接收器内调用startActivity()
。
当您的应用尝试从充当通知跳板的服务或广播接收器启动活动时,系统会阻止活动启动,并且以下消息将显示在Logcat中
Indirect notification activity start (trampoline) from PACKAGE_NAME, \
this should be avoided for performance reasons.
确定哪些应用组件充当通知跳板
在测试您的应用时,在点击通知后,您可以确定哪个服务或广播接收器充当了应用中的通知跳板。为此,请查看以下终端命令的输出
adb shell dumpsys activity service \ com.android.systemui/.dump.SystemUIAuxiliaryDumpService
输出的一部分包含文本“NotifInteractionLog”。此部分包含识别作为通知点击结果启动的组件所需的信息。
更新您的应用
如果您的应用从充当通知跳板的服务或广播接收器启动活动,请完成以下迁移步骤
- 创建一个与用户点击通知后看到的活动关联的
PendingIntent
对象。 - 将您在上一步中创建的
PendingIntent
对象用作构建通知的一部分。
为了识别活动的来源(例如,执行日志记录),请在发布通知时使用额外信息。对于集中式日志记录,请使用ActivityLifecycleCallbacks
或Jetpack 生命周期观察者。
切换行为
在测试您的应用的可调试版本时,您可以使用NOTIFICATION_TRAMPOLINE_BLOCK
应用兼容性标志启用和禁用此限制。
备份和恢复
在运行于 Android 12(API 级别 31)及更高版本并以其为目标的应用中,备份和恢复的工作方式有所改变。Android 备份和恢复有两种形式
- 云备份:用户数据存储在用户的 Google Drive 中,以便以后可以在该设备或新设备上恢复。
- 设备到设备 (D2D) 传输:用户数据直接从用户的旧设备发送到其新设备,例如通过使用电缆。
有关如何备份和恢复数据的更多信息,请参阅使用自动备份备份用户数据和使用 Android 备份服务备份键值对。
D2D 传输功能更改
对于在 Android 12 及更高版本上运行并以其为目标的应用
使用 XML 配置机制指定包含和排除规则不会影响 D2D 传输,尽管它仍然会影响基于云的备份和恢复(例如 Google Drive 备份)。要为 D2D 传输指定规则,您必须使用下一节中介绍的新配置。
在某些设备制造商的设备上,指定
android:allowBackup="false"
会禁用对 Google Drive 的备份,但不会禁用应用的 D2D 传输。
新的包含和排除格式
在 Android 12 及更高版本上运行并以其为目标的应用使用不同的 XML 配置格式。此格式通过要求您分别为云备份和 D2D 传输指定包含和排除规则,从而明确了 Google Drive 备份和 D2D 传输之间的区别。
或者,您也可以使用它来指定备份规则,在这种情况下,以前使用的配置在运行 Android 12 或更高版本的设备上将被忽略。旧配置仍然需要用于运行 Android 11 或更低版本的设备。
XML 格式更改
以下是 Android 11 及更低版本中用于备份和恢复配置的格式
<full-backup-content> <include domain=["file" | "database" | "sharedpref" | "external" | "root"] path="string" requireFlags=["clientSideEncryption" | "deviceToDeviceTransfer"] /> <exclude domain=["file" | "database" | "sharedpref" | "external" | "root"] path="string" /> </full-backup-content>
以下显示了格式中的更改(以粗体显示)。
<data-extraction-rules> <cloud-backup [disableIfNoEncryptionCapabilities="true|false"]> ... <include domain=["file" | "database" | "sharedpref" | "external" | "root"] path="string"/> ... <exclude domain=["file" | "database" | "sharedpref" | "external" | "root"] path="string"/> ... </cloud-backup> <device-transfer> ... <include domain=["file" | "database" | "sharedpref" | "external" | "root"] path="string"/> ... <exclude domain=["file" | "database" | "sharedpref" | "external" | "root"] path="string"/> ... </device-transfer> </data-extraction-rules>
有关更多信息,请参阅指南中相应的章节,该章节介绍了如何使用自动备份备份用户数据。
应用的清单标志
通过在清单文件中使用android:dataExtractionRules
属性,将您的应用指向新的 XML 配置。当您指向新的 XML 配置时,指向旧配置的android:fullBackupContent
属性在运行 Android 12 或更高版本的设备上将被忽略。以下代码示例显示了新的清单文件条目
<application ... <!-- The below attribute is ignored. --> android:fullBackupContent="old_config.xml" <!-- You can point to your new configuration using the new dataExtractionRules attribute . --> android:dataExtractionRules="new_config.xml" ...> </application>
连接
蓝牙权限
Android 12 引入了BLUETOOTH_SCAN
、BLUETOOTH_ADVERTISE
和BLUETOOTH_CONNECT
权限。这些权限使以 Android 12 为目标的应用更容易与蓝牙设备交互,特别是对于不需要访问设备位置的应用。
要准备您的设备以适配 Android 12 或更高版本,请更新您的应用逻辑。不要声明旧版蓝牙权限集,而是声明更现代的蓝牙权限集。
并发点对点 + 互联网连接
对于以 Android 12(API 级别 31)或更高版本为目标的应用,支持并发点对点和互联网连接的设备可以同时维持与对等设备和主要互联网提供网络的 Wi-Fi 连接,从而使用户体验更加流畅。以 Android 11(API 级别 30)或更低版本为目标的应用仍会遇到旧版行为,即在连接到对等设备之前断开主要 Wi-Fi 网络的连接。
兼容性
WifiManager.getConnectionInfo()
只能返回单个网络的WifiInfo
。因此,在 Android 12 及更高版本中,API 的行为已更改为以下方式
- 如果只有一个 Wi-Fi 网络可用,则返回其
WifiInfo
。 - 如果有多个 Wi-Fi 网络可用且调用应用触发了点对点连接,则返回与对等设备对应的
WifiInfo
。 - 如果有多个 Wi-Fi 网络可用且调用应用未触发点对点连接,则返回主要互联网提供连接的
WifiInfo
。
为了在支持双并发 Wi-Fi 网络的设备上提供更好的用户体验,我们建议所有应用(尤其是触发点对点连接的应用)迁移到不调用WifiManager.getConnectionInfo()
,而是使用NetworkCallback.onCapabilitiesChanged()
来获取与用于注册NetworkCallback
的NetworkRequest
匹配的所有WifiInfo
对象。从 Android 12 开始,getConnectionInfo()
已弃用。
以下代码示例显示了如何在NetworkCallback
中获取WifiInfo
Kotlin
val networkCallback = object : ConnectivityManager.NetworkCallback() { ... override fun onCapabilitiesChanged( network : Network, networkCapabilities : NetworkCapabilities) { val transportInfo = networkCapabilities.getTransportInfo() if (transportInfo !is WifiInfo) return val wifiInfo : WifiInfo = transportInfo ... } }
Java
final NetworkCallback networkCallback = new NetworkCallback() { ... @Override public void onCapabilitiesChanged( Network network, NetworkCapabilities networkCapabilities) { final TransportInfo transportInfo = networkCapabilities.getTransportInfo(); if (!(transportInfo instanceof WifiInfo)) return; final WifiInfo wifiInfo = (WifiInfo) transportInfo; ... } ... };
mDNSResponder 本机 API
Android 12 更改了应用何时可以使用mDNSResponder 本机 API与 mDNSResponder 守护程序交互。以前,当应用在网络上注册服务并调用getSystemService()
方法时,即使应用尚未调用任何NsdManager
方法,系统的 NSD 服务也会启动 mDNSResponder 守护程序。然后,守护程序将设备订阅到所有节点多播组,导致系统更频繁地唤醒并使用更多电量。为了最大程度地减少电池使用量,在 Android 12 及更高版本中,系统现在仅在需要 NSD 事件时才启动 mDNSResponder 守护程序,并在之后停止它。
由于此更改会影响 mDNSResponder 守护程序的可用时间,因此假设在调用getSystemService()
方法后将启动 mDNSResponder 守护程序的应用可能会收到来自系统的消息,指出 mDNSResponder 守护程序不可用。使用NsdManager
且不使用 mDNSResponder 本机 API 的应用不受此更改的影响。
供应商库
供应商提供的原生共享库
由硅片供应商或设备制造商提供的非 NDK 原生共享库如果应用以 Android 12(API 级别 31)或更高版本为目标,则默认情况下不可访问。只有在使用<uses-native-library>
标记显式请求时,这些库才可访问。
如果应用以 Android 11(API 级别 30)或更低版本为目标,则不需要<uses-native-library>
标记。在这种情况下,任何原生共享库都可访问,无论它是否是 NDK 库。
更新的非 SDK 限制
Android 12 包含基于与 Android 开发人员合作和最新的内部测试更新的受限非 SDK 接口列表。只要有可能,我们都会确保在限制非 SDK 接口之前提供公共替代方案。
如果您的应用没有以 Android 12 为目标,则其中一些更改可能不会立即影响您。但是,虽然您目前可以使用某些非 SDK 接口(取决于您应用的目标 API 级别),但使用任何非 SDK 方法或字段始终存在导致应用崩溃的高风险。
如果您不确定您的应用是否使用了非 SDK 接口,您可以测试您的应用来查明。如果您的应用依赖于非 SDK 接口,则应开始计划迁移到 SDK 替代方案。尽管如此,我们理解某些应用有使用非 SDK 接口的有效用例。如果您无法找到应用中某个功能的非 SDK 接口的替代方案,则应请求新的公共 API。
要详细了解此 Android 版本中的更改,请参阅Android 12 中非 SDK 接口限制的更新。要详细了解非 SDK 接口,请参阅非 SDK 接口的限制。