Android 12目前还是开发者预览版,预计到8月份会出正式版,但是官网已经给出了关于以Android 12为目标的应用适配应该注意的事项。
exported
属性以Android 12 为目标平台的应用,且包含使用intent 过滤器的activity、服务或广播接收器,必须为这些应用组件显式声明android:exported
属性。
如果 activity、服务或广播接收器使用 intent 过滤器,并且未显式声明android:exported
的值,则您的应用将无法在搭载 Android 12 的设备上进行安装。
如果您在使用 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:exported
的值时未进行此声明,则 Logcat 会提供以下错误消息:
Targeting S+(version10000 and above) requires that an explicit valuefor \ android:exported be defined when intent filters are present
以下代码段显示了一个服务示例,该服务包含 intent 过滤器并针对 Android 12 进行了正确配置:
<service android:name="com.example.app.backgroundService" android:exported="false"><intent-filter><action android:name="com.example.app.START_BACKGROUND"/></intent-filter></service>
如果以Android 12 为目标平台,必须为应用创建的每个PendingIntent 对象指定可变性。
要声明特定PendingIntent 对象是否可变,请分别使用PendingIntent.FLAG_MUTABLE
或PendingIntent.FLAG_IMMUTABLE
标志。
如果您的应用创建未包含设置任何可变标志的PendingIntent 对象,系统会抛出IllegalArgumentException
,并在Logcat 中显示以下消息:
PACKAGE_NAME: Targeting S+(version10000 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_MUTABLEif \ some functionality depends on the PendingIntent being mutable, e.g.if \ it needs to be used with inline replies or bubbles.
然而,某些应用需要创建可变的 PendingIntent 对象:
如果您的应用创建了可变的 PendingIntent 对象,强烈建议您使用显式 intent 并填写 ComponentName。如此一来,每当另一个应用调用 PendingIntent 并将控制权传回您的应用时,应用中的相同组件都会启动。
为了提高平台安全性,Android 12 提供了一种调试功能,如果您的应用以不安全的方式启动嵌套intent,此功能便会发出警告。嵌套 intent 是在其他 intent 中作为 extra 传递的 intent。
如果您的应用同时执行以下两项操作,就会发生StrictMode 违规行为:
startActivity()
、startService()
或bindService()
。如何检测嵌套 intent 的不安全启动
如需检查您的应用中是否会以不安全的方式启动嵌套intent,请在配置VmPolicy
时调用detectUnsafeIntentLaunch()
,如以下代码段所示:
protectedvoidonCreate(){ StrictMode.setVmPolicy(newVmPolicy.Builder()// Other StrictMode checks that you've previously added.// ....detectUnsafeIntentLaunch().penaltyLog()// Consider also adding penaltyDeath().build());}
如果您的应用检测到StrictMode
违规行为,您可能需要停止应用的执行以保护潜在的敏感信息。
注意:如果您的应用以 Android 12 为目标平台,并在其VmPolicy
定义中使用detectAll()
方法,系统将自动调用detectUnsafeIntentLaunch()
方法。
如何最大限度地降低出现 StrictMode 违规行为的可能性
如果您的应用不可避免的会启动嵌套intent
,以便在应用的各个组件之间导航,或代表其他应用执行操作等。请执行以下操作:
PendingIntent
代替嵌套intent
。如此一来,当PendingIntent
从包含它的Intent
中解封时,应用组件可以使用调用进程的身份启动PendingIntent
。该配置允许提供程序应用向调用应用的任何组件(包括未导出的组件)发送回调。以Android 12 为目标平台的应用再也无法在后台运行时启动前台服务,但一些特殊情况除外。如果应用尝试在后台运行时启动前台服务,则会引发异常(少数特殊情况除外)。当您的应用在后台运行时,请考虑使用WorkManager
来计划和启动工作。
当用户与通知互动时,某些应用会启动应用组件来响应通知点按操作,此应用组件最终会启动用户最终看到并与之互动的activity。此应用组件被称为通知trampoline。
为了改进应用性能和用户体验,以Android 12 为目标平台的应用无法从用作通知trampoline 的服务或广播接收器中启动activity。换言之,当用户点按通知或通知中的操作按钮时,您的应用无法在服务或广播接收器内调用startActivity()
。
当您的应用尝试从充当通知trampoline 的服务或广播接收器启动activity 时,系统会阻止启动该activity 启动,并在Logcat 中显示以下消息:
Indirect notification activity start(trampoline) from PACKAGE_NAME, \this should be avoidedfor performance reasons.
解决方法:
如果您的应用从充当通知trampoline 的服务或广播接收器启动activity,请完成以下迁移步骤:
1.创建一个与以下activity
关联的PendingIntent
对象:
activity
(首选)。Trampoline activity
或用于启动用户在点按通知后可以看到的activity
的activity
。2.在构建通知的过程中,请使用您在上一步中创建的PendingIntent
对象。
其实从 Android 9(API 级别 28)开始,Android 平台对应用能使用的非 SDK 接口就实施了限制。只要应用引用非 SDK 接口或尝试使用反射或JNI 来获取其句柄,这些限制就适用。Android 12 更新了这个限制列表(将Android 11的部分灰名单直接加到了黑名单列表中)
区分 SDK 接口和非 SDK 接口
为最大程度地降低非 SDK 使用限制对开发工作流的影响,我们将非 SDK 接口分成了几个名单,这些名单界定了非 SDK 接口使用限制的严格程度(取决于应用的目标 API 级别)
名单 | 说明 |
---|---|
黑名单 (blacklist) | 无论应用的目标 API 级别是什么,您都无法使用的非 SDK 接口。 如果您的应用尝试访问其中任何一个接口,系统就会抛出错误。 |
有条件灰名单 (greylist-max-x) | 从 Android 9(API 级别 28)开始,当有应用以该 API 级别为目标平台时,我们会在每个 API 级别分别限制某些非 SDK 接口。 这些名单会以应用无法再访问该名单中的非 SDK 接口之前可以作为目标平台的最高 API 级别 (max-target-x) 进行标记。例如,在 Android Pie 中未被屏蔽、但现在已被 Android 10 屏蔽的非 SDK 接口会列入 max-target-p (greylist-max-p) 名单,其中的“p”表示 Pie 或 Android 9(API 级别 28)。 如果您的应用尝试访问受目标 API 级别限制的接口,系统就会将此 API 视为已列入屏蔽名单。 |
灰名单 (greylist) | 当前不受限制且您的应用可以使用的非 SDK 接口。 但请注意,这些接口不受支持,可能会在未发出通知的情况下随时发生更改。预计这些接口在未来的 Android 版本中会被有条件地屏蔽,并列在 max-target-x 名单中。 |
白名单 (whitelist) | 已在 Android 框架软件包索引中正式记录、受支持并且可以自由使用的接口。 |
如何确定我当前使用的接口属于哪个名单?
hiddenapi
关键字,搜索结果中的hiddenapi-force-blacklist.txt
和hiddenapi-light-greylist.txt
就是黑名单和灰名单列表,推荐Android Source 这个网站可在线搜索如果用反射或者JNI调用了这些非SDK接口会导致什么影响:
访问方式 | 结果 |
---|---|
Dalvik 指令引用某个字段 | 抛出 NoSuchFieldError |
Dalvik 指令引用某个方法 | 抛出 NoSuchMethodError |
通过 Class.getDeclaredField() 或 Class.getField() 进行反射 | 抛出 NoSuchFieldException |
通过 Class.getDeclaredMethod()、Class.getMethod() 进行反射 | 抛出 NoSuchMethodException |
通过 Class.getDeclaredFields()、Class.getFields() 进行反射 | 结果中未获取到非 SDK 成员 |
通过 Class.getDeclaredMethods()、Class.getMethods() 进行反射 | 结果中未获取到非 SDK 成员 |
通过 env->GetFieldID() 进行 JNI 调用 | 返回 NULL,抛出 NoSuchFieldError |
通过 env->GetMethodID() 进行 JNI 调用 | 返回 NULL,抛出 NoSuchMethodError |
Android 12 改变了完全自定义通知的外观。 以前,自定义通知能够使用整个通知区域并提供自己的布局和样式。由此产生的反模式可能会令用户困惑,或在不同设备上引发布局兼容性问题。
对于以 Android 12 为目标平台的应用,包含自定义内容视图的通知将不再使用完整通知区域;相反,系统会应用标准模板。此模板可确保自定义通知在所有状态下都与其他通知相同。
换言之,应用不能在整个通知栏区域进行个性化了,大家都长一个样。这是为了保持通知外观一致且易于浏览。
下图显示了标准模板中的自定义通知:
以下示例展示了在收起状态和展开状态下呈现的自定义通知:
Android 12 中的变更会影响某些定义Notification.Style
的自定义子类的应用,或使用Notification.Builder
的方法setCustomContentView(RemoteViews)
、setCustomBigContentView(RemoteViews)
和setCustomHeadsUpContentView(RemoteViews)
的应用。
如果您的应用使用的是完全自定义的通知,建议尽快使用新模板进行测试,并进行必要的调整:
targetSdkVersion
变更为S
以启用新行为。Android 12
的设备或模拟器上安装您的应用。106dp
减少到48dp
。此外,水平空间也减小了。什么是 SameSite Cookie?
可参考以下文章了解:
Cookie 的SameSite 属性决定了它是可以与任何请求一起发送,还是只能与同站点请求一起发送。Android 12 中的WebView 基础版本包含以下隐私保护方面的变更,旨在改善对第三方Cookie 的默认处理方式,并帮助防止意外跨站点共享:
SameSite=Lax
。SameSite=None
的Cookie 还必须指定Secure 属性,这意味着它们需要安全的上下文,并应通过HTTPS 发送。SameSite=None; Secure
,否则Cookie 不会被发送。对于开发者而言,一般指导意见是识别关键用户流中的跨站点Cookie 依赖项,并确保在需要时使用适当的值显式设置SameSite
属性。您必须显式指定允许在不同网站上运行的Cookie,或适用于从HTTP 切换到HTTPS 进行同站点导航的Cookie。
为了保护私有应用数据,Android 12 变更了adb backup
命令的默认行为。对于以 Android 12 为目标平台的应用,用户运行adb backup
命令时,从设备导出的任何其他系统数据都不包含应用数据。
如果您的测试或开发工作流程依赖于使用adb backup
的应用数据,现在您可以选择通过在应用的清单文件中将android:debuggable
设置为true
来导出应用数据。
以上,可参考官网:行为变更:以 Android 12 为目标平台的应用