Android 12 适配指南

前言

本文基于 Android 12 开发者预览版 2 中进行介绍新版本中的部分特性。

时间轴、里程碑和更新:

时间轴、里程碑和更新


1. 获取 Android 12

获取最新 Android 12 的方式有两种,一为你已拥有安装了 Android 11 的 Google Pixel 设备,或者 Android 模拟器。本文介绍的方式为如何通过模拟器设置 Android 12 的 SDK。

  1. 安装 Android Studio 的最新预览版 build

  2. 在 Android Studio 中,依次点击 Tools > SDK Manager

  3. SDK Tools 标签页中,选择最新版 Android 模拟器,然后点击 OK。如果尚未安装最新版本,则此操作会安装最新版本。

  4. 在 Android Studio 中,依次点击 Tools > AVD Manager,然后按照说明创建新的 Android 虚拟设备 (AVD)。

    请务必选择 Pixel 3、Pixel 3a、Pixel 4、Pixel 4a 或 Pixel 5 设备定义以及 64 位 Android 12 模拟器系统映像。请注意,Android 12 不支持 32 位 Android 模拟器系统映像。如果您尚未安装与您的设备定义匹配的 Android 12 系统映像,请点击 Release Name 旁边的 Download 下载该映像。

  5. 在 AVD Manager 中返回虚拟设备列表,然后双击您的 Android 12 虚拟设备以启动它。


2. API 变更

Android 12 面向开发者引入了一些出色的新功能和 API。以下几部分内容可帮助您了解适用于您的应用的功能并开始使用相关 API。


2.1 GIF 和 WebP 的原生 ImageDecoder 支持

在 Android 12 中,NDK ImageDecoderAPI 已进行了扩展,可以对 GIF 和 WebP 文件格式的图片的所有帧和时间数据进行解码。在 Android 11 中引入该 API 时,该 API 仅从这些格式的动画中解码第一张图片。

使用 ImageDecoder(而非第三方库)可进一步缩减 APK 大小,并从未来与安全性和性能相关的更新中受益。


2.2 支持圆角

许多现代设备的屏幕采用圆角设计,这彰显了简洁时尚的风格,但也为应用开发者带来一些额外的问题。要在这些设备上提供出色的用户体验,开发者需要将这些圆角纳入考虑,调整圆角附近的界面元素,防止出现裁切的情况。

为了解决这个问题,Android 12 引入了新的 API,便于您查询圆角及其详情。RoundedCorner 提供了圆角半径、中心点等信息。可以通过 Display.getRoundedCorner() 来获取每个圆角的详尽信息。

还可以调用 WindowInsets.getRoundedCorner() 来获取基于应用边界的圆角位置等信息。如此一来,你就可以根据需要灵活调整界面元素和内容的位置。

截图


2.3 更易用的模糊、色彩滤镜等特效

在 Android 12 中,可以更轻松地将常用图形效果应用于视图和渲染结构上。可以使用 RenderEffect 将模糊、色彩滤镜等特效应用于任何 RenderNode。可以将这些特效组合为连锁特效 (即组成内部和外部特效),也可以混用这些特效。还可以通过调用 View.setRenderEffect(RenderEffect) 将特效直接应用于视图 (View,因为其基于 RenderNode)。

view.setRenderEffect(RenderEffect.createBlurEffect(radiusX, radiusY, SHADER_TILE_MODE))

有了这个功能,在模糊 ImageView 时,就不必进行获取位图数据、处理图像、创建新 Bitmap,再将其设置回 ImageView 这些操作了。RenderEffect 利用了现有的渲染流水线,最大限度地减少了额外的计算量。

还可以使用新的 Window.setBackgroundBlurRadius() API 为窗口背景创建雾面玻璃效果。这个 API 可以设置模糊半径,以调整雾面密度和范围,平台只会对您的应用窗口边框内的背景内容应用模糊效果。还可以使用 blurBehindRadius 来模糊窗口后面的所有内容,从而为浮动窗口营造出深度效果。

截图


3. 影响应用的行为变更

3.1 针对所有应用的行为变更

以下行为变更将影响在 Android 12 上运行的所有应用,无论采用哪种 targetSdkVersion 都不例外。


3.1.1 对 MAC 地址的限制

Android 12 进一步限制了所有非系统应用对设备的 MAC 地址的访问。

相关 API 会返回空值或占位值,具体取决于应用的 Target SDK 版本:

  • 如果应用以 Android 12 为目标平台,则该 API 会返回 null。
  • 如果应用以 Android 11 或更低版本为目标平台,则该 API 将返回硬编码占位值:02:00:00:00:00:00

开发者应使用 ConnectivityManager,而不是较低级别的 API,例如 NetworkInterfacegetifaddrs()。开发者在其代码中调用 NetworkInterface.getHardwareAddress() 时,logcat 输出会显示:CompatibilityChangeReporter: Compat change id reported: 170188668;

开发者可以使用名为 RETURN_NULL_HARDWARE_ADDRESS 的兼容性标志切换 NetworkInterface.getHardwareAddress() 的行为:在启用时返回 null,或在停用时返回 02:00:00:00:00:00


3.1.2 应用覆盖控制

Android 的系统警告框允许一个应用在其他活动应用之上覆盖显示一个图层,以帮助应用提醒用户关注重要操作。不过由于这些窗口会中断用户操作,因此应用需要请求权限才能显示这些内容。在 Android 12 中,可以控制是否允许在自己的内容上显示这些覆盖图层。在声明新权限后,你的应用可以调用 Window#setHideOverlayWindows(),以表明在你的应用窗口可见时应隐藏所有 TYPE_APPLICATION_OVERLAY 窗口,比如可以在交易确认流程等敏感界面中如此操作。


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

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

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

  • 如果应用以 Android 11(API 级别 30)或更低版本为目标平台,则系统不会执行 intent,并且 Logcat 中会显示以下消息:

  E ActivityTaskManager Permission Denial: \
  android.intent.action.CLOSE_SYSTEM_DIALOGS broadcast from \
  com.package.name requires android.permission.BROADCAST_CLOSE_SYSTEM_DIALOGS, \
  dropping broadcast.


3.2 针对以 Android 12 为目标平台的应用

3.2.1 更安全的导出组件

包含 intent 过滤器的应用组件必须显式设置 android:exported 属性,如 Activity、Service、Broadcast Receive。 未设置该属性的应用无法安装在 Android 12 上。

错误信息:

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'

正确示范:

<service android:name="com.example.app.backgroundService"
         android:exported="false">
    <intent-filter>
        <action android:name="com.example.app.START_BACKGROUND" />
    </intent-filter>
</service>


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

如果你的应用以 Android 12 为目标平台,则必须为你的应用创建的每个 PendingIntent对象指定可变性。这项额外的要求可提高应用的安全性。

如需声明特定 PendingIntent 对象是否可变,请分别使用 PendingIntent.FLAG_MUTABLEPendingIntent.FLAG_IMMUTABLE 标志。如果你的应用试图在不设置任何可变标志的情况下创建 PendingIntent 对象,系统会抛出 IllegalArgumentException,并在 Logcat 中显示以下消息:

PACKAGE_NAME: Targeting S+ (version 10000 and above) requires that one of \
FLAG_IMMUTABLE or FLAG_MUTABLE be specified when creating a PendingIntent.

Strongly consider using FLAG_IMMUTABLE, only use FLAG_MUTABLE if \
some functionality depends on the PendingIntent being mutable, e.g. if \
it needs to be used with inline replies or bubbles.

尽可能创建不可变的待处理 intent

在大多数情况下,你的应用应创建不可变的 PendingIntent 对象,如以下代码段所示。如果 PendingIntent 对象不可变,则应用无法修改 intent 来调整调用 intent 的结果。

PendingIntent pendingIntent = PendingIntent.getActivity(
                getApplicationContext(),
                REQUEST_CODE, 
                intent, 
                PendingIntent.FLAG_IMMUTABLE // flags
        );

然而,某些应用需要创建可变的 PendingIntent 对象:

  • 通知中的直接回复操作需要变更与回复关联的 PendingIntent 对象中的剪辑数据。通常,您可以通过将 FILL_IN_CLIP_DATA 作为标志传递给 fillIn()的方法请求此变更。
  • 如果您的应用使用 PendingIntent 将对话放在气泡中,则 intent 应该可变,以便系统可以应用正确的标志,例如 FLAG_ACTIVITY_MULTIPLE_TASKFLAG_ACTIVITY_NEW_DOCUMENT

如果您的应用创建了可变的 PendingIntent 对象,强烈建议您使用显式 intent 并填写 ComponentName。如此一来,每当另一个应用调用 PendingIntent 并将控制权传回您的应用时,应用中的相同组件都会启动。


3.2.3 前台服务启动限制

以 Android 12 为目标平台的应用在后台运行时无法再启动前台服务,但一些特殊情况除外。如果应用在后台运行时尝试启动前台服务,并且前台服务不符合任何特殊情况,则系统会抛出IllegalStateException


4. 关于APP 适配

基于对 Android 12 的调研以及还呗当前的环境配置,总结出还呗可能面临的一些适配问题

我司 App 当前环境配置:

compileSdkVersion = 27
targetSdkVersion = 27

由于当前的目标版本为27,小于 Android 12 的目标版本,因此目前只需要关注所有应用的行为变更,如MAC 地址的限制、禁止使用ACTION_CLOSE_SYSTEM_DIALOGS的 intent 操作。

如果未来计划升级目标版本至 31,则需关注以 Android 12 为目标平台的改动,如清单文件中申明了intent-filter的 Activity、Service,必须设置android:exported,我们目前在 APP 启动页、短链唤起页等使用了 intent 过滤器;以及在集成推送服务时,使用到的PendingIntent也需要适配,详细可参考官方文档。


5. 参考资料

Android 12 预览

获取 Android 12

Android 12 新功能

行为变更 - 所有应用

行为变更 - 以 Android 12 为目标平台

API 差异性报告

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,126评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,254评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,445评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,185评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,178评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,970评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,276评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,927评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,400评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,883评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,997评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,646评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,213评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,204评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,423评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,423评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,722评论 2 345

推荐阅读更多精彩内容