Android 基于Gradle 7.2+,自定义插件示例(实测7.4.2也可以运行)
Posted 匆忙拥挤repeat
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android 基于Gradle 7.2+,自定义插件示例(实测7.4.2也可以运行)相关的知识,希望对你有一定的参考价值。
文章目录
起源
前几天,找到了之前从官方公众号中,收藏的文章,来简单学习一波Gradle与AGP
。
就是这一篇:Gradle 与 AGP 构建 API: 进一步完善您的插件!,文章内部会发现,这是一个小系列,共有3篇文章。
文章对应的官方代码示例 gradle-recipes
示例中用的是 gradle 7.1的alpha版本,而我这边由于工作需要,本地升级过其它项目到7.2了。
结果呢,文章中的示例代码,大部分在我这运行不起来。真是怀疑人生啊!!!
后来,由于不能运行 ProcessBuilder,升级了gradle到 7.4.2,然而,发现还是不能在task中运行ProcessBuilder 运行命令。
靠不断的猜测,查资料,遂有了本篇。
截止到目前(2022-04-27),gradle已支持到7.4.2了。
对应的 gradle plugin 版本需要是 7.2+
环境配置
工程下的 build.gradle
// all buildscript blocks must appear before any plugins blocks in the script
buildscript // gradle 构建脚本 自身,所需的
repositories
google()
mavenCentral()
dependencies
// https://mvnrepository.com/artifact/com.android.tools.build/gradle?repo=google
classpath("com.android.tools.build:gradle:7.2.0-rc01")
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.20")
// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins
id 'com.android.application' version '7.2.0-rc01' apply false
id 'com.android.library' version '7.2.0-rc01' apply false
id 'org.jetbrains.kotlin.android' version '1.6.20' apply false
//apply plugin: CustomPlugin
task clean(type: Delete)
delete rootProject.buildDir
为了编译插件,在工程下创建 buildSrc目录。
为了使用kotlin
,将build.gradle 增加.kts
后缀。
buildSrc/build.gradle.kts
plugins
`kotlin-dsl` // 使用这个后 buildSrc/src/main/kotlin 才成为源码目录
repositories // project 所需的 repos
google()
mavenCentral()
dependencies // project 所需的 depends
// 这个必须依赖,不然一些 gradle 中的api 无法使用
implementation("com.android.tools.build:gradle-api:7.1.3")
implementation(kotlin("stdlib", version = "1.6.20"))
// val ga = gradleApi() // 暂没看出来有什么作用
// print: " gradle 2api: null unspecified null "
// println("gradle api: $ga.group $ga.name $ga.version")
插件中增加变体variant(示例)
什么是变体,其实就是 android 中配置的 buildType 。
也是,如下图的东西
示例中,会增加一个 staging的变体。通过插件来完成。
代码不复杂,直接贴了
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.kotlin.dsl.register
import com.android.build.api.variant.ApplicationAndroidComponentsExtension
class CustomPlugin : Plugin<Project>
// 在哪里 apply plugin,那里所属的项目或模块就是这个 project 对象
override fun apply(project: Project)
addVariant(project, "staging")
// 添加构建变体
private fun addVariant(project: Project, variantName: String)
val extension = project.extensions.getByName(
"androidComponents"
) as ApplicationAndroidComponentsExtension // android应用组件扩展
// finalizeDsl, 在 DSL 对象应用于 Variant 创建前对它们进行修改
// 在阶段结束时,AGP 将会锁定 DSL 对象,这样它们就无法再被更改
extension.finalizeDsl ext->
println("finalizeDsl")
ext.buildTypes.create(variantName).let buildType ->
buildType.initWith(ext.buildTypes.getByName("debug"))
buildType.manifestPlaceholders["hostName"] = "example.com"
buildType.applicationIdSuffix = ".debug$variantName"
buildType.isDebuggable = true
buildType.isShrinkResources = false // 是否压缩资源
buildType.isMinifyEnabled = false // 是否混淆
// 在每个变体锁定之前
extension.beforeVariants variantBuilder ->
println("beforeVariants $variantBuilder.name")
if (variantBuilder.name == variantName)
variantBuilder.enableUnitTest = false
variantBuilder.minSdk = 23
在android application 模块的 build.gradle.kts 中应用 插件:
apply<CustomPlugin>()
然后在命令行执行命令
./gradlew :app:compileStagingSources
输出:
finalizeDsl
beforeVariants debug
beforeVariants release
beforeVariants staging
创建变体还有一些简单的方式,我的示例中,试了 “构建变体,方式1、2、3” ,就定义在 app/build.gradle.kts 中。
插件中修改manifest的version code值(示例)
这个示例,用到了 task,还是一个task套另一个task。还有文件输出与输入,manifest读取与合并等。
本来官方的示例,是以读取 git commint-id的 short 的 sha-1值 ,来改写 androidmanifest 中的 version code值。结果,并不能运行那段命令代码,搜索了一堆资料,也没搞定,放弃了。看了官方的示例,把那段也注释掉了,真有意思,哈哈。 所以也和他们一样,简单向文件内写入个数字。
GitVersionTask
package gitversion
import org.gradle.api.DefaultTask
import org.gradle.api.file.RegularFileProperty
import org.gradle.api.tasks.OutputFile
import org.gradle.api.tasks.TaskAction
import java.io.BufferedReader
import java.io.InputStreamReader
abstract class GitVersionTask : DefaultTask()
// RegularFileProperty, 表示某个可配置的常规文件位置,其值是可变的。
@get:OutputFile
abstract val gitVersionOutputFile: RegularFileProperty
@TaskAction
fun taskAction()
// 向文件内写入字符串
gitVersionOutputFile.get().asFile.writeText("3234")
ManifestTransformerTask
package gitversion
import org.gradle.api.DefaultTask
import org.gradle.api.file.RegularFileProperty
import org.gradle.api.tasks.InputFile
import org.gradle.api.tasks.OutputFile
import org.gradle.api.tasks.TaskAction
abstract class ManifestTransformerTask: DefaultTask()
@get:InputFile
abstract val gitInfoFile: RegularFileProperty
@get:InputFile
abstract val mergedManifest: RegularFileProperty
@get:OutputFile
abstract val updatedManifest: RegularFileProperty
@TaskAction
fun taskAction()
val gitVersion = gitInfoFile.get().asFile.readText()
var manifest = mergedManifest.asFile.get().readText()
manifest = manifest.replace(
"android:versionCode=\\"1\\"",
"android:versionCode=\\"$gitVersion\\""
)
// 先 get或先 asFile,都可以的,最终都是 File 对象
// updatedManifest.get().asFile.writeText(manifest)
updatedManifest.asFile.get().writeText(manifest)
@get:InputFile 用于读取数据
@get:OutputFile 用于写入数据
GitVersionPlugin
package gitversion
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.kotlin.dsl.register
import java.io.File
import com.android.build.api.variant.AndroidComponentsExtension
import org.gradle.api.tasks.TaskProvider
import org.gradle.kotlin.dsl.getByType
import com.android.build.api.artifact.SingleArtifact
class GitVersionPlugin: Plugin<Project>
override fun apply(project: Project)
// ./gradlew :app:gitVersionProvider
val gitVersionProvider = project.tasks.register<GitVersionTask>("gitVersionProvider")
// 对输出文件属性赋值一个文件对象 app/build/intermediates/gitVersionProvider/output
gitVersionOutputFile.set(File(project.buildDir, "intermediates/gitVersionProvider/output"))
outputs.upToDateWhen false // 将 upToDateWhen 设置为 false,这样此 Task 前一次执行的输出就不会被复用
val androidComponents = project.extensions.getByType(
AndroidComponentsExtension::class
)
androidComponents.onVariants variant ->
// staging/debug/release ManifestUpdater, $ ./gradlew :app:stagingManifestUpdater
// 输出文件位置:app/build/intermediates/merged_manifest/staging/[build variant]ManifestUpdater/AndroidManifest.xml
val manifestUpdater: TaskProvider<ManifestTransformerTask> = project.tasks.register<ManifestTransformerTask>(variant.name + "ManifestUpdater")
// 设置输入(对 ManifestTransformerTask来说,是输入),输入的是 GitVersionTask 的输出 gitVersionOutputFile
gitInfoFile.set(gitVersionProvider.get().gitVersionOutputFile)
// gitInfoFile.set(gitVersionProvider.flatMap
// it.gitVersionOutputFile
// )
variant.artifacts.use(manifestUpdater)
.wiredWithFiles(ManifestTransformerTask::mergedManifest, ManifestTransformerTask::updatedManifest)
.toTransform(SingleArtifact.MERGED_MANIFEST)
/*
* GitVersionPlugin, 注册 []ManifestUpdater 任务,其依赖了 ManifestTransformerTask。
*
* 当执行 ./gradlew :app:stagingManifestUpdater;
* 发现 其依赖了 gitVersionProvider 的 GitVersionTask;
* GitVersionTask 输出文本,并创建文件到 app/build/intermediates/gitVersionProvider/output;
* manifestUpdater 的 ManifestTransformerTask, 读取 gitVersion 文本;
* 在 manifest 文件中替换文本,得到了 app/build/intermediates/merged_manifest/staging/[build variant]ManifestUpdater/AndroidManifest.xml
*/
有意思的是,AS编译器内好几个地方报红,但运行是正常的。
在android application 模块的 build.gradle.kts 中应用 插件:
apply<gitversion.GitVersionPlugin>()
然后在命令行执行命令
./gradlew :app:stagingManifestUpdater
最终生成:
app/build/intermediates/merged_manifest/staging/stagingManifestUpdater/AndroidManifest.xml
试了,对 app项目打了个包,发现 version code 已等于 3234了
示例源码
以上内容,对应于今天以前的提交记录。
补更: 神奇了,发现 加一段代码后, ProcessBuilder 又能运行了。
对应 git commint:processBuilder 重定错误输出流后,可以执行命令了
// 代码运行这个命令,会提示 is not a git command 。 而单独放到命令行运行,是可以的。真晕
// val processBuilder = ProcessBuilder(“git”, “rev-parse --short HEAD”)
// 这个可以正常运行
val processBuilder = ProcessBuilder(“git”, “–version”)
// 如果此属性为true,则由该对象的start()方法随后启动的子进程生成的任何错误输出将与标准输出合并,
// 以便可以使用Process.getInputStream()方法读取它们。初始值为false
processBuilder.redirectErrorStream(true)
val process = processBuilder.start()
以上是关于Android 基于Gradle 7.2+,自定义插件示例(实测7.4.2也可以运行)的主要内容,如果未能解决你的问题,请参考以下文章
Android 基于Gradle 7.4.2,自定义插件示例
Android Gradle 插件Gradle 自定义 Plugin 插件 ③ ( 自定义插件作用 | Android Gradle 插件的扩展 | 自定义 Extension 扩展 )