1. 前言
Gradle系列已完成,專注於Gradle,有如下幾篇文章
依賴apply plugin: 'com.android.application'
就是依賴了安卓的應用程式外掛.然後這個外掛裡面有android擴充套件,在官方文件裡面有詳細描述.但是,有時候不得不自己寫一個外掛,方便與業務開展.比如我覺得美團的熱修復,在每個方法前面插邏輯的話,肯定得插樁,插樁就得自己寫外掛.方便快捷.Gradle+ASM可以插樁.有興趣的可以去了解.
demo地址: github.com/xfhy/Gradle…
2. 簡單外掛
新建一個簡單的專案,然後建立一個buildSrc這個名字的module,這個module的名稱必須為buildSrc.因為我們建立的這個module是AS專門用來寫外掛的,會自動參與編譯.建立好之後刪除Android那一堆東西,什麼java程式碼,res,清單檔案等.只剩下build.gradle和.gitignore
把build.gradle檔案內容改成
repositories {
google()
jcenter()
}
apply {
plugin 'groovy'
plugin 'java-gradle-plugin'
}
dependencies {
implementation gradleApi()
implementation localGroovy()
implementation "commons-io:commons-io:2.6"
}
複製程式碼
然後在main下面建立資料夾groovy,sync一下.沒啥問題的話,應該能編譯過.然後在groovy資料夾下面建立包名com.xfhy.plugin
,然後建立一個外掛,名字叫CustomPlugin.groovy
package com.xfhy.plugin
import org.gradle.api.Plugin
import org.gradle.api.Project
class CustomPlugin implements Plugin<Project> {
@Override
void apply(Project project) {
project.task('showCustomPlugin') {
doLast {
println('hello world plugin!')
}
}
}
}
複製程式碼
我在這裡宣告瞭一個CustomPlugin外掛,然後裡面建立了一個task名字叫showCustomPlugin,showCustomPlugin外掛就只是簡單輸出一句話. 然後在app的build.gradle裡面引入這個外掛
import com.xfhy.plugin.CustomPlugin
apply plugin: CustomPlugin
複製程式碼
然後就可以在命令列輸入gradlew showCustomPlugin
執行這個外掛.然後就可以在命令列看到輸出了.就這樣簡單的幾步,一個簡單的外掛就寫完了,雖然只是簡單地列印了hello world.
.
3. 外掛 plus
但是,我們肯定不會滿足於只會輸出hello world的外掛,我們來做一個稍微有點用的外掛.正如我們平常在android{} 閉包裡面,我們寫了很多次的
compileSdkVersion Config.compileSdkVersion
buildToolsVersion Config.buildToolsVersion
....
複製程式碼
那我們就來做這樣一個外掛,讀取這些配置資訊的資料.首先在包名com.xfhy.plugin
下面建立AndroidExtension.groovy
,它是一個bean物件,用來儲存資訊的.定義如下:
package com.xfhy.plugin
class AndroidExtension {
String compileSdkVersion = ''
String buildToolsVersion = ''
String applicationId = ''
String minSdkVersion = ''
}
複製程式碼
然後建立一個新的外掛MyAndroidPlugin.groovy
package com.xfhy.plugin
import org.gradle.api.Plugin
import org.gradle.api.Project
class MyAndroidPlugin implements Plugin<Project> {
@Override
void apply(Project project) {
def extension = project.extensions.create('testExtension', AndroidExtension)
project.task('AndroidPlugin') {
doLast {
println("minSdkVersion = ${extension.minSdkVersion}")
println("applicationId = ${extension.applicationId}")
println("compileSdkVersion = ${extension.compileSdkVersion}")
println("buildToolsVersion = ${extension.buildToolsVersion}")
}
}
}
}
複製程式碼
通過project.extensions.create
來獲取testExtension閉包中的內容,並通過反射將閉包中的內容轉成一個AndroidExtension物件.然後我建立了一個task去讀取它.
然後我們在app下面的build.gradle中加入程式碼:
testExtension {
minSdkVersion '22'
applicationId 'com.xfhy.gradledemo'
compileSdkVersion '29'
buildToolsVersion '29.0.2'
}
複製程式碼
輸出如下:
minSdkVersion = 22
applicationId = com.xfhy.gradledemo
compileSdkVersion = 29
buildToolsVersion = 29.0.2
複製程式碼
不錯,已經能搞一個能讀取到閉包資訊的外掛了.
4. 實操
我們來實現一個外掛,打包的時候將pic/test.png
複製到apk檔案中的assets中.實際上是在打包之前將test.png複製到相應的資料夾,等待打包合成.首先是新建HookAssetsPlugin.groovy
class HookAssetsPlugin implements Plugin<Project> {
@Override
void apply(Project project) {
project.afterEvaluate { it ->
//1. 在afterEvaluate閉包中才能獲取當前project中的所有task
project.plugins.withId('com.android.application') {
//2.確保當前project是Android app project,而不是Android library project, 為給定id的外掛執行或註冊操作
project.android.applicationVariants.all { variant ->
//3. 拿到所有變體資訊
//[ApkVariantOutputImpl_Decorated{apkData=Main{type=MAIN, fullName=freeDebug, filters=[], versionCode=2, versionName=2.0.0}}]
variant.outputs.each { variantOutput ->
// 4. outputs 欄位可知道該欄位代表著當前變體的輸出資訊(DomainObjectCollection 型別)
// println("${variantOutput.name}") //free-debug free-release
if (variantOutput.name.contains('release')) {
//5. 拿到release
project.tasks.findByName("package${variant.name.capitalize()}").doFirst { task ->
//6. 得到packageApplication
project.copy {
//7. 複製
from "${project.projectDir.absolutePath}/pic/test.png"
into "${task.assets.provider.value.value.getAbsolutePath()}"
}
}
}
}
}
}
}
}
}
複製程式碼
巢狀特別多,寫起來不是很舒服,而且不能智慧提示,而且api還不好查....吐血..詳細的註釋在程式碼中已給出,這裡就不多做介紹了.使用的時候在app下的build.gradle中新增如下程式碼即可:
import com.xfhy.plugin.HookAssetsPlugin
apply plugin: HookAssetsPlugin
複製程式碼
然後執行gradlew assembleFreeRelease
,完事兒之後看一下打出來的apk包,可以看到是apk檔案裡面的assets裡面確實多了test.png檔案.看起來沒什麼鳥用,但是卻讓我們感受到了外掛到底可以幹些什麼事兒.
5. 除錯Gradle
首先是我們在執行指令的時候加一個引數gradlew assembleFreeRelease -Dorg.gradle.debug=true --no-daemon
,這樣.
然後在AS->Run->EditConfigurations,然後點選左上角的+
號,新增一個Remote,然後直接點選apply即可.
然後點選debug按鈕即可進入除錯.
6. 總結
Gradle外掛很多時候能方便我們進行一些騷操作,用處還是挺大的.
參考