Android 12应用适配指南

1.Android 12上的主要变更

1.1 兼容性

1.1.1 前台服务启动限制

说明:除少数特殊情况外,以Android 12为目标的应用程序无法在后台运行时启动前台服务。如果应用程序在后台运行时尝试启动前台服务,并且前台服务不满足以下特殊情况之一,则系统将抛出ForegroundServiceStartNotAllowedException异常。具体情况可查询  https://developer.android.com/about/versions/12/foreground-services 。

注意:如果一个应用程序调用Context.startForegroundService()启动另一个应用程序拥有的前台服务,则只有两个应用程序的API级别都为Android 12时,此页面上描述的限制才有效。

影响范围:targetSdkVersion为31的应用。

适配建议:如果您的应用想要在后台运行时启动前台服务但又不符合以上几种特例时,您可以尝试使用WorkManager启动优先级更高的后台任务。在Android 12中WorkManager将支持一种新作业-加急作业,它允许应用执行重要任务,同时使系统能够更好地控制对资源的访问权限。但是加急作业并不是万能的,在系统负载过高或者已超出加急作业配额限制的时候,系统会延迟启动新的加急作业。

1.1.2 前台服务通知延迟

为了在 Android 12 上提供针对短时间运行的前台服务的流畅体验,系统可以为某些前台服务延迟 10 秒显示前台服务通知。此更改使某些短期任务在显示通知之前完成。如果某项前台服务至少具有以下特征之一,则系统会在服务启动后立即显示相关通知:

1.该服务与包含操作按钮的通知相关联。

2.该服务的 foregroundServiceType 为mediaPlayback、mediaProjection 或 phoneCall。

3.该服务根据通知的类别属性中的定义,提供与通话、导航或媒体播放相关的用例。

注意:在未来的 Android 12 开发者预览版中,这些用例可能会发生变化。

4.该服务通过在设置通知时调用 setShowForegroundImmediately(),以停用行为变更。

1.1.3 待处理 intent 必须声明可变性

说明:如果您的应用以 Android 12 为目标平台,您必须为您的应用创建的每个 PendingIntent 对象指定可变性。这项额外的要求可提高应用的安全性。如需声明特定 PendingIntent 对象是否可变,请分别使用 PendingIntent.FLAG_MUTABLE 或 PendingIntent.FLAG_IMMUTABLE 标志。如果您的应用试图在不设置任何可变标志的情况下创建 PendingIntent 对象,系统会抛出 IllegalArgumentException。 

影响范围:targetSdkVersion为31的应用。

适配建议:您必须为您的应用创建的每个 PendingIntent 对象指定可变性。

1.1.4 非SDK接口名单更新

说明:Android 12相较于Android11有大量的非SDK接口名单更新,这些改变可分为两种: 

1.Android 11(API 级别 30)中不受支持的(已被列入灰名单)的非 SDK 接口现已在 Android 12 中被屏蔽;

2.在 Android 12 中被添加到 Android SDK 的非 SDK 接口。

各接口名单更新情况可查询https://developer.android.com/about/versions/12/non-sdk-12 。这些变更可能会对一些依赖了非SDK接口的应用带来不同程度的兼容性问题,特别是依赖了Android 11灰名单接口的应用,因为这些接口有一部分已经在Android 12中已归入屏蔽名单中。

影响范围:运行于Android 12上的所有应用。

适配建议:如果您的应用依赖于Android 12的受限接口,您应该开始计划升级SDK并迁移到SDK替代方案。

1.2 用户体验

每次Android系统的升级,几乎都会在交互体验上带来一些变化,此次Android 12也不例外。

1.2.1 接收内容的统一API

对于用户来说,目前还没什么方法在应用中插入和移动图片、视频和其他富有表现力的内容。为了使您的应用能够轻松接收富媒体内容,我们引入了全新的统一 API,便于您接受来自任何来源的内容。在Android 12上,您可以用粘贴板复制粘贴、键盘输入或者拖放图片或者视频等内容。

在Android 11以及之前的版本,每个界面机制(例如长按菜单或拖放)都有对应的 API。这意味着您必须单独与每个API集成,并为每种插入内容的机制添加类似的代码:

而在Android 12上,统一API会通过创建一个要实现的单一 API 来整合这些不同的代码路径,这样您就可以专注于应用特定的逻辑,而让平台处理其余的工作。

您可以向界面组件附加新接口 OnReceiveContentListener,并在通过任何机制插入内容时获得回调。此回调会成为您的代码处理接收所有内容(从纯文本和样式文本到标记、图片、视频、音频文件等)的唯一位置。

1.2.2 自定义通知变更

以前,自定义通知能够使用整个通知区域并提供自己的布局和样式。由此产生的反模式可能会令用户困惑,或在不同设备上引发布局兼容性问题。Android 12 改变了完全自定义通知的外观。

对于以 Android 12 为目标平台的应用,包含自定义内容视图的通知将不再使用完整通知区域;相反,系统会应用标准模板。此模板可确保自定义通知在所有状态下都与其他通知相同,例如,在收起状态下的通知图标和展开功能,以及在展开状态下的通知图标、应用名称和收起功能。

通过这种方式,Android 12 通过为用户提供可看到且熟悉的通知展开功能,使所有通知保持外观一致且易于浏览。

如果您的应用使用的是完全自定义的通知,我们建议您尽快使用新模板进行测试,并进行必要的调整:

1.启用自定义通知变更:

a.将应用的 targetSdkVersion 变更为 S 以启用新行为。

b.重新编译。

c.在搭载 Android 12 的设备或模拟器上安装您的应用。

2.测试所有使用自定义视图的通知,确保这些通知在通知栏中看起来符合预期。

3.请注意自定义视图规格。一般来说,提供给自定义通知的高度比之前小。在收起状态下,自定义内容的最大高度已从 106dp 减少到 48dp。此外,水平空间也减小了。

4.为了确保“浮动通知”状态看起来符合您的预期,请勿忘记将通知渠道的重要性提升至“高”(在屏幕中弹出)。

1.2.3 配套设备的权限授予

连接到手表时,面向Android 12及更高版本的开发者们现在可以使用配置文件将特定于设备类型的一组权限捆绑在一起,让用户在手机连接上设备时将一次性授予所有权限,从而简化了设置过程。用户删除应用程序或删除关联之后,系统也会删除相关权限。

1.3 图形、图像和媒体

1.3.1 更轻松的模糊,滤色器和其他效果

Android 12添加了新功能RenderEffect ,可将常见的图形效果(例如模糊,滤色器,Android着色器效果等)应用于Views和渲染层次结构。效果可以组合为链式效果(组成内部和外部效果)或混合效果。由于处理能力有限,部分的Android设备可能不支持该功能。通过调用View.setRenderEffect(RenderEffect),效果也可以适用于View的底层的RenderNode。

实施RenderEffect:view.setRenderEffect(RenderEffect.createBlurEffect(radiusX, radiusY, SHADER_TILE_MODE))。

1.3.2音频和触觉耦合效果

Android 12应用程序可以使用手机的振动器从音频会话中生成触觉反馈。这为更身临其境的游戏和音频体验提供了机会。例如,触觉增强的铃声可以帮助识别呼叫者,或者驾驶游戏可以模拟崎岖地形的感觉。

1.4 安全性与隐私

1.4.1 更安全地导出组件

说明:如果您的应用以 Android 12 为目标平台,且包含使用 intent 过滤器的 activity、服务或广播接收器,您必须为这些应用组件显式声明 android:exported 属性。如果 activity、服务或广播接收器使用 intent 过滤器,并且未显式声明 android:exported 的值,则您的应用将无法在搭载 Android 12 的设备上进行安装。

影响范围:targetSdkVersion为31的应用。

适配建议:您必须为包含intent过滤器的应用组件显式声明 android:exported 属性。

1.4.2 adb 备份限制

说明:为了保护私有应用数据,Android 12 变更了 adb backup 命令的默认行为。对于以 Android 12 为目标平台的应用,用户运行 adb backup 命令时,从设备导出的任何其他系统数据都不包含应用数据。

影响范围:targetSdkVersion为31的应用。

适配建议:如果您的测试或开发工作流程依赖于使用 adb backup 的应用数据,现在您可以选择通过在应用的清单文件中将 android:debuggable 设置为 true 来导出应用数据。

注意:为了帮助保护应用数据,请务必在发布应用前将 android:debuggable 设置为 false。

1.4.3 以不安全的方式启动嵌套 intent

说明:嵌套 intent 是在其他 intent 中作为 extra 传递的 intent。如果您的应用同时执行以下两项操作,就会发生 StrictMode 违规行为。

1.您的应用从已传递的 intent 的 extra 中解封嵌套 intent。

2.您的应用立即使用该嵌套 intent 启动应用组件,例如将 intent 传递给 startActivity()、startService() 或 bindService()。

为了提高平台安全性,Android 12 提供了一种调试功能,如果您的应用以不安全的方式启动嵌套 intent,此功能便会发出警告。如需检查您的应用中是否会以不安全的方式启动嵌套 intent,请在配置 VmPolicy 时调用 detectUnsafeIntentLaunch()。如果您的应用检测到 StrictMode 违规行为,您可能需要停止应用的执行以保护潜在的敏感信息。

影响范围:targetSdkVersion为31的应用。

适配建议:您的应用可能会启动嵌套 intent,以便在应用的各个组件之间导航,或代表其他应用执行操作。如需在这两种情况下最大限度地降低出现 StrictMode 违规行为的可能性,请执行以下操作:

1.嵌套 intent 的内部启动:确保这些组件不会被导出。

2.嵌套 intent 的跨应用启动:使用 PendingIntent 代替嵌套 intent。如此一来,当 PendingIntent 从包含它的 Intent 中解封时,应用组件可以使用调用进程的身份启动 PendingIntent。该配置允许提供程序应用向调用应用的任何组件(包括未导出的组件)发送回调。

1.4.4 应用无法关闭系统对话框

说明:为了加强用户与应用和系统互动时的控制,从 Android 12 开始,弃用了 ACTION_CLOSE_SYSTEM_DIALOGS intent 操作。除了一些特殊情况之外,当应用尝试调用包含此操作的 intent 时,系统会基于应用的目标 SDK 版本执行以下操作之一:

1.如果应用以 Android 12 为目标平台,则会发生 SecurityException。

2.如果应用以 Android 11或更低版本为目标平台,则系统不会执行 intent,并且打印log。

在以下情况下,应用仍然可以在 Android 12 上关闭系统对话框:

1.您的应用运行的是插桩测试。

2.您的应用以 Android 11 或更低版本为目标平台,并在抽屉式通知栏顶部显示一个窗口。

如果您的应用以 Android 12 为目标平台,在这种情况下您无需使用 ACTION_CLOSE_SYSTEM_DIALOGS。这是因为,如果在窗口位于抽屉式通知栏的顶部时您的应用调用 startActivity(),系统会自动关闭抽屉式通知栏。

3. 您的应用以 Android 11 或更低版本为目标平台。此外,用户已与通知互动,可能使用了通知的操作按钮,您的应用正在处理服务或广播接收器来响应该用户操作。

影响范围:运行于Android 12上的所有应用。

1.4.5 不受信任的触摸事件被屏蔽

说明:为了维持系统安全并保持良好的用户体验,Android 12 会阻止应用使用触摸事件,使用触摸事件时叠加层会以不安全的方式遮掩应用。换言之,系统会屏蔽穿透某些窗口的触摸操作。此变更会影响选择让触摸操作穿透其窗口的应用,例如使用 FLAG_NOT_TOUCHABLE 标志。包括但不限于以下示例:

1.需要 SYSTEM_ALERT_WINDOW 权限并使用 FLAG_NOT_TOUCHABLE 标志的叠加层,例如使用 TYPE_APPLICATION_OVERLAY 的窗口。

2.使用 FLAG_NOT_TOUCHABLE 标志的 activity 窗口。

3.消息框消息。

在以下情况下,允许执行“穿透”触摸操作:

1.应用中的互动。您的应用会显示叠加层,并且只有当用户与您的应用进行互动时才会显示叠加层。

2.可信窗口。包括但不限于以下窗口:

    a.无障碍窗口

    b.输入法 (IME) 窗口

    c.Google 助理窗口

    注意:类型为 TYPE_APPLICATION_OVERLAY 的窗口不受信任。

3.不可见窗口。窗口的根视图是 GONE 或 INVISIBLE。

4.全透明窗口。窗口的 alpha 属性为 0.0。

5.足够半透明的系统警报窗口。当组合后的不透明度小于或等于系统针对触摸的最大遮掩不透明度时,系统会将一组系统警报窗口视为足够半透明。如果系统屏蔽触摸操作,Logcat 会记录以下消息:Untrusted touch due to occlusion by PACKAGE_NAME。

影响范围:运行于Android 12上的所有应用。

1.4.6 隐藏应用程序覆盖窗口

为了使开发人员能够更好地控制用户与开发人员的应用进行交互时所看到的内容,Android 12引入了隐藏已授予SYSTEM_ALERT_WINDOW 权限的应用的叠加窗口的功能 。

声明 HIDE_OVERLAY_WINDOWS 许可后,应用程序可以调用 setHideOverlayWindows() 以指示当该应用程序自己的窗口可见时,所有TYPE_APPLICATION_OVERLAY类型的窗口都应隐藏。在显示敏感内容(例如交易确认)时,应用程序可能会选择执行此操作。

显示TYPE_APPLICATION_OVERLAY窗口类型的应用应考虑可能更适合其用例的替代方案,例如画中画或气泡。

1.4.7 安全锁屏通知操作

Android 12在Notification.Action.Builder中添加了新的setAuthenticationRequired 标志。您可以使用该标志为锁定设备上的通知添加额外的安全保护。

当通知操作(notificaiton action)中的setAuthenticationRequired值为true时,用户必须先完成身份认证之后才能在锁定设备上进行通知操作。在这之前,仅当用户通知操作启动Activity或直接答复时,系统才会要求在锁定的设备上进行身份验证。要实现此功能,请添加setAuthenticationRequired到通知操作中。

1.5 其他功能

1.5.1 圆角API

Android 12引入了RoundedCorner 和WindowInsets.getRoundedCorner(int position) API,提供了屏幕圆角的半径和中心点。使用这些API,您的应用程序可以避免UI元素在带有圆角的屏幕上被截断。这些API在非圆角屏幕的设备上不生效。

1.5.2 运动传感器的速率限制

为了保护用户的潜在敏感信息,如果您的应用以 Android 12 为目标平台,则系统会将来自某些运动传感器和位置传感器的数据刷新率限制为200 Hz。该数据包括由设备的加速度计,陀螺仪和地磁场传感器记录的值 。

如果您的应用程序以Android 12为目标平台并且需要以更高的速率收集运动传感器数据,则必须声明 HIGH_SAMPLING_RATE_SENSORS 权限。如果您的应用尝试在未声明此权限的情况下以更高的速率收集运动传感器数据, 系统会抛出SecurityException异常。

2.参考链接

[1]前台服务启动设置:https://developer.android.com/about/versions/12/foreground-services

[2]非SDK接口名单更新:https://developer.android.com/about/versions/12/non-sdk-12

[3]接收内容的统一API:https://developer.android.com/about/versions/12/features/unified-content-api

[4]自定义通知变更:https://developer.android.com/about/versions/12/behavior-changes-12#custom-notifications