前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >写了一个适配 Android12-exported 的小插件

写了一个适配 Android12-exported 的小插件

作者头像
Petterp
发布2022-06-30 14:51:30
7720
发布2022-06-30 14:51:30
举报
文章被收录于专栏:JetPack

📚 背景

Android12 开始,如果我们的 tagSdk >=31, 即以 Android 12 或更高版本为目标平台时,且包含使用 intent 过滤器activity服务广播接收器,则必须为这些应用组件显式声明 android:exported 属性。

如果你满足上述条件,并且 tagSdk>=31 ,而未声明 exported 属性,则在不同的 Agp 版本有着以下不同提醒方式:

  • Agp7.0 及以上,在 build 时会出现下面的报错: Manifest merger failed : android:exported needs to be explicitly specified for . Apps targeting Android 12 and higher are required to specify an explicit value for android:exported when the corresponding component has an intent filter defined. See https://developer.android.com/guide/topics/manifest/activity-element#exported for details
  • Agp7.0以下 则并不会在编译时报错,而是在安装后打开相关页面时报错,相应的,Android Studio 会以 ⚠️ 的样式提醒你添加 exported

恰好最近也正好在做相关的适配,于是就查了下,发现了恋猫的小郭大佬写的这样一篇文章,Android12的适配,其中关于 exported 部分,比较简单实用,但相对来说,存在版本差异,真实使用起来还需要再改一下。本文就是针对其做的一个完善,并将其抽离成了一个小插件,以便更好的复用。

💬 插件简介

manifest-exported-plugin

一个用于快速适配 Manifest-exported 的小插件,通过修改 manifest 文件,从而做到适配。

👨‍💻‍ 使用方式

1. 添加jitpack

build.gradle

Gradle7.0 以下

代码语言:javascript
复制
buildscript {
	repositories {
			// ...
			maven { url 'https://jitpack.io' }
	}
}

Gradle7.0+ ,并且已经对依赖方式进行过调整,则可能需要添加到如下位置:

settings.gradle pluginManagement { repositories { //... maven { url 'https://jitpack.io' } } }

Gradle
代码语言:javascript
复制
dependencies {
      classpath 'com.github.xiachufang:manifest-exported-plugin:1.0.6'
}

2. 添加插件

在主app Model中添加:

代码语言:javascript
复制
apply plugin: 'com.xiachufang.manifest.exported'

或 plugins { id 'com.xiachufang.manifest.exported' }

3. 参数说明

app-build.gradle

代码语言:javascript
复制
apply plugin: 'com.xiachufang.manifest.exported'
...
  
exported {
    actionRules = ["android.intent.action.MAIN"]
    enableMainManifest false
    logOutPath "自定义的日志输出目录,如果不存在会自动创建"
}

📰 相关截图说明

默认情况下插件的输出目录如下所示,主 model/build/exportred/outManifestLog.md,默认日志如下:

image-20220627110207568
image-20220627110207568

💭 注意事项

对于主model下的 manifest ,默认不进行适配(可开关 enableManifest ),会通过日志进行输出,建议大家自行对比调整。

为什么默认不对主 model 进行适配?

  • 对于业务 model ,我们建议开发者自行适配,这属于我们可控范围,适配来说主要就是为了不可控的,即第三方 aar
  • 修改之后,会影响原有的 manifest 代码风格,需要重新格式化一下,相比默认的,增加了不少空格,暂时不知道怎么解决。

🤔 原理解析

通过插入到 processxxxMainManifest Task之前,提前对manifest进行修改。

为什么不插入到 processxxxManifest ,这样不就不用操作 manifest 源文件了吗,只需要对build下的 mergeManifest 进行操作不就行了?

首先说明这两者的顺序:

  1. processxxxMainManifest
  2. processxxxManifest

我们都知道,build 时会将所有 aar 里的 manifest 的全部进行合并,如果有异常会进行报错。

但在不同的 AGP 版本,它们的检测时机不一样

通常情况下,在 processxxxMainManifest 结束后,我们就可以拿到已经合并好的 manifest 文件,此时就可以直接进行更改适配。

在agp7.0这个思路没有问题,因为 processxxxMainManifest 里面不会去检测 manifest 是否合并成功,而会在 processxxxManifest 去检测。

但在agp7.0以上,因为会先去检测 manifest 是否合并成功,这就导致我们后续的任务没法正常执行,所以我们没有办法将任务插入到 processxxxMainManifest 之后,只能在其之前执行,所以此时我们只能去修改 manifest 源文件从而做到适配。

具体的适配上也比较简单,我们使用 XmlParser 拿到manifest里的节点,通过如下几个条件层层判断,最终完成适配:

  1. 判断是不是 activityservicesbroadcasts 以及是不是包含了
  2. 判断 exported 是否为 null
  3. 判断 action 是否匹配我们的条件

需要注意的是,在 Agp4.2 && gradle6.7 及以下时,tagSdk31,就算你不去写 exported ,编译也不会报错,但此时运行在Android12 手机上时,就会出现相应的报错提示。所以在写插件时我们需要对这种情况进行容错,对于未适配的 主mainManifest ,进行报错以便提醒用户。

🔖 感谢

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-06-27,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 📚 背景
  • 💬 插件简介
  • 👨‍💻‍ 使用方式
    • 1. 添加jitpack
      • Gradle
    • 2. 添加插件
      • 3. 参数说明
      • 📰 相关截图说明
      • 💭 注意事项
      • 🤔 原理解析
      • 🔖 感谢
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档