Gradle自定義插件和發(fā)布

Gradle自定義插件和發(fā)布

這篇文章講解的是如何自定義gradle插件摊欠,并以本地依賴和遠(yuǎn)程依賴的方式來集成。

本文大體結(jié)構(gòu)和內(nèi)容基于:gradle官網(wǎng)的教程:開發(fā)自定義gradle插件

約定俗成的說法:

  1. 插件消費者項目:使用對應(yīng)插件的項目吸占。
  2. 開發(fā)插件的項目:獨立的,用來開發(fā)gradle插件的項目。

開始:

自定義gradle插件的三種形式:

  1. 直接在項目中寫一個插件,并由build.gradle直接應(yīng)用來使用汉规。
  2. 在獨立的項目中開發(fā)插件,并以本地依賴的形式集成驹吮。
  3. 在獨立的項目中開發(fā)插件针史,并以遠(yuǎn)程依賴的形式集成。

1 直接在項目中寫插件并應(yīng)用

2 在獨立的項目中開發(fā)一個插件钥屈,本地依賴

2.1 新建一個獨立的java類項目

用idea或者android studio新建一個module或者新建一個project都可以悟民,只要是能夠輕易打出jar包的項目即可。

2.1.1 build.gradle中引入gradle api的依賴

首先篷就,自定義插件類的編寫射亏,需要實現(xiàn)org.gradle.api.Plugin接口,這個不是jdk的類竭业,而是gradle提供的接口智润,因此必須對gradle的api做一個依賴。

那么在項目的build.gradle中寫入:

plugins {
    id 'groovy'
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])

    //我們需要實現(xiàn)gradle的Plugin<T>接口未辆,來做自定義插件窟绷,因此依賴gradle api
    implementation gradleApi()
    //依賴gradle提供的groovy sdk,在編寫自定義插件的時候咐柜,用groovy更快兼蜈。
    implementation localGroovy()
}

sourceCompatibility = "7"
targetCompatibility = "7"

我的例子并沒有用到groovy,所以去掉上面的localGroovy拙友,并將groovy插件換成java插件也可以为狸。

2.1.2 創(chuàng)建并配置.properties文件。

其次遗契,我們寫出來的插件最終作為jar包被插件消費者項目引用辐棒,那么插件消費者項目要如何在jar包中找到我們org.gradle.Plugin接口的實現(xiàn)類呢?以及我們在哪里定義我們的插件的id呢牍蜂?

那么漾根,需要在路徑:src/main/resources/META-INF/gradle-plugins/下,創(chuàng)建一個aa.bb.cc.properties名字的文件鲫竞,里面容為:

implementation-class=你的Plugin<T>接口實現(xiàn)類的全路徑名辐怕,例如:aa.bb.cc.MyPlugin

那么此時,消費者項目能夠找到插件接口實現(xiàn)類从绘,并且秘蛇,properties文件的名字就作為你的插件id其做。

2.1.3 寫一個簡單的插件,生成一個task
package com.william.customplugin;

import org.gradle.api.Action;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.Task;

/**
 * date: 2019/9/6 0006
 *
 * @author hwj
 * description 插件
 */
public class GreetingPlugin implements Plugin<Project> {
    @Override
    public void apply(Project project) {
        project.task("hello", new Action<Task>() {
            @Override
            public void execute(Task task) {
                task.doLast(new Action<Task>() {
                    @Override
                    public void execute(Task task) {
                        System.out.println("task hello---doLast");
                    }
                });
            }
        });
    }
}

以上赁还,所有的代碼編寫工作完成了妖泄。

貼出此時項目的結(jié)構(gòu):

/customPlugin

│  .gitignore
│  build.gradle
│
└─src
    └─main
        ├─java
        │  └─com
        │      └─william
        │          └─customplugin
        │                  GreetingPlugin.java
        │
        └─resources
            └─META-INF
                └─gradle-plugins
                        com.william.customplugin.properties

2.2 構(gòu)建項目的產(chǎn)物:jar包

注意,在這一步艘策,有兩種實現(xiàn)方案:

  1. 直接用build類型的gradle腳本打出一個jar包蹈胡,然后將jar包復(fù)制粘貼到插件消費者項目。
  2. 用gradle的maven或者maven-publish插件朋蔫,來將打包的jar包發(fā)布到指定的本地路徑中罚渐。

我們先看第一種方式:

2.2.1 用build類型的gradle腳本打包

執(zhí)行

/customPlugin
$ gradlew build

構(gòu)建產(chǎn)物在:./build/libs/customPlugin.jar

此時拿到了jar包。其中包含了我們寫的org.gradle.Plugin接口的實現(xiàn)類驯妄。

2.2.2 用maven類型的腳本打包并發(fā)布在指定的本地路徑

打開插件開發(fā)項目荷并,我們需要發(fā)布一個maven類型的軟件包。gradle為maven類型的軟件包發(fā)布提供了兩種插件:mavenmaven-publish青扔,前者已經(jīng)被廢棄源织,現(xiàn)在最新的是后者,我們這里用后者插件來實現(xiàn)構(gòu)件一個maven類型的軟件包微猖。

我們參考的是maven-publish文檔的最簡單的發(fā)版配置:

group = 'org.example'
version = '1.0'

publishing {
    publications {
        myLibrary(MavenPublication) {
            from components.java
        }
    }

    repositories {
        maven {
            name = 'myRepo'
            url = "file://${buildDir}/repo"
        }
    }
}

將上述的配置移植到我們的插件開發(fā)項目的build.gradle中谈息,如下:

plugins {
    id 'groovy'
    id 'maven-publish'
}

group = "com.william.customplugin"
version = "1.0"

publishing {
    publications {
        myLibrary(MavenPublication) {
            from components.java
        }
    }

    //倉庫配置
    repositories {
        maven {
            //name這個屬性是用來指定倉庫名字的,貌似在這里沒什么用凛剥,注釋掉侠仇。
            //name = 'myRepo'
            
            //指定發(fā)布倉庫的路徑
            url = "./build/repo"
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])

    implementation gradleApi()
    implementation localGroovy()
}

sourceCompatibility = "7"
targetCompatibility = "7"

接下來就是執(zhí)行一個task,來構(gòu)建并發(fā)布了犁珠。

maven-publish腳本帶來了task publish逻炊,他會執(zhí)行所有的發(fā)布任務(wù)。而我們這里只有一個發(fā)布任務(wù)犁享,所以執(zhí)行他就好了余素。

gradlew publish

===>

14:45:49: Executing task 'publish'...

Executing tasks: [publish] in project C:\AndroidProject\KotlinSimpleTest\customPlugin

> Task :customPlugin:generatePomFileForMyLibraryPublication
> Task :customPlugin:compileJava UP-TO-DATE
> Task :customPlugin:compileGroovy NO-SOURCE
> Task :customPlugin:processResources UP-TO-DATE
> Task :customPlugin:classes UP-TO-DATE
> Task :customPlugin:jar UP-TO-DATE
> Task :customPlugin:publishMyLibraryPublicationToMavenRepository
> Task :customPlugin:publish

BUILD SUCCESSFUL in 4s
5 actionable tasks: 2 executed, 3 up-to-date
14:45:53: Task execution finished 'publish'.

OK,現(xiàn)在跑去./build/repo下面找我們的軟件包吧饼疙。

├─repo
│  └─com
│      └─william
│          └─customplugin
│              └─customPlugin
│                  │  maven-metadata.xml
│                  │  maven-metadata.xml.md5
│                  │  maven-metadata.xml.sha1
│                  │
│                  └─1.0
│                          customPlugin-1.0.jar
│                          customPlugin-1.0.jar.md5
│                          customPlugin-1.0.jar.sha1
│                          customPlugin-1.0.pom
│                          customPlugin-1.0.pom.md5
│                          customPlugin-1.0.pom.sha1

輸出的整個包多了很多東西,我們用普通的`build`命令打出來的jar包慕爬,只有一個單獨的jar包窑眯,而用`maven-publish`插件打出來的包,囊括了完整的全路徑名医窿,帶有pom文件用于描述依賴磅甩,帶有maven元數(shù)據(jù)等等,這是一個完整的姥卢、可用于分發(fā)的軟件了

2.3 在插件消費者項目中使用插件

2.3.1 直接使用本地的jar包中的插件卷要。

拿到j(luò)ar包后渣聚,把他放在一個可以被找到的路徑,我把他放在了插件消費者項目的根目錄的gradle_plugin_libs/目錄下僧叉。

└─gradle_plugin_libs
        customPlugin.jar

一般來說奕枝,安卓項目都采用的是gradle的multi-project-build組織類型,所以我打算在根目錄下讓gradle對我的腳本進(jìn)行一個依賴瓶堕,以便子項目不需要再自己去聲明對腳本的依賴隘道。

rootProject/build.gradle下:

buildscript{
    repositories{
        //...
    }
    dependencies{
        classpath 'com.android.tools.build:gradle:3.4.1'
        //...
        
        //注意,之類不能用classpath郎笆,因為classpath指定的是以標(biāo)準(zhǔn)的maven格式構(gòu)建的軟件包谭梗。
        //我們這里是直接用jar的,classpath識別不了宛蚓,會報錯激捏。因此用classpath files()
        classpath files ('./gradle_plugin_libs/customPlugin.jar')
    }
}
//..

隨意地找一個項目的構(gòu)建腳本,寫上:apply plugin: 'com.william.customplugin'凄吏。(注意远舅,插件Id是properties文件的名字)

執(zhí)行命令:gradlew hello--> 輸出: task hello---doLast

大功告成~

2.3.2 使用本地maven倉庫下的jar包中的插件

將2.2.2節(jié)構(gòu)建出的軟件包整個復(fù)制到gradle_plugin_libs/中。

修改根目錄構(gòu)建腳本:rootProject/build.gradle

buildscript{
    repositories{
        //...

        //指定一個maven倉庫的路徑
        maven {
            url uri('./gradle_plugin_libs')
        }
    }
    dependencies{
        //...
        
        //用標(biāo)準(zhǔn)的classpath方法竞思,來找到我們的插件
        classpath('com.william.customplugin:customPlugin:1.0')
    }
}
//..

執(zhí)行gradlew hello表谊,輸出和上一節(jié)一樣。

大功告成~

2.4 如何測試插件盖喷?

待補充

3 在獨立的項目中開發(fā)一個插件爆办,遠(yuǎn)程依賴

上面我們對插件進(jìn)行了本地依賴的方式來使用,現(xiàn)在我們將我們的插件打出的軟件包上傳到遠(yuǎn)程倉庫上课梳,讓別的開發(fā)者也能快速地集成距辆。

3.1 新建一個獨立的java類項目

我們就用上述的那個插件開發(fā)項目,不用再新建了暮刃。

3.2 將構(gòu)建的jar包上傳到一個遠(yuǎn)程倉庫

遠(yuǎn)程倉庫有兩個類型:

  1. 大家所熟知的中央倉庫:例如mavenCentral跨算,jcenterjitpack
  2. 普通的遠(yuǎn)程倉庫

他們本質(zhì)上都是一樣的椭懊,只是那3個中央倉庫是用的人最多的诸蚕。

我們現(xiàn)在通過bintray這個軟件包發(fā)行平臺,來上傳并管理我們的軟件包氧猬。

bintray用于上傳maven類型的軟件包有3種方式背犯,我們的其中一種是通過gradle的方式:https://github.com/bintray/gradle-bintray-plugin。這是bintray官方開發(fā)的上傳插件盅抚,專門用于打包和上傳maven類型的軟件包到bintray上面漠魏,選項多,可自定義程度高妄均,使用復(fù)雜柱锹。

在github上有一個快捷方便的第三方開發(fā)者開發(fā)的插件:https://github.com/novoda/bintray-release

只需要一個代碼塊就能完成bintray上傳的配置哪自,這里我們用這個簡單的插件來做演示,當(dāng)然大家可以根據(jù)自己業(yè)務(wù)的需求選擇負(fù)責(zé)度和功能性更高的官方插件禁熏。

3.2.1 創(chuàng)建bintray賬號

在這一步壤巷,要完成的事項如下:

  1. 創(chuàng)建bintray賬號
  2. 創(chuàng)建一個要上傳該軟件包的倉庫
  3. 在上述倉庫下創(chuàng)建一個package,即創(chuàng)建一個軟件包匹层,軟件包需要和你后面上傳的軟件包名字相同隙笆。(我很納悶為什么一定要創(chuàng)建了一個包才能上傳,不能上傳的時候沒有包bintray就自己創(chuàng)建嗎升筏,真是奇怪撑柔,我在這一步停滯了很久...)
3.2.2 配置bintray上傳腳本
plugins {
    id 'groovy'
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])

    implementation gradleApi()
    implementation localGroovy()
}

sourceCompatibility = "7"
targetCompatibility = "7"

//以上是默認(rèn)的內(nèi)容,以下是上傳腳本的配置您访,可以說是非常簡潔了铅忿。

//應(yīng)用插件
apply plugin: 'com.novoda.bintray-release'

//上傳配置
publish {
    userOrg = "huangwilliam33333"http://組織,如果沒有創(chuàng)建組織灵汪,就直接填寫用戶名檀训。
    groupId = 'com.william'//group
    artifactId = 'customPlugin'//module
    publishVersion = '1.0'//版本
    desc = '自定義測試用的插件'//描述
    website = 'htttp://www.baidu.com'//網(wǎng)站,隨便填
    bintrayUser = "huangwilliam33333"http://用戶名
    bintrayKey = "xxx"http://bintray秘鑰
    dryRun = false//如果這個是true享言,則只是運行峻凫,而不會上傳,要配置成false
}

執(zhí)行gradlew clean build bintrayUpload

上傳成功览露。

3.3 在另一個項目中依賴這個遠(yuǎn)程倉庫荧琼,并使用該插件

到插件消費者項目中:

我們還是在根目錄應(yīng)用插件:

buildscript {
    ext.kotlin_version = '1.3.41'
    repositories {
        google()
        jcenter()
        
        //因為還沒有將軟件包加入到Jcenter,所以要指明maven地址
        maven{
            url  "https://dl.bintray.com/huangwilliam33333/maven"
        }
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.5.0'
        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
        classpath 'com.novoda:bintray-release:0.9.1'
            
        //依賴插件
        classpath('com.william:customPlugin:1.0')
    }
}

插件的使用和前面一樣差牛。

3.4 如何測試插件

待補充

參考資料:

bintray第三方簡易上傳插件

bintray官方上傳插件

講到了bintray創(chuàng)建了倉庫后還要創(chuàng)建軟件包才能上傳

https://stackoverflow.com/questions/35302414/adding-local-plugin-to-a-gradle-project

gradle官方文檔:publishing artifact

gradle官方文檔:maven publish plugin

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末命锄,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子偏化,更是在濱河造成了極大的恐慌脐恩,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,464評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件侦讨,死亡現(xiàn)場離奇詭異驶冒,居然都是意外死亡,警方通過查閱死者的電腦和手機韵卤,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,033評論 3 399
  • 文/潘曉璐 我一進(jìn)店門骗污,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人怜俐,你說我怎么就攤上這事身堡〉擞龋” “怎么了拍鲤?”我有些...
    開封第一講書人閱讀 169,078評論 0 362
  • 文/不壞的土叔 我叫張陵贴谎,是天一觀的道長。 經(jīng)常有香客問我季稳,道長擅这,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,979評論 1 299
  • 正文 為了忘掉前任景鼠,我火速辦了婚禮仲翎,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘铛漓。我一直安慰自己溯香,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 69,001評論 6 398
  • 文/花漫 我一把揭開白布浓恶。 她就那樣靜靜地躺著玫坛,像睡著了一般。 火紅的嫁衣襯著肌膚如雪包晰。 梳的紋絲不亂的頭發(fā)上湿镀,一...
    開封第一講書人閱讀 52,584評論 1 312
  • 那天,我揣著相機與錄音伐憾,去河邊找鬼勉痴。 笑死,一個胖子當(dāng)著我的面吹牛树肃,可吹牛的內(nèi)容都是我干的蒸矛。 我是一名探鬼主播,決...
    沈念sama閱讀 41,085評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼扫外,長吁一口氣:“原來是場噩夢啊……” “哼莉钙!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起筛谚,我...
    開封第一講書人閱讀 40,023評論 0 277
  • 序言:老撾萬榮一對情侶失蹤磁玉,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后驾讲,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蚊伞,經(jīng)...
    沈念sama閱讀 46,555評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,626評論 3 342
  • 正文 我和宋清朗相戀三年吮铭,在試婚紗的時候發(fā)現(xiàn)自己被綠了时迫。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,769評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡谓晌,死狀恐怖掠拳,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情纸肉,我是刑警寧澤溺欧,帶...
    沈念sama閱讀 36,439評論 5 351
  • 正文 年R本政府宣布喊熟,位于F島的核電站,受9級特大地震影響姐刁,放射性物質(zhì)發(fā)生泄漏芥牌。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,115評論 3 335
  • 文/蒙蒙 一聂使、第九天 我趴在偏房一處隱蔽的房頂上張望壁拉。 院中可真熱鬧,春花似錦柏靶、人聲如沸弃理。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,601評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽案铺。三九已至,卻和暖如春梆靖,著一層夾襖步出監(jiān)牢的瞬間控汉,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,702評論 1 274
  • 我被黑心中介騙來泰國打工返吻, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留姑子,地道東北人。 一個月前我還...
    沈念sama閱讀 49,191評論 3 378
  • 正文 我出身青樓测僵,卻偏偏與公主長得像街佑,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子捍靠,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,781評論 2 361

推薦閱讀更多精彩內(nèi)容