Android 12 行为变更:适配以Android 12为目标的应用

以不安全的方式启动嵌套 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 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. 官方给出了文件下载地址,可以到这里下载:确定接口属于哪个名单

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

  3. 可以在FrameWork源码中搜索hiddenapi关键字,搜索结果中的hiddenapi-force-blacklist.txthiddenapi-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) 的应用。

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

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

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

b. 重新编译。

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

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

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

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

SameSite Cookie 行为将被应用于 WebView


什么是 SameSite Cookie

可参考以下文章了解:

CookieSameSite 属性决定了它是可以与任何请求一起发送,还是只能与同站点请求一起发送。Android 12 中的 WebView 基础版本包含以下隐私保护方面的变更,旨在改善对第三方 Cookie 的默认处理方式,并帮助防止意外跨站点共享:

  • 没有 SameSite 属性的 Cookie 被视为 SameSite=Lax

  • 带有 SameSite=NoneCookie 还必须指定 Secure 属性,这意味着它们需要安全的上下文,并应通过 HTTPS 发送。

  • 站点的 HTTP 版本和 HTTPS 版本之间的链接现在被视为跨站点请求,因此除非将 Cookie 正确标记为 SameSite=None; Secure,否则 Cookie 不会被发送。

对于开发者而言,一般指导意见是识别关键用户流中的跨站点 Cookie 依赖项,并确保在需要时使用适当的值显式设置 SameSite 属性。您必须显式指定允许在不同网站上运行的 Cookie,或适用于从 HTTP 切换到 HTTPS 进行同站点导航的 Cookie

adb 备份限制


先自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《Android移动开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

img

img

img

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频

如果你觉得这些内容对你有帮助,可以扫码领取!!!!

最后

**一个零基础的新人,我认为坚持是最最重要的。**我的很多朋友都找我来学习过,我也很用心的教他们,可是不到一个月就坚持不下来了。我认为他们坚持不下来有两点主要原因:

他们打算入行不是因为兴趣,而是因为所谓的IT行业工资高,或者说完全对未来没有任何规划。

刚开始学的时候确实很枯燥,这确实对你是个考验,所以说坚持下来也很不容易,但是如果你有兴趣就不会认为这是累,不会认为这很枯燥,总之还是贵在坚持。

技术提升遇到瓶颈了?缺高级Android进阶视频学习提升自己吗?还有大量大厂面试题为你面试做准备!

提升自己去挑战一下BAT面试难关吧

对于很多Android工程师而言,想要提升技能,往往是自己摸索成长,不成体系的学习效果低效漫长且无助。整理的这些知识图谱希望对Android开发的朋友们有所参考以及少走弯路,本文的重点是你有没有收获与成长,其余的都不重要,希望读者们能谨记这一点。

不论遇到什么困难,都不应该成为我们放弃的理由!

如果有什么疑问的可以直接私我,我尽自己最大力量帮助你!

最后祝各位新人都能坚持下来,学有所成。
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》点击传送门,即可免费领取!

链图片转存中…(img-7zZ7JGGN-1711261507067)]

对于很多Android工程师而言,想要提升技能,往往是自己摸索成长,不成体系的学习效果低效漫长且无助。整理的这些知识图谱希望对Android开发的朋友们有所参考以及少走弯路,本文的重点是你有没有收获与成长,其余的都不重要,希望读者们能谨记这一点。

不论遇到什么困难,都不应该成为我们放弃的理由!

如果有什么疑问的可以直接私我,我尽自己最大力量帮助你!

最后祝各位新人都能坚持下来,学有所成。
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》点击传送门,即可免费领取!

  • 28
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android 12 中,由于安全性的考虑,应用程序访问本地文件系统的方式发生了变化。从 Android 12 开始,应用程序将无法访问 `file:///android_asset/` 目录。相反,您应该使用 `content://` URI 或将文件复制到应用程序专用目录中的 `files/` 目录。 以下是一些用于 Android 12 的解决方案: 1. 使用 `AssetManager` 类来获取 `assets` 目录中的文件。例如,您可以使用以下代码从 `assets` 目录中读取文本文件: ``` try { InputStream inputStream = getAssets().open("filename.txt"); BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); String line; while ((line = bufferedReader.readLine()) != null) { // process the line } bufferedReader.close(); } catch (IOException e) { e.printStackTrace(); } ``` 2. 将文件复制到应用程序专用目录中的 `files/` 目录,并使用 `FileProvider` 类来生成 `content://` URI。例如,您可以使用以下代码将文件复制到 `files/` 目录: ``` try { InputStream inputStream = getAssets().open("filename.txt"); FileOutputStream outputStream = openFileOutput("filename.txt", Context.MODE_PRIVATE); byte[] buffer = new byte[1024]; int length; while ((length = inputStream.read(buffer)) > 0) { outputStream.write(buffer, 0, length); } outputStream.close(); inputStream.close(); } catch (IOException e) { e.printStackTrace(); } ``` 然后,您可以使用以下代码生成 `content://` URI: ``` File file = new File(getFilesDir(), "filename.txt"); Uri contentUri = FileProvider.getUriForFile(this, "your.package.name.fileprovider", file); ``` 在此示例中,`your.package.name` 应该替换为您的应用程序的包名。 请注意,如果您的应用程序需要访问其他应用程序的文件,则需要使用 `ACTION_OPEN_DOCUMENT` 或 `ACTION_CREATE_DOCUMENT` 操作来请求用户授权。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值