背景
最近組里gradle大神帶大家一起飛,lz也趁機(jī)學(xué)習(xí)一下Gradle相關(guān)的知識。我們工程中的gradle的腳本幾乎是我所見過的最復(fù)雜的工程(另一個是Tinker),里面有自定義的plugin,也有自己執(zhí)行的一些腳本,如lint,時間監(jiān)聽,findbugs,Checkstyle等,也使用gradle transform api 動態(tài)插樁。lz 作為小白,默默從自定義gradle plugin 開始。
先看gradle的工程結(jié)構(gòu)圖

主工程app, submodule helloplugin
helloplugin 通過新建


lets go
helloplugin 的gradle配置如下
apply plugin: 'groovy'
//添加maven plugin, 用于發(fā)布我們的jar
apply plugin: 'maven'
dependencies {
compile gradleApi()
compile localGroovy()
}
repositories {
mavenCentral()
}
//設(shè)置maven deployer
uploadArchives {
repositories {
mavenDeployer {
//設(shè)置插件的GAV參數(shù)
pom.groupId = 'plugin'
pom.artifactId = 'helloplugin'
pom.version = 1.2
//文件發(fā)布到下面目錄
repository(url: uri('../release'))
}
}
}
其中uploadArchives用于上傳plugin到本地release文件夾下(實際使用一般 是私有maven倉庫)。 其實看過我前面IntelliJ IDEA spring mvc +mybatis 環(huán)境搭建服務(wù)器 http://www.itdecent.cn/p/c7060f84bf5c 等系列的童鞋不會陌生groupId、artifactId、version 目的是相當(dāng)于配置一個工程唯一id。
新建groovy和resources文件夾

主插件類HelloPlugin.groovy
package plugin
import org.gradle.api.Plugin
import org.gradle.api.Project
public class HelloPlugin implements Plugin<Project> {
@Override
void apply(Project project) {
project.extensions.create('apkdistconf', ApkDistExtension);
project.task('hellotask') << {
println "hello, this is test task!"
}
project.afterEvaluate {
//只可以在 android application 或者 android lib 項目中使用
if (!project.android) {
throw new IllegalStateException('Must apply \'com.android.application\' or \'com.android.library\' first!')
}
//配置不能為空
if (project.apkdistconf.nameMap == null || project.apkdistconf.destDir == null) {
project.logger.info('Apkdist conf should be set!')
return
}
Closure nameMap = project['apkdistconf'].nameMap
String destDir = project['apkdistconf'].destDir
//枚舉每一個 build variant,生成的apk放入如下路徑和文件名
project.android.applicationVariants.all { variant ->
variant.outputs.each { output ->
File file = output.outputFile
print("dir " + destDir + " " + file.getName())
output.outputFile = new File(destDir, nameMap(file.getName()))
}
}
}
}
}
需要繼承 Plugin<Project> ,當(dāng)主gradle使用//使用helloplugin
apply plugin: 'helloplugin'時,就會調(diào)用apply方法。
ApkDistExtension.groovy擴(kuò)展的屬性
package plugin
class ApkDistExtension {
Closure nameMap = null;
String destDir = null;
}
groovy語法,默認(rèn)生成get和set方法。
配置指向插件的主類HelloPlugin

implementation-class=plugin.HelloPlugin
注意路徑為plugin.HelloPlugin 全包名 + 類名
編譯
此時會發(fā)現(xiàn)

運行uploadArchives task就可以將其打包到本地了。
此時,如下:

使用

import plugin.HelloWorldTask
apply plugin: 'com.android.application'
//使用helloplugin
apply plugin: 'helloplugin'
buildscript {
repositories {
maven {
//cooker-plugin 所在的倉庫
//這里是發(fā)布在本地文件夾了
url uri('../release')
}
}
dependencies {
//引入helloplugin
classpath 'plugin:helloplugin:1.2'
}
tasks.withType(JavaCompile) {
sourceCompatibility = JavaVersion.VERSION_1_7
targetCompatibility = JavaVersion.VERSION_1_7
}
}
task hello1(type:HelloWorldTask){
message ="I am a programmer"
}
apkdistconf {
nameMap { name ->
println 'hdasd, ' + name
return name
}
destDir "$project.path"
}
android {
compileSdkVersion 25
buildToolsVersion "25.0.2"
defaultConfig {
applicationId "com.example.nothing.plugindemo"
minSdkVersion 11
targetSdkVersion 25
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
compile 'com.android.support:appcompat-v7:25.1.1'
compile project(':helloplugin')
}
type:HelloWorldTask是helloplugin里面自定義的一個task不影響使用,可以去掉或參考我上傳的。
正常運行即可。
這里有幾點說明下,其他groovy還是和其他腳本很相似的,閉包也與lamda表達(dá)式類似。 destDir "$project.path"相當(dāng)于 setDestDir("$project.path"), $用戶變量,與其他腳本類似。
遇到的問題
第一個問題,找不到,這里需要分析找不到ext的原因: 本來未定義或其他,這里是我自己已經(jīng)upload了一次之后,沒有upload新的gradle plugin,自己挖的坑含著淚也要跳下去。
Error:(25, 0) Could not find method sa() for arguments [build_2x9mdgfer2n7ji1nsjr5g8ki6$_run_closure1@32b044f8] on project ':app' of type org.gradle.api.Project.
<a href="openFile:XXX/pluginTest/app/build.gradle">Open File</a>
報的錯誤

在主gradle 添加如下配置:
buildscript {
tasks.withType(JavaCompile) {
sourceCompatibility = JavaVersion.VERSION_1_7
targetCompatibility = JavaVersion.VERSION_1_7
}
}