Android-AGP之手写你的第一款自定义plugin插件

何为Android Gradle Plugin(AGP)

在 Android 项目中的 build.gradle 文件中,经常可以看见一些 plugin 声明如:

plugins {
    id 'com.android.application'
	  id 'com.android.library'
}
// or
apply plugin: 'com.android.application'
apply plugin: 'com.android.library' 

其实com.android.applicationcom.android.library就是两种常引用的 gradle 插件。com.android.application 是用来构建 apk 的 gradle 插件;com.android.library 是用来构建 Android Library 的 gradle 插件。

Gradle 作为 Android 官方推荐的构建工具,可以灵活的管理依赖与构建过程,同时提供了强大的插件体系,可以很方便的自定义插件以实现各种自定义的扩展功能。

何为Gradle

Gradle 是为多项目构建而设计的自动化构建工具。主要通过 groovy 或 kotlin 来编写构建脚本。

主要用来处理:

  • 自动处理包依赖关系
  • 自动处理部署问题

过去 Java 开发者常用 Maven 和 Ant 等工具进行封装布署的自动化,或是两者兼用,不过这两个包彼此有优缺点:

如果频繁改变相依包版本,使用 Ant 相当麻烦;如果琐碎工作很多,Maven 功能不足;而且两者都使用 XML 描述,相当不利于设计 if、switch 等判断式,即使写了可读性也不佳;而 Gradle 改良了过去 Maven、Ant 带给开发者的问题,成为 Android Studio 内置的构建工具。

官方文档:What is Gradle?

手写你的Gradle插件

新建plugin module

新建Gradle插件需要县新建一个普通的Android Library Module,再手动修改成gradle plugin module。

如何将Android Library修改成Gradle Plugin Library呢?

  1. 将src/main下的目录全删除
  2. 将build.gradle文件内容删除,并添加两行
apply plugin: 'groovy'
apply plugin: 'kotlin'

这里常用的DSL 语言有groovy或者kotlin,若只想用groovy开发插件,可不添加kotlin。本文主要以kotlin方式介绍写法。

  1. 在src/main下新建两个目录:kotlin和resources/META-INF/gradle-plugins

kotlin下放的是源代码,resources下是资源文件。(注意:采用groovy方式写plugin,此处第一个目录写成groovy)

这样就完成了module的改造。改造后的工程目录结构:

自定义Gradle Plugin
在pluginlib中的build.gradle中添加依赖:

//gradle 开发 sdk 依赖
dependencies {
    implementation gradleApi()
    implementation localGroovy()

    //noinspection GradleDependency
    implementation 'org.ow2.asm:asm:7.1'
    //noinspection GradleDependency
    implementation 'org.ow2.asm:asm-util:7.1'
    //noinspection GradleDependency
    implementation 'org.ow2.asm:asm-commons:7.1'
    implementation 'com.android.tools.build:gradle:4.1.3'
    implementation 'cn.quinnchen.hunter:hunter-transform:1.2.1'
}

重要的是gradleApi()localGroovy(),下面的几行是该plugin项目中引用到的几个关于项目的依赖。

接着,在src/main/groovy下新建包名(比如com.lucas.networkviewer),至此,可以再该目录下写自己的plugin插件的相关逻辑代码了。

继承Plugin类

插件类必须实现Plugin接口,并重写apply方法:

groovy版本:

package com.lucas.networkviewer.plugin

import org.gradle.api.Plugin
import org.gradle.api.Project

public class MonitorPlugin implements Plugin<Project>{

  void apply(Project project){
	  //这里写自定义插件实现逻辑
  }
  
}

kotlin版本:

package com.lucas.networkviewer.plugin

import org.gradle.api.Plugin
import org.gradle.api.Project

class MonitorPlugin : Plugin<Project> {

    override fun apply(project: Project) {
      //这里写自定义插件实现逻辑
    }
  
  }

apply方法是在apply plugin: '插件名称'这行脚本执行的时候调用。

插件实现代码如下:

package com.lucas.networkviewer.plugin

import com.android.build.gradle.AppExtension
import com.lucas.networkviewer.okhttp.OkHttpTransform
import org.gradle.api.Plugin
import org.gradle.api.Project
import java.util.*

class MonitorPlugin : Plugin<Project> {

    override fun apply(project: Project) {
      ...
        try {
            val appException: AppExtension = project.extensions.getByName("android") as AppExtension
            appException.registerTransform(OkHttpTransform(project))
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

}

这里利用registerTransform()注册了一个transform方法,它基于hunter库,实现了对okhttp网络请求的获取打印,从而实现了我们插件无缝感知任意网络请求参数的功能;详细内容可参考**NetworkViewer**,本篇仅基于该库介绍AGP的写法。

Hunter是一个框架,帮你快速开发插件,在编译过程中修改字节码,它底层基于ASMGradle Transform API 实现。仓库地址:https://github.com/Leaking/Hunter

定义插件名称

在使用插件的module中,需要在build.gradle中添加

apply plugin: '插件名称'

因此需要给我们的自定义插件定义一个名称。如何定义插件名称?

在src/main/resources/META-INF/gradle-plugins下面新建一个properties文件,文件名称就是我们的插件名称,比如monitor-plugin.properties,插件名称就是"monitor-plugin"。

文件内容中指定插件类的路径:

implementation-class=com.lucas.networkviewer.plugin.MonitorPlugin

至此,自定义插件的过程就完了。

插件上传

将插件打包出来就需要写上传代码。可以上传到本地仓库,或者远程仓库。两种方式只是上传地址不同。最终形成的插件包是一个jar文件。

参考文章

https://blog.csdn.net/m0_56144365/article/details/125154748

https://juejin.cn/post/7119083753376317448

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

许进进

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值