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

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: 从 Android12 开始,如果我们的 tagSdk >=31, 即以 Android 12 或更高版本为目标平台时,且包含使用 intent 过滤器的 activity、服务或广播接收器,则必须为这些应用组件显式声明 android:exported 属性。

📚 背景

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 以下

buildscript {
  repositories {
      // ...
      maven { url 'https://jitpack.io' }
  }
}

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

settings.gradle

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

Gradle

dependencies {
      classpath 'com.github.xiachufang:manifest-exported-plugin:1.0.6'
}

2. 添加插件

在主app Model中添加:

apply plugin: 'com.xiachufang.manifest.exported'
• 1

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

3. 参数说明

app-build.gradle

apply plugin: 'com.xiachufang.manifest.exported'
...
exported {
    actionRules = ["android.intent.action.MAIN"]
    enableMainManifest false
    logOutPath "自定义的日志输出目录,如果不存在会自动创建"
}
  • logOutPath 日志输出目录,默认 app/build/exported/outManifest.md
  • actionRules action的匹配项(数组), 如:
<activity android:name=".simple.MainActivity" >
      <intent-filter>
          // action 对应的 android:name 可与actionRules 数组任意一项匹配 ,并且当前没有配置exported
            // -> yes: android:exported="true"
            // -> no: android:exported="false"
        <action android:name="android.intent.action.MAIN"/>
        <category android:name="android.intent.category.LAUNCHER"/>
      </intent-filter>
</activity>

enableMainManifest 是否对主 model-AndroidManifest 进行修改

对于 主model ,属于业务可控的,建议开发者自行调整。

插件默认不会对主 model-AndroidManifest 进行修改,如果发现可用匹配上述规则的,即会进行修正。

开发者可根据日志中的提示,进行修改。

📰 相关截图说明

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

💭 注意事项

对于主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. 判断是不是 activity、services、broadcasts 以及是不是包含了
  2. 判断 exported 是否为 null
  3. 判断 action 是否匹配我们的条件

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

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
目录
相关文章
|
1月前
|
SQL 人工智能 Dart
Android Studio的插件生态非常丰富
Android Studio的插件生态非常丰富
66 1
|
7月前
|
缓存 程序员 定位技术
Android Studio 插件,那些被大厂优化的程序员们
Android Studio 插件,那些被大厂优化的程序员们
|
7月前
|
Web App开发 移动开发 小程序
"项目中mpaas升级到10.2.3 适配Android 14之后 app中的H5以及小程序都访问不了,
"项目中mpaas升级到10.2.3 适配Android 14之后 app中的H5以及小程序都访问不了,显示“网络不给力,请稍后再试”,预发内网版本不能使用,线上版本可以正常使用,这个是什么原因啊,是某些参数没有配置吗,还是说是一些参数改错了?
118 2
|
人工智能 移动开发 Java
Android Studio插件版本与Gradle 版本对应关系
Android Studio插件版本与Gradle 版本对应关系
2576 0
Android Studio插件版本与Gradle 版本对应关系
|
Android开发
Android 全屏适配刘海机型
Android 全屏适配刘海机型
197 0
|
2月前
|
Android开发
我是一位Android工程师,用通义灵码的AS插件做开发工作助手,对比之前没有灵码,现在提效了60%
我是一位Android工程师,用通义灵码的AS插件做开发工作助手,对比之前没有灵码,现在提效了60%
80 0
|
3月前
|
调度 Android开发 UED
Android经典实战之Android 14前台服务适配
本文介绍了在Android 14中适配前台服务的关键步骤与最佳实践,包括指定服务类型、请求权限、优化用户体验及使用WorkManager等。通过遵循这些指南,确保应用在新系统上顺畅运行并提升用户体验。
276 6
|
5月前
|
IDE API Android开发
安卓与iOS开发环境的差异及适配策略
在移动应用开发的广阔舞台上,Android和iOS两大操作系统各据一方,各自拥有独特的开发环境和工具集。本文旨在深入探讨这两个平台在开发环境上的关键差异,并提供有效的适配策略,帮助开发者优化跨平台开发流程。通过比较Android的Java/Kotlin和iOS的Swift/Objective-C语言特性、IDE的选择、以及API和系统服务的访问方式,本文揭示了两个操作系统在开发实践中的主要分歧点,并提出了一套实用的适配方法,以期为移动开发者提供指导和启示。
|
4月前
|
安全 Java Android开发
Android 14适配Google play截止时间临近,适配注意点和经验
本文介绍了Android 14带来的关键更新,包括性能优化、定制化体验、多语言支持、多媒体与图形增强等功能。此外,还强调了适配时的重要事项,如targetSdkVersion升级、前台服务类型声明、蓝牙权限变更等,以及安全性与用户体验方面的改进。开发者需按官方指南更新应用,以充分利用新特性并确保兼容性和安全性。
319 0
|
7月前
|
编解码 人工智能 测试技术
安卓适配性策略:确保应用在不同设备上的兼容性
【4月更文挑战第13天】本文探讨了提升安卓应用兼容性的策略,包括理解平台碎片化、设计响应式UI(使用dp单位,考虑横竖屏)、利用Android SDK的兼容工具(支持库、资源限定符)、编写兼容性代码(运行时权限、设备特性检查)以及优化性能以适应低端设备。适配性是安卓开发的关键,通过这些方法可确保应用在多样化设备上提供一致体验。未来,自动化测试和AI将助力应对设备碎片化挑战。
751 4