本次升级是从之前的 AGP7+ 升级到 AGP8+
1. 升级 AGP
- Android gradle plugin version:
7.4.2 ——> 8.3.2
- Gradle version:
7.5 ——> 8.5
2. 同步报错
2.1 未指定命名空间
根据给出的文档链接设置命名空间:设置命名空间
命名空间是需要再 application
模块设置的,我们的插件是 groovy
库模块不需要在 build.gradle 配置
2.2 不支持 Transform
TransformManager 被移除
但这不是主要的
不妨把它抽出来,如下所示,编译通过了
迁移 Transform
重要的是:API 'android.registerTransform' is removed.
- Transform 类弃用:计划在 Android Gradle plugin 9.0 中删除
- Extension registerTransform:Transform API 计划在 Android Gradle 插件 8.0 中移除
在 AGP 8.0 中已经删除了 Transform API的支持,所以要迁移 Transform
跟进官方文档:移除了 Transform API 进行迁移适配
当前我需要适配的功能部分是 支持转换字节码,也就是我们以前用来处理字节码部分的 Transform,很多时候是我们使用的 ASM + Transform
处理 class 文件
官方:ASM 转换例子
- 官方提供的 Demo:Github 访问:BuildSrc/testAsmTransformApi
如何开始适配呢?
我的插件之前都是用 java
写的,但是 AGP8+ 上 AsmTransformApi 是完全基于 Kotlin
实现的
所以你不得不把你的插件也使用 Kotlin 实现,麻烦点在这,你要重写插件,谁愿意挖一坨屎山呢?
3. AGP8+ Plugin Demo
3.1 创建插件 module
字节码转换 AGP8+ 只有 Kotlin 实现,一定要选择 Kotlin + Kotlin DSL
3.2 配置 build.gradle
- 引入 groovy-gradle-plugin(Gradle API)
- 引入 maven-publish 发布版本
- 配置 gradlePlugin 指定插件 ID + 实现类
版本一:后面适配插件引入,调整 Maven 发布有版本二
plugins {
alias(libs.plugins.jetbrains.kotlin.jvm)
//一定要配置这个,否则找不到 org.gradle.api.Plugin 等
id("groovy-gradle-plugin")
//发布版本
id("maven-publish")
}
java {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
kotlin {
compilerOptions {
jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17
}
}
dependencies {
//一定要引入这个,否则找不到一些 build-api
//com.android.build.api.variant.AndroidComponentsExtension
//com.android.build.api.instrumentation.AsmClassVisitorFactory
compileOnly(libs.build.gradle.api)
}
//指定插件 ID 和入口
gradlePlugin {
plugins {
create("Check") {
id = "com.vimedia.plugin"
implementationClass = "com.vimedia.plugin.Check"
}
}
}
publishing {
publications {
//发布到本地仓库
create<MavenPublication>("release") {
from(components["kotlin"])
groupId = "com.vimedia.plugin"
artifactId = "check"
version = "1.0.0.2.1"
}
}
}
3.3 插件版本依赖错误
我是这样声明的
[versions]
check = "1.0.0.4"
[plugins]
check = { id = "com.vimedia.plugin", version.ref = "check" }
项目 build.gradle.kts 下这样应用
plugins {
alias(libs.plugins.check) apply false
}
当我同步时却找不到插件
报错 Plugin Repositories (could not resolve plugin artifact ‘com.vimedia.plugin:com.vimedia.plugin.gradle.plugin:1.0.0.4’)
我的插件明明是 com.vimedia.plugin:check1.0.0.4,怎么就变成com.vimedia.plugin:com.vimedia.plugin.gradle.plugin:1.0.0.4
多了 com.vimedia.plugin.gradle.plugin,artifactId
check 哪去了
我本地发布的版本似乎也没有问题啊
打印日志
输出插件依赖是这样:com.vimedia.plugin:1.0.0.5
肯定不对,预期是 com.vimedia.plugin:check:1.0.0.5
check-plugin = { id = "com.vimedia.plugin", version.ref = "check" }
alias(libs.plugins.check.plugin) apply false
输出:
模块依赖=== com.vimedia.plugin:1.0.0.5
报错:
- Gradle Core Plugins (plugin is not in 'org.gradle' namespace)
- Included Builds (No included builds contain this plugin)
- Plugin Repositories (could not resolve plugin artifact
- 'com.vimedia.plugin:com.vimedia.plugin.gradle.plugin:1.0.0.5')
尝试添加 check,也不对,不允许特殊字符
check-plugin = { id = "com.vimedia.plugin:check", version.ref = "check" }
alias(libs.plugins.check.plugin) apply false
输出:
模块依赖=== com.vimedia.plugin:check:1.0.0.5
报错:
plugin id 'com.vimedia.plugin:check' is invalid: Plugin id contains invalid char ':'
(only ASCII alphanumeric characters, '.', '_' and '-' characters are valid)
3.4. 向困难妥协
既然这样写:check-plugin = { id = "com.vimedia.plugin", version.ref = "check" }
它依赖的是:com.vimedia.plugin:com.vimedia.plugin.gradle.plugin:1.0.0.4
那我发布版本便满足他
publishing {
publications {
create<MavenPublication>("release") {
from(components["kotlin"])
groupId = "com.vimedia.plugin"
//临时处理,后续回头再看如何解决
//因为暂时搞不明白拼接的这个 .gradle.plugin 是什么
artifactId = "com.vimedia.plugin.gradle.plugin"
version = "1.0.0.6"
}
}
repositories {
mavenLocal()
}
}
3.4 应用插件
在app/build.gradle.kts
下配置
方式一:
import com.vimedia.plugin.Check
//在 agp7+ 等低版本是这样的: apply plugin: 'com.vimedia.plugin'
//现在看起来跟以前比别扭多了
apply<Check>()
方式二:
plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.jetbrains.kotlin.android)
//插件创建时填写的 ID
id("com.vimedia.plugin")
}
//创建插件名称、指定插件ID、版本等
gradlePlugin {
plugins {
create("Check") {
//1、同 agp7+ 应用插件的 ID,apply plugin: 'com.vimedia.plugin'
//2、会再发布一个 id + gradle.plugin 的 pom
id = GROUP_ID
group = GROUP_ID
version = VERSION
implementationClass = "Check"
}
}
}
官方文档(插件部分): Understanding Plugins
3.5 不再妥协
3.4. 向困难妥协 我们使用了临时方案
经过不断地调试,多次给插件创建 plugins create
赋予不同的值:
- id:插件 ID
- group:插件 pom group
- version:插件版本
对比 publishing create
赋予不同的值:
- groupId:插件 pom group
- version:插件版本
发现:
1. 如果这两个配置的group、version 不一样,那么会生成两个路径的 pom
2. plugins create id 是会拼接 .gradle.plugin
生成新的路径作为 pom
大概能猜到,这个带.gradle.plugin
生成新的 pom 可能是高 AGP 版本为了更好的版本管理
为了能够使插件引入check-plugin = { id = "com.vimedia.plugin", version.ref = "checkVersion" }
正常使用和 Maven 发布简化
我们统一插件创建和 Maven 发布
的 pom 信息 groupId 和 version
plugins {
alias(libs.plugins.jetbrains.kotlin.jvm)
//一定要配置这个,否则找不到 org.gradle.api.Plugin 等
id("groovy-gradle-plugin")
id("java-gradle-plugin")
//发布版本
id("maven-publish")
}
java {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
kotlin {
compilerOptions {
jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17
}
}
dependencies {
//一定要引入这个,否则找不到一些 build-api
//com.android.build.api.variant.AndroidComponentsExtension
//com.android.build.api.instrumentation.AsmClassVisitorFactory
compileOnly(libs.build.gradle.api)
}
val ARTIFACT_ID = "check"
val GROUP_ID = "com.vimedia.plugin"
val VERSION = "1.0.0.9"
//指定插件 ID 和入口
gradlePlugin {
plugins {
create("Check") {
//1、同 agp7+ 应用插件的 ID,apply plugin: 'com.vimedia.plugin'
//2、会再发布一个 id + gradle.plugin 的 pom
id = GROUP_ID
group = GROUP_ID
version = VERSION
implementationClass = "com.vimedia.plugin.Check"
}
}
}
//插件发布
publishing {
publications {
//发布到本地仓库
create<MavenPublication>("release") {
from(components["kotlin"])
groupId = GROUP_ID
version = VERSION
artifactId = ARTIFACT_ID
}
}
repositories {
mavenLocal()
}
}