作為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目錄,裡邊的内容如下圖:
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開發者門戶”,了解相關資訊可以關注“
”。