天天看點

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.properties

apk_change_name

為插件名

005 釋出插件到本地目錄中

執行如下指令即可

gradle uploadArchives

則會在

build.gradle

的同級目中生成repo目錄,裡邊的内容如下圖:

Android Gradle 插件開發指南

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開發者門戶

”,了解相關資訊可以關注“

”。

繼續閱讀