【Android】自定义Gradle插件——实现云端配置项目依赖

本文详细介绍自定义Gradle插件的方法,包括插件的定义、打包至本地或Maven仓库,以及如何在项目中使用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

自定义Gradle插件是一个很常见的操作,Gradle插件能帮我们解决很多项目打包问题、CICD问题、效率提升问题。

这篇文章讲解如何自定义一个Gradle插件,如何将插件打包上传到本地文件仓库和maven仓库,如何使用插件。笔者将结合一个案例来讲解插件插件从定义、打包到使用的全流程。这个案例实现功能是将Application Module中的dependencies{…}配置部分交给插件,在云端来管理项目的依赖。

本文主要围绕几下几个话题展开:

  • 如何自定义一个Gradle插件
  • Gradle插件打包到本地文件仓库
  • Gradle插件打包到自建maven仓库
  • 如何使用自定义的Gradle插件

Grade插件其实是一段gradle脚本,实现了Plugin类,通过apply '插件名'的方式去调用它。而且可以打包上传,复用插件代码。所以叫它插件。

Gradle插件可以用三种方式来写。

第一种方式:直接在build.gradle文件里写。

例如:

apply plugin: MyPlugin

class MyPlugin implements Plugin<Project>{
    @Override
    void apply(Project target) {
         println "Hello,Plugin"
     }
 }

这种方式的缺点是插件只对当前build script可见,其它脚本无法复用它,不能将插件打包并上传到maven。

第二种方式:创建buildSrcproject
buildSrc(名字是固定的)是rootProject的子project,它的build.gradle脚本执行优先级最高,buildScr project不需要在setting.gradle里注册。这种方式也适用于本地项目,不适用于将插件打包上传。同时它支持三种语言开发:groovy、java、kotlin。

第三种方式:创建独立的project。
这种方式好处是可以将脚本通过maven插件打包上传,供其它项目依赖。它也支持三种语言开发:groovy、java、kotlin。
下面就以这种方式为例,介绍如何自定义Gradle插件。

新建一个Project,名为GradlePluginDemo,并新增子project(library)名为pluginlib,这个project就用来编写Gradle插件。

创建Gradle Plugin Project

目前Android Studio还不支持新建Gradle Plugin Project,所以新建一个普通的Android Library Module或者Java Library,将它改造成Gradle Module。

先新建一个普通的Android Library Module,按如下操作改造成Groovy Module:

1、将src/main下的目录全删除
2、将build.gradle文件内容删除,并添加一行 apply plugin: 'groovy'
3、在src/main下新建两个目录:
(1) groovyjavakotlin 。 这里以groovy为例。
(2) resources/META-INF/gradle-plugins

groovy下放的是源代码,resources下是资源文件。

改造后的工程目录结构:

在这里插入图片描述

自定义Gradle Plugin

在pluginlib中的build.gradle中添加依赖dependencies依赖:

apply plugin: 'groovy'
dependencies{
    // gradle sdk
    implementation gradleApi()
    // groovy sdk
    implementation localGroovy()
}

在src/main/groovy下新建包名(比如com.devnn.plugin),并新建插件类,比如PluginImpl.groovy,这个类名无所谓,并不是最后插件的名字。

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

package com.devnn.plugin

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

public class PluginImpl implements Plugin<Project>{

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

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

在这里,我们要实现的功能是将app module的依赖部分写在插件里,并将插件上传到maven私有库。

插件实现代码如下:

package com.devnn.plugin

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

public class PluginImpl implements Plugin<Project>{

    void apply(Project project){
        System.out.println("========================")
        System.out.println("apply MyPlugin succeed!")
        System.out.println("========================")
        
        project.repositories{
            maven{
                //添加maven库地址
                url 'http://localhost:8081/nexus3/repository/maven-public/'
            }
        }
        
        //定义project的依赖部分
        project.dependencies {
            implementation 'androidx.appcompat:appcompat:1.0.2'
            implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
            implementation 'com.devnn.lib:lib1:1.1.5'
        }

    }
}

前三行是一个日志打印。这里有一个自定义的名为lib1的library加进了依赖。

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

apply plugin: '插件名称'

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

如何定义插件名称?

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

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

implementation-class=com.devnn.plugin.PluginImpl

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

将插件打包出来就需要写上传代码。可以上传到本地文件仓库,或者maven仓库。两种方式只是上传地址不同。最终形成的插件包是一个jar文件及及pom.xml描述文件。上传到maven仓库需要事先搭建一个maven服务器。

将插件打包并上传到本地文件仓库

如果要在本地测试gradle插件,上传到本地文件仓库是个很好的选择。

这里将本地文件仓库定义在项目根目录的plugins文件夹。此文件夹会自动生成。

本地文件仓库其实就是一个文件夹,里面存放了打包好的jar及其pom.xml,内容跟maven上是一样的,跟maven仓库的区别是仅能供本机使用,不能作为web服务器来用。

首先在pluginlib的build.gradle文件中应用maven上传插件:

apply plugin: 'maven'

然后再添加uploadArchives任务,完整内容如下。

apply plugin: 'groovy'
apply plugin: 'maven'
dependencies{
    // gradle sdk
    implementation gradleApi()
    // groovy sdk
    implementation localGroovy()
}

uploadArchives {
    repositories {
        mavenDeployer {
            pom.groupId = 'com.devnn.myplugin'//这是groudId
            pom.artifactId = 'myplugin' //这是artifactId,注意这跟gradle插件的名字是两回事,互不干扰。同一个artifactId可以包含多个插件。
            pom.version = '1.0.0'
            repository(url: uri('../plugins')) //打包到此脚本上一级目录的plugins目录下(跟pluginlib并列),目录不存在会自动创建。
        }
    }
}

这里的artifactId跟插件名称容易混淆,它们俩的名字可以相同也可以不同,并不会冲突。一个artifactId是一个依赖包,也是一个jar包,里面可能包含多个插件。就像工程根目录的build.gradle这行代码:

 dependencies {
        classpath "com.android.tools.build:gradle:3.6.2"
 }

这是gradle脚本需要依赖的插件库(jar包),它是个artifact,artifactId=gradle。这个插件库里面有多个插件比如:com.android.librarycom.android.application

这个插件jar包是作用在编译阶段,因为编译程序也是jvm在工作,需要依赖jar。跟平常使用jar包不同,平常使用的jar包作用在app运行时。

上面代码只是写了一个插件,还可以编写多个插件,在资源文件里添加新插件即可:src/main/resources/META-INF/gradle-plugins

添加uploadArchives任务后在工程根目录执行上传命令即可:
./gradlew pluginlib:uploadArchives

上传成功后就会生成新目录plugins:

在这里插入图片描述

里面就是打包后的产物。

如何使用刚刚打包好的插件呢?

使用时分两步,见以下注释。

buildscript {
    repositories {
        google()
        jcenter()
        maven{
           url uri('plugins') //1,添加插件仓库地址
        }
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.6.2'
        classpath "com.devnn.plugin:myplugin:1.0.0" //2,添加插件依赖
    }
}

第2步插件依赖就是从第1步的仓库地址中去搜索插件。

然后在gradle脚本中添加apply plugin: 'MyPlugin',实际就是在调用插件的apply方法。

将插件打包并上传到maven仓库

上传插件到maven仓库,跟上传aar/jar是一样的,在我的另一篇文章中有比较详细讲解:

将aar及其依赖aar上传至maven私有仓库

这里就简单描述一下上传脚本。

首先在pluginlib的build.gradle文件中应用maven上传插件:

apply plugin: 'maven'

添加上传脚本:

def NEXUS_REPOSITORY_URL="http://localhost:8081/nexus3/repository/maven-releases/"
def NEXUS_USERNAME="admin"
def NEXUS_PASSWORD="123456"

uploadArchives {
    repositories {
        mavenDeployer {
            pom.groupId = 'com.devnn.plugin'
            pom.artifactId = 'myplugin'
            pom.version = '1.0.0'
            repository(url: NEXUS_REPOSITORY_URL) {
                authentication(userName: NEXUS_USERNAME, password: NEXUS_PASSWORD)
            }
        }
    }
}

完整的build.gradle文件内容:

apply plugin: 'groovy'
apply plugin: 'maven'

dependencies{
    // gradle sdk
    implementation gradleApi()
    // groovy sdk
    implementation localGroovy()
}

def NEXUS_REPOSITORY_URL="http://localhost:8081/nexus3/repository/maven-releases/"
def NEXUS_USERNAME="admin"
def NEXUS_PASSWORD="123456"

uploadArchives {
    repositories {
        mavenDeployer {
            pom.groupId = 'com.devnn.plugin'
            pom.artifactId = 'myplugin'
            pom.version = '1.0.0'
            repository(url: NEXUS_REPOSITORY_URL) {
                authentication(userName: NEXUS_USERNAME, password: NEXUS_PASSWORD)
            }
        }
    }
}

可以跟上面的上传本地文件仓库的脚本对比一下,其实只是上传地址不同。

在终端中执行上传命令:

./gradlew pluginlib:uploadArchives

执行上传命令后,自定义插件类会报红,这是AS自身的问题,不要在意,删除build目录就好了。

到maven私有库上看一下刚刚上传的插件:
在这里插入图片描述
可以看到已经上传成功了。

它的pom文件内容:
在这里插入图片描述

自动完成插件更新

上面讲解了通过Gradle的uploadArchives命令上传插件到Maven仓库,这个操作可以通过Jenkins帮助我们自动完成。当更新了插件代码后,可以自动触发jenkins打包并上传插件。客户端应用的依赖部分代码(dependencies{…})就完成了云端化。

使用maven仓库中的自定义插件

在工程根目录的build.gradle文件的buildscipt添加插件所在仓库地址,并且添加插件依赖:

buildscript {
    repositories {
        google()
        jcenter()
        maven{
            url 'http://localhost:8081/nexus3/repository/maven-public/'
        }
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.6.2'
        classpath 'com.devnn.plugin:myplugin:1.0.0'
        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

在application moudle(app)中应用插件:

apply plugin: 'MyPlugin'

这样就会自动引入了这三个库:

    implementation 'androidx.appcompat:appcompat:1.0.2'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
    implementation 'com.devnn.lib:lib1:1.1.5'

application module下面没有配置自己dependencies,全部通过插件来实现。

整个过程的Demo工程源码地址:
https://github.com/devnns/GradlePluginDemo.git

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值