Android Gradle 插件开发指南

简介:

作为Android开发者,你可能见过无数个apply plugin:plugin_name,plugin_name对应着相应的插件。

例如:


apply plugin: 'com.android.application'
apply plugin: 'com.android.library'

com.android.application就对应着可以一个构建APK的Gradle插件,而com.android.library则对应着一个构建android library的插件。

Gradle插件开发支持Java、Groovy、Scala三种语言开发,Groovy用于实现与 Gradle 构建生命周期(如 task 的依赖)有关的逻辑,Java用于核心逻辑,表现为 Groovy 调用 Java 的代码。

插件的打包方式

Gradle的插件有三种打包方式,主要是按照复杂程度和可见性来划分:

类型 说明
Build script 把插件写在 build.gradle 文件中,一般用于简单的逻辑,只在该 build.gradle 文件中可见
buildSrc 项目 将插件源代码放在 rootProjectDir/buildSrc/src/main/groovy 中,只对该项目中可见,适用于逻辑较为复杂,但又不需要外部可见的插件,可以参见
独立项目 一个独立的 Groovy 和 Java 项目,可以把这个项目打包成 Jar 文件包,一个 Jar 文件包还可以包含多个插件入口,将文件包发布到托管平台上,供其他人使用。本文将着重介绍此类。

接下来我将从Build script和独立项目详细介绍。

Buid script

把插件写在build.gradle文件中,这种是最简单的插件开发方式。

下边举个例子:


build.gradle//文件名

class GreetingPluginExtension{
String message = "Hello from GreetingPlugin"
}


class GreetingPlugin implements Plugin<Project>{

@Override
void apply(Project project){

def extension = project.extensions.create('greeting',GreetingPluginExtension)

project.task('hello'){
doLast {
println extension.message
}
}
}
}

apply plugin: GreetingPlugin //应用插件,这样插件才能在gradle构建过程中生效。

build.gradle同级目录中,在命令行执行gradle greeting。则会输出以下内容:

Hello from GreetingPlugin

这个插件创建了一个名为hello的task,并在task中打印了GreetingPluginExtension#message的内容。

create的第一个参数greeting是我们自定义配置的DSL名字,第二个参数是参数类的名字。

通过greeting这个DSL这个名字,我们可以任意的改变参数类中相应字段的值。这样就带来了很大的便利。

比如我们将Android工程的app目录中经常见到build.gradle中会有


android {
compileSdkVersion 24
buildToolsVersion "24.0.3"
defaultConfig {
applicationId "com.chenenyu.plugintest"
minSdkVersion 14
targetSdkVersion 24
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}

而这些就是名为android DSL的动态参数配置。

同样,我们把刚才写的build.gradle中添加新的内容,如下:


class GreetingPluginExtension{
String message = "Hello from GreetingPlugin"
}


class GreetingPlugin implements Plugin<Project>{

@Override
void apply(Project project){

def extension = project.extensions.create('greeting',GreetingPluginExtension)

project.task('hello'){
doLast {
println extension.message
}
}
}
}

apply plugin:GreetingPlugin

greeting{
message="I am dynamic message"
}

重新执行gradle hello,则会看到以下内容:

I am dynamic message

在本小节介绍了Gradle插件的基本开发,通过继承org.gradle.api.Plugin即可简单快速的实现。同时我们通过project.extensions.create可以实现动态传参。只需要定义DSL名字和定义相应的Class,并且在DSL作用域中重新赋值。

在Gradle插件开发中,所有的插件都要继承org.gradle.api.Plugin接口,并且需要重写void apply(Project project) 方法,这个方法将会传入使用这个插件的 project 的实例,这是一个重要的 context。

独立项目插件

独立的项目可以发布到本地或者jcenter仓库中,这样就会很方便第三方集成。

通常我们可以在build.gradle中来改变APK最终输出的名字。我们换个套路,把这个功能放在插件中来完成。同时将该插件发布到本地仓库,同时在第三方APP中应用该插件。

001 创建项目

在 Android Studio 中新建 Java Library module “plugin”。

002 修改 build.gradle 文件


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

repositories {
mavenLocal()
jcenter()
}

dependencies {
compile gradleApi()
}

//publish to local directory
def versionName = "1.0.0"
group "com.demon.plugin"
version versionName

uploadArchives{ //当前项目可以发布到本地文件夹中
repositories {
mavenDeployer {
repository(url: uri('./repo')) //定义本地maven仓库的地址
}
}
}

003 修改项目文件夹

src/main 项目文件下:

 ●   移除 java 文件夹,因为在这个项目中用不到 java 代码
 ●   添加 groovy 文件夹,主要的代码文件放在这里

 ●  添加 resources 文件夹,存放用于标识 gradle 插件的 meta-data

004 建立对应文件


├── build.gradle
└── src
└── main
├── groovy
│ └── com
│ └── demon
│ └── plugin
│ ├── ApkChangeNamePlugin.groovy
└── resources
└── META-INF
└── gradle-plugins
└── apk_change_name.properties

ApkChangeNamePlugin.groovy文件内容如下:


package com.demon.plugin

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

class ApkChangeNamePlugin implements Plugin<Project>{
@Override
void apply(Project project) {

if(!project.android){
throw new IllegalStateException('Must apply \'com.android.application\' or \'com.android.library\' first!');
}

project.android.applicationVariants.all{
variant ->
variant.outputs.all{
outputFileName = "${variant.name}-${variant.versionName}.apk"
}
}
}
}

apk_change_name.properties文件内容如下:

implementation-class=com.demon.plugin.ApkChangeNamePlugin //指定实现类

注意:

 ●   groovy文件夹中的类,一定要修改成 .groovy 后缀,IDE才会正常识别。
 ●   resources/META-INF/gradle-plugins 这个文件夹结构是强制要求的,否则不能识别成插件。

●  apk_change_name.propertiesapk_change_name为插件名

005 发布插件到本地目录中

执行如下命令即可
gradle uploadArchives

则会在build.gradle的同级目中生成repo目录,里边的内容如下图:

a2bbea78171e0c87e9d601cd00a93240487505cd

Picture

006 在第三方APP中使用插件

在项目的 buildscript 添加插件作为 classpath


buildscript {
repositories {
maven{
url '/Users/demon.li/workspace/GradlePlugin/repo/'
}
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.0.1'
classpath "com.demon.plugin:plugin:1.0.0"
}
}

app module中使用插件:

apply plugin: 'apk-change-name'

在最终的apk构建后会根据variant名字和版本的不同而输出不同名称的apk。

例如最终生成:


debug-1.0.apk
release-1.0.apk

总结

就实现了在Android项目中压缩.png图片的插件。

我们在这里也用到了Groovy,如果想深入Gradle插件开发的同学可以学习一下Groovy语言的精妙。

Groovy也是借助于Java虚拟机运行的,Java虚拟机规范定义了字节码的规范。比如kotlin和Scala都是运行在Java虚拟机中的。


原文发布时间为:2018-10-29
本文作者:我是吸血鬼
本文来自云栖社区合作伙伴“ 安卓巴士Android开发者门户”,了解相关信息可以关注“ 安卓巴士Android开发者门户”。
相关文章
|
6月前
|
SQL 人工智能 移动开发
Android Studio插件版本与Gradle 版本对应关系
Android Studio插件版本与Gradle 版本对应关系
Android Studio插件版本与Gradle 版本对应关系
|
6月前
|
Java 开发工具 Android开发
Cocos Creator 2.4.6 Android Gradle 版本升级为 6.5.1(插件4.1.0)
Cocos Creator 2.4.6 Android Gradle 版本升级为 6.5.1(插件4.1.0)
185 1
|
7月前
|
存储 Java Android开发
Android 开发 - 充分利用Gradle
Android 开发 - 充分利用Gradle
112 2
|
11月前
|
XML IDE Java
Android gradle.properties 基础使用和常规配置
Gradle 是一个开源构建自动化工具,其设计足够灵活,可以构建几乎任何类型的软件。
|
8月前
|
IDE Java 开发工具
Android Gradle plugin requires Java 11 to run. You are currently using Java 1.8的解决方案
Android Gradle plugin requires Java 11 to run. You are currently using Java 1.8的解决方案
|
4月前
|
开发工具 Android开发 开发者
Android 项目编译 Gradle 配置说明
Android 项目编译 Gradle 配置说明
150 0
|
5月前
|
Java Maven Android开发
android之gradle配置仓库与引入依赖
android之gradle配置仓库与引入依赖
233 0
|
7月前
|
Java 开发工具 Maven
Android 编译 gradle 内存 OOM 解决之路(二)
Android 编译 gradle 内存 OOM 解决之路
|
7月前
|
Java Android开发
Android 编译 gradle 内存 OOM 解决之路(一)
Android 编译 gradle 内存 OOM 解决之路
|
8月前
|
Java Shell 数据处理
Android 根目录下和应用目录下的build.gradle的详解,以及groovy语法的讲解
Android 根目录下和应用目录下的build.gradle的详解,以及groovy语法的讲解
154 0