写点什么

Android 12 行为变更:适配以 Android 12 为目标的应用,移动应用开发就业方向

用户头像
Android架构
关注
发布于: 10 小时前

<service android:name="com.example.app.backgroundService"


android:exported="false">


<intent-filter>


<action android:name="com.example.app.START_BACKGROUND" />


</intent-filter>


</service>


[](


)PendingIntent 必须声明可变性




如果以 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.


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


  • 通知中的直接回复操作需要变更与回复关联的 PendingIntent 对象中的剪辑数据。通常,您可以通过将 FILL_IN_CLIP_DATA 作为标志传递给 fillIn() 的方法请求此变更。

  • 如果您的应用使用 PendingIntent 将对话放在气泡中,则 intent 应该可变,以便系统可以应用正确的标志,例如 FLAG_ACTIVITY_MULTIPLE_TASK 和 FLAG_ACTIVITY_NEW_DOCUMENT。


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


[](


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




为了提高平台安全性,Android 12 提供了一种调试功能,如果您的应用以不安全的方式启动嵌套 intent,此功能便会发出警告。嵌套 intent 是在其他 intent 中作为 extra 传递的 intent


如果您的应用同时执行以下两项操作,就会发生 StrictMode 违规行为:


  • 您的应用从已传递的 intentextra 中解封嵌套 intent

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


如何检测嵌套 intent 的不安全启动


如需检查您的应用中是否会以不安全的方式启动嵌套 intent,请在配置 VmPolicy 时调用 detectUnsafeIntentLaunch(),如以下代码段所示:


protected void onCreate() {


StrictMode.setVmPolicy(new VmPolicy.Builder()


// Other StrictMode checks that you've previously added.


// ...


.detectUnsafeIntentLaunch()


.penaltyLog()


// Consider also adding penaltyDeath()


.build());


}


如果您的应用检测到 StrictMode 违规行为,您可能需要停止应用的执行以保护潜在的敏感信息。


注意:如果您的应用以 Android 12 为目标平台,并在其 VmPolicy 定义中使用 detectAll() 方法,系统将自动调用 detectUnsafeIntentLaunch() 方法。


如何最大限度地降低出现 StrictMode 违规行为的可能性


如果您的应用不可避免的会启动嵌套 intent,以便在应用的各个组件之间导航,或代表其他应用执行操作等。请执行以下操作:


  • 嵌套 intent 的内部启动确保这些组件不会被导出

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


[](


)应用再也无法在后台运行时启动前台服务




Android 12 为目标平台的应用再也无法在后台运行时启动前台服务,但一些特殊情况除外。如果应用尝试在后台运行时启动前台服务,则会引发异常(少数特殊情况除外)。当您的应用在后台运行时,请考虑使用 WorkManager 来计划和启动工作。


[](


)无法通过服务或广播接收器创建通知 trampoline




当用户与通知互动时,某些应用会启动应用组件来响应通知点按操作,此应用组件最终会启动用户最终看到并与之互动的 activity。此应用组件被称为通知 trampoline


为了改进应用性能和用户体验,以 Android 12 为目标平台的应用无法从用作通知 trampoline 的服务或广播接收器中启动 activity。换言之,当用户点按通知或通知中的操作按钮时,您的应用无法在服务或广播接收器内调用 startActivity()


当您的应用尝试从充当通知 trampoline 的服务或广播接收器启动 activity 时,系统会阻止启动该 activity 启动,并在 Logcat 中显示以下消息:


Indirect notification activity start (trampoline) from PACKAGE_NAME, \


this should be avoided for performance reasons.


解决方法:


如果您的应用从充当通知 trampoline 的服务或广播接收器启动 activity,请完成以下迁移步骤:


1.创建一个与以下 activity 关联的 PendingIntent 对象:


  • 用户点按通知后会看到的 activity(首选)。

  • Trampoline activity 或用于启动用户在点按通知后可以看到的 activityactivity


2.在构建通知的过程中,请使用您在上一步中创建的 PendingIntent 对象。


[](


)更新限制非 SDK 接口




其实从 Android 9(API 级别 28)开始,Android 平台对应用能使用的非 SDK 接口就实施了限制。只要应用引用非 SDK 接口或尝试使用反射JNI 来获取其句柄,这些限制就适用。Android 12 更新了这个


《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
浏览器打开:qq.cn.hn/FTe 免费领取
复制代码


限制列表(将 Android 11 的部分灰名单直接加到了黑名单列表中)


区分 SDK 接口和非 SDK 接口


  • SDK 接口:在 Android 框架软件包索引中记录的那些接口

  • 非 SDK 接口:Android 中私有或隐藏的 hidden api 接口,这些接口方法可能在未来版本中随时可变


为最大程度地降低非 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 框架软件包索引中正式记录、受支持并且可以自由使用的接口。 |


如何确定我当前使用的接口属于哪个名单?


  1. 官方给出了文件下载地址,可以到这里下载:[确定接口属于哪个名单](


)


  1. 可以参考这里:[Android 12 中有关限制非 SDK 接口的更新](


)


  1. 可以在 FrameWork 源码中搜索hiddenapi关键字,搜索结果中的hiddenapi-force-blacklist.txthiddenapi-light-greylist.txt 就是黑名单和灰名单列表,推荐 [Android Source](


) 这个网站可在线搜索


如果用反射或者 JNI 调用了这些非 SDK 接口会导致什么影响:


| 访问方式 | 结果 |


| :-- | :-- |


| Dalvik 指令引用某个字段 | 抛出 NoSuchFieldError |

用户头像

Android架构

关注

还未添加个人签名 2021.10.31 加入

还未添加个人简介

评论

发布
暂无评论
Android 12 行为变更:适配以Android 12为目标的应用,移动应用开发就业方向