Gradle理論與實踐四:自定義Gradle外掛
Gradle外掛
Gradle可以認為是一個框架,負責定義流程和規則。而具體的編譯工作則是透過外掛的方式來完成的。比如編譯 Java 有 Java 外掛,編譯 Groovy 有 Groovy 外掛,編譯 Android APP 有 Android APP 外掛,編譯 Android Library 有 Android Library 外掛。在Gradle中一般有兩種型別的外掛,指令碼外掛和二進位制外掛。使用外掛方式可以使得同一邏輯在專案中複用,也可以針對不同專案做個性化配置,只要外掛程式碼支援即可。
一、Java Gradle外掛
Java外掛引入方式:
apply plugin: 'java'
Java外掛約定src/main/java
為我們專案原始碼存放位置;src/main/resources
為資源存放位置;src/test/java
為我們單元測試用例存放目錄;src/test/resources
存放我們單元測試中資源存放位置。
java外掛引入了一個概念叫做SourceSets,透過修改SourceSets中的屬性,可以指定哪些原始檔(或資料夾下的原始檔)要被編譯,哪些原始檔要被排除。Gradle就是透過它實現Java專案的佈局定義。
預設配置:
android { sourceSets { main { manifest.srcFile 'AndroidManifest.xml' java.srcDirs = ['src'] resources.srcDirs = ['src'] aidl.srcDirs = ['src'] renderscript.srcDirs = ['src'] res.srcDirs = ['res'] assets.srcDirs = ['assets'] jniLibs.srcDirs = ['libs'] } }
如果想修改原始碼的目錄以及多個resource的目錄,可以透過下面來設定:
sourceSets { main { java.srcDirs = ['other/java'] res.srcDirs = [ 'src/main/res/', 'src/main/res/extra' ] } }
更多設定請移步官網:
https://developer.android.com/studio/build/build-variants
二、Android Gradle外掛
Android其實就是Gradle的一個第三方外掛,Android Gradle和Android Studio完美無縫搭配的新一代構建系統。
APP外掛id :com.android.application
Library外掛id:com.android.library
Test外掛id:com.android.test
2.1、應用Android Gradle外掛
上面說了Android Gradle是Gradle的一個三方外掛,託管在jcenter上,如果要使用,必須知道他們的外掛id,另外還要配置他們依賴的classpath,在根目錄的build.gradle中配置如下:
buildscript { repositories { //程式碼倉庫 jcenter() } dependencies { //Android Gradle外掛版本 classpath 'com.android.tools.build:gradle:2.3.3' } }
配置程式碼倉庫為jcenter,當編譯專案時,Gradle會去jcenter倉庫中尋找Android Gradle對應版本的依賴,以上配置好後,就可以使用Android Gradle外掛了,在我們app目錄的build.gradle下:
apply plugin: 'com.android.application android { compileSdkVersion 26 buildToolsVersion "26.0.3" defaultConfig { applicationId "org.ninetripods.qrcode" minSdkVersion 14 targetSdkVersion 26 versionCode 1 versionName "1.0" } signingConfigs { release { keyAlias 'xxx' keyPassword 'xxx' storeFile file('xxx.jks') storePassword 'xxx' } } buildTypes { release { minifyEnabled false signingConfig signingConfigs.release proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } }
android{}是Android Gradle外掛提供的一個擴充套件型別,可以讓我們自定義Android Gradle工程。
compileSdkVersion: compileSdkVersion告訴Gradle用哪個Android SDK版本編譯應用
1、應用想相容新版本、使用了新版本API,此時就必須使用新版本及以上版本編譯,否則就會編譯報錯;
2、如果使用了新版本的Support Library,此時也必須使用新版本及以上版本編譯buildToolsVersion:構建該Android工程所用構建工具(aapt, dx, renderscript compiler, etc...)的版本,一般google在釋出新的SDK時,會同時釋出對應的buildToolsVersion,更詳細的見:
PS:Android Studio 3.0以上時,buildToolsVersion不是必須要寫的了。defaultConfig: 預設配置,它是一個ProductFlavor。ProductFlavor允許我們在打多渠道包時根據不同的情況生成不同的APK包。即如果不在ProductFlavor中單獨配置的話,那麼會使用defaultConfig的預設配置。
minSdkVersion: 最低支援的Android系統API Level
targetSdkVersion: App基於哪個Android版本開發的
versionCode: App應用內部版本號,一般用來控制App升級
versionName: App應用的版本名稱,即我們釋出的App版本,一般使用者可以看到。
minSdkVersion、targetSdkVersion、compileSdkVersion三者的關係:
minSdkVersion <= targetSdkVersion <= compileSdkVersion。
理想狀態是:
minSdkVersion(lowest possible) <= targetSdkVersion == compileSdkVersion(latest SDK)。
三、自定義Gradle外掛
編寫自定義Gradle外掛原始碼的有下面三個地方:
3.1、Build script
可以在構建指令碼中直接編寫自定義外掛的原始碼。這樣做的好處是外掛可以自動編譯幷包含在構建指令碼的classpath中,不需要再去宣告。然而,這個自定義外掛在構建指令碼之外是不可見的,因此這種方式實現的外掛在構建指令碼之外是不能複用。
舉個例子,在根目錄下的build.gradle中寫入:
//build.gradleclass GreetingPlugin implements Plugin<Project> { @Override void apply(Project project) { //新建task hello project.task('hello') { doLast { println 'Hello from the GreetingPlugin' } } } }//引入外掛apply plugin: GreetingPlugin
執行結果
./gradlew hello Hello from the GreetingPlugin
3.2、buildSrc project
在專案的根目錄下新建一個buildSrc/src/main/groovy的目錄,將自定義外掛的原始碼放入此目錄中,Gradle將負責編譯和測試外掛,並使其在構建指令碼的classpath中可見。這個外掛對於專案中所有的build script都是可見的,但是在構建之外是不可見的,此構建方式不能再其他專案中複用。
舉例:在rootProjectDir/buildSrc/src/main/groovy目錄下新建了一個外掛類,如下:
image.png
GreetingExtensionPlugin.groovy中程式碼如下:
//GreetingExtensionPlugin.groovypackage comimport org.gradle.api.Pluginimport org.gradle.api.Projectclass GreetingExtensionPlugin implements Plugin<Project> { @Override void apply(Project project) { // Add the 'greeting' extension object def extension = project.extensions.create('greeting', GreetingExtension) // Add a task that uses configuration from the extension object project.tasks.create('buildSrc') { doLast { println "${extension.message} from ${extension.greeter}" println project.greeting } } } }class GreetingExtension { String message String greeter }
定義好的外掛就可以在專案中所有的build.gradle中使用了:
//build.gradleapply plugin: GreetingExtensionPlugin greeting { message = 'hello' greeter = 'GreetingExtensionPlugin'}
執行結果:
./gradlew buildSrc hello from GreetingExtensionPlugin com.GreetingExtension_Decorated@42870556
擴充套件屬性:自定義外掛程式碼中有一句
def extension = project.extensions.create('greeting', GreetingExtension)
,可以用來擴充套件屬性,可以理解為往GreetingExtension中新加了一個屬性。建立完成後,可以透過project.greeting來獲取擴充套件屬性的例項。使用這種方式來給外掛傳遞引數。
3.3、Standalone project
上面兩種自定義外掛都只能在自己的專案中使用,如果想在其他專案中也能複用,可以建立一個單獨的專案並把這個專案釋出成一個JAR,這樣多個專案中就可以引入並共享這個JAR。通常這個JAR包含一些外掛,或者將幾個相關的task捆綁到一個庫中,或者是外掛和task的組合, Standalone project建立步驟:
在Android Studio的rootProject目錄下新建一個Module,型別隨便選一個就行(如 Android Module),後面會有大的改動。(也可以選擇IDEA來開發,IDEA中可以直接建立groovy元件)
清空Module目錄下build.gradle中的所有內容,刪除其他所有檔案
在Module中建立
src/main/groovy
的目錄,然後再建立包名資料夾。在main目錄下再新建resources/META-INF/gradle-plugins
目錄,在這個目錄下編寫一個和外掛id名字相同的.properties
檔案,這樣Gradle就可以找到外掛實現了。
舉個例子,下面的程式碼實現了在build目錄中新建個文字檔案,並寫入文字的功能。
1、在src/main/groovy
下新建/com/fastgo/plugin
目錄並建立一個名為CustomPlugin.groovy
的檔案:
package com.fastgo.pluginimport org.gradle.api.DefaultTaskimport org.gradle.api.Projectimport org.gradle.api.Pluginimport org.gradle.api.tasks.TaskActionclass CustomPlugin implements Plugin<Project> { @Override void apply(Project project) { project.tasks.create('writeToFile', CustomPluginTask) { destination = { project.greetingFile } doLast { println project.file(destination).text } } } }class CustomPluginTask extends DefaultTask { def destination File getDestination() { //建立路徑為destination的file project.file(destination) } @TaskAction def greet() { def file = getDestination() file.parentFile.mkdirs() //向檔案中寫入文字 file.write('hello world') } }
上面的程式碼中在外掛的apply(Project project)
中建立了名為writeToFile
的Task,並依賴於CustomPluginTask
。CustomPluginTask
中定義了一個destination
路徑,並透過project.file(destination)
建立建立一個路徑為destination
的檔案,並往檔案中寫入文字。
注意:別忘了引入 package com.fastgo.plugin
,否則最後生成後會提示找不到外掛。
2、建立resources/META-INF/gradle-plugins/com.fastgo.plugin.properties
檔案,並在檔案裡寫入:
implementation-class=com.fastgo.plugin.CustomPlugin
3、在build.gradle
中寫入:
plugins { id 'groovy' id 'maven-publish' id 'maven'} dependencies { implementation gradleApi() implementation localGroovy() } repositories { mavenCentral() } group = 'com.fastgo'version = '1.0-test'publishing { repositories { maven { url = uri("$rootDir/repo") } } publications { maven(MavenPublication) { from components.java } } }
本例中是透過url = uri("$rootDir/repo")
將程式碼打包到maven的本地倉庫中,如果想上傳到遠端,換成遠端連結即可。透過設定GroupId、ArtifactId、Version來保證外掛的唯一性。
GroupId:
group = 'com.fastgo'
ArtifactId:
plugin
Version:
version = '1.0-test'
最終的檔案如下:
image.png
外掛編寫完成後,在Android Studio的右上角開啟Gradle,執行:plugin
分組中的publish
命令,執行完成後,會在專案根目錄下生成repo倉庫:
image.png
4、在專案根目錄的build.gradle
中引用外掛:
buildscript { repositories { maven { url = uri("$rootDir/repo") } ------其他------- } dependencies { classpath 'com.android.tools.build:gradle:2.3.3' classpath 'com.fastgo:plugin:1.0-test' } } //透過外掛id找到外掛 apply plugin: 'com.fastgo.plugin' ext.greetingFile="$buildDir/hello.txt"
5、驗證效果
mqdeMacBook-Pro:AndroidStudy mq$ ./gradlew -q writeToFile hello world
執行writeToFile的task輸出了我們寫入的文字,再看看build目錄下是否有我們想要的檔案:
image.png
可以看到在build
目錄下生成了hello.txt
檔案並往裡面寫入了設定的文字,說明我們編寫的外掛被成功引入了。
作者:_小馬快跑_
連結:
x
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/4686/viewspace-2821528/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- gradle自定義外掛Gradle
- 自定義Gradle-Plugin 外掛GradlePlugin
- Gradle系列(四) Gradle外掛Gradle
- gradle自定義任務和外掛Gradle
- 手把手帶你自定義 Gradle 外掛 —— Gradle 系列(2)Gradle
- Gradle核心思想(六)自定義Gradle外掛的三種方式Gradle
- Gradle系列之Gradle外掛Gradle
- Gradle外掛學習筆記(四)Gradle筆記
- Gradle 自定義 pluginGradlePlugin
- Android Gradle外掛AndroidGradle
- 不得不學之「 Gradle」 ⑤ Gradle 外掛Gradle
- Gradle入門系列(五)——Gradle其它模組與Plugin外掛GradlePlugin
- 自定義一個gradle外掛動態修改jar包Class檔案GradleJAR
- Android Studio之Gradle和Gradle外掛的區別AndroidGradle
- Flutter 自定義 Widget(理論+實踐)Flutter
- Gradle最佳實踐Gradle
- 使用 Java 開發 Gradle 外掛JavaGradle
- Android Studio gradle外掛版本和gradle版本對應關係AndroidGradle
- Gradle 與 AGP 構建 API: 如何編寫外掛GradleAPI
- Gradle核心思想(五)通俗易懂的Gradle外掛講解Gradle
- Gradle外掛學習筆記(一)Gradle筆記
- Android開發中Gradle外掛,Gradle版本與JDK版本之間的對應關係 AndroidAndroidGradleJDK
- IDEA建立Gradle工程-實踐IdeaGradle
- Gradle外掛從入門到進階Gradle
- 通俗易懂的Gradle外掛講解Gradle
- Gradle入門系列(四)——初識Gradle TaskGradle
- Android中的Gradle之玩轉自定義功能AndroidGradle
- Gradle核心思想(四)看似無用,實則重要的Gradle WrapperGradleAPP
- Gradle 與 AGP 構建 API: 進一步完善您的外掛!GradleAPI
- mybatis 自定義外掛MyBatis
- Gradle Repo:一個能管理多個Git倉庫,又能快速切換分支的Gradle外掛GradleGit
- 淺析MyBatis(三):聊一聊MyBatis的實用外掛與自定義外掛MyBatis
- 【軟體工程理論與實踐】Homework(四.1)軟體工程
- Gradle多渠道打包的原理、實踐與輔助開發Gradle
- Gradle入門系列(三)——初識Gradle與ProjectGradleProject
- 使用新 Android Gradle 外掛加速您的應用構建AndroidGradle
- 使用gradle外掛釋出專案到nexus中央倉庫Gradle
- vue自定義全域性元件(或自定義外掛)Vue元件