这个多是做为 Android 开发想要作插件开发的时候最关心的事,咱们今天看看如何去扩展 Android Gradle Plugin(如下简称 AGP)java
咱们扩展 AGP 的方式有两种:android
其中,第一种方式是咱们常见的方式,咱们常常会使用 Gradle 的 DSL 获取到全部的变体。api
applicationVariants.all { variant -> ... // Do something }
applicationVariants 是 AppExtension 里的内容,若是你想配置 Library 工程的话,就使用libraryVariants
,这两个 DSL 调用返回的是两种对象的集合,一个是 ApplicationVariant 这个类的集合,一个是 LibraryVariant 的集合,他们都继承于 BaseVariant,咱们看下两个对象的简单声明:app
public interface ApplicationVariant extends ApkVariant, TestedVariant {} public interface LibraryVariant extends BaseVariant, TestedVariant { ... }
他们统一继承于 BaseVariant(ApkVariant 继承自 BaseVariant),所以能够使用 BaseVariant 得到一些接口。
首先,咱们目前使用的版本是 AGP 3.5.x,BaseVariant 提供了一些主要的 TaskProvider,咱们能拿到相关 Variant 的 TaskProvider 作一些配置,好比咱们关心 Java 编译任务的话,能够使用getJavaCompileProvider
这个方法,拿到 TaskProvider<JavaCompile> 对象,而后使用.config
方法对这个 Task 进行调用。通常来讲,使用 BaseVariant 的方式能知足基本需求,ide
第二种方式的自定义能力更强大,同时接入会更加复杂,咱们继承了 AppPlugin 就意味着须要子类化 TaskManager 等类,这时候,若是咱们想子类化一些 AGP 提供的任务的话,用这种方式会好不少,若是咱们只想在 AGP 的任务链调用中,插入一个新任务的话,用上第一种方案比较好。gradle
若是咱们已经按照 上一个教程 构建好一个项目的话,咱们能够直接按照这个项目开始。ui
咱们这一节的目的是在咱们的 APK 中增长本身的任意。咱们须要在 apply
的回调中写逻辑,那么这个处理起来很简单,看如下示例代码:lua
public class AppPlugin implements Plugin<Project> { @Override public void apply(Project project) { project.afterEvaluate(p -> { AppExtension extension = (AppExtension)p.getExtensions().getByName("android"); Set<? extends BaseVariant> variants = extension.getApplicationVariants(); configureVariants(project, variants); }); } private void configureVariants(Project project, Set<? extends BaseVariant> variants) { variants.forEach(it -> { TaskProvider<AbstractCopyTask> task = it.getProcessJavaResourcesProvider(); configureProcessJavaResource(project, task); }); } private void configureProcessJavaResource(Project project, TaskProvider<AbstractCopyTask> taskProvider) { taskProvider.configure(task -> { task.from(project.file("gemini.txt")); }); } }
AbstractCopyTask.from 的注释以下:spa
/** * Specifies source files or directories for a copy. The given paths are evaluated as per {@link * org.gradle.api.Project#files(Object...)}. * * @param sourcePaths Paths to source files for the copy */ CopySourceSpec from(Object... sourcePaths);
那么通过以上修改,咱们就成功的往 JavaResources 任务里面新增了一个 Input 啦。赶忙使用插件
./gradlew clean install
把插件安装到本地,而后在 Android 工程中进行实践吧。
打开咱们上次建立的 Android 工程,而后在app
模块中新建刚刚须要的文件,好比我这里使用的是gemini.txt
最后,执行 Android 工程的任务:
./gradlew clean assembleDebug
完成后,咱们查看下咱们的 APK 文件:
能够看见咱们须要的文件已经打进去了。
那么对于其余 Task 咱们依然能够如法炮制,在 Variants 迭代的过程当中,咱们能先拿到这些 TaskProvider,而后调用 configure 方法,在 Task 真正被建立的时候,会调用到这些方法,咱们只要配置好正确的输入,它就会执行咱们的输出了。
咱们在前面 Gradle Builds Everything —— Task 实例 说过,Task 之间的产物,能够使用 BuildableArtifactsHolder 这个对象链接起来。
由于它是一个产物收集器,在最后 Package 任务须要打包 zip 的过程当中,都是经过这个类把全部已经打出的产物收集起来,最后变成一个 zip 包。
task.outputFile = variantScope.getArtifacts().createArtifactFile( InternalArtifactType.BUNDLE, BuildArtifactsHolder.OperationType.INITIAL, taskName, bundleName)
咱们目前只能经过继承的方式拿到 VariantScope,同时只能经过子类化 TaskManager 的方式从新编排 Configuration 过程当中的顺序(任务执行顺序咱们反而不用担忧)。经过精心编排好 BuildableArtifactsHolder 的注册顺序,Task 就自动被串联起来了。
后续可能还有关于 Task 输入和输出的高级用法,好比像前文提到的 Artifacts 之类的链接等等。不过到此为止,咱们关于自定义 Gradle 插件的基础用法和主线就全讲完啦。
欢迎关注个人公众号「TalkWithMobile」