如何從零開發一個 gradle 插件(二)

上一篇咱們介紹了 gradle 插件相關的概念,沒看的同窗能夠點擊這裏查看,這一篇讓咱們結合例子來看看如何一步步建立一個 gradle 插件,並在 Android 項目中使用。java

IDE

工欲善其事必先利其器,要開發 gradle 插件得先決定用什麼開發環境。我本身使用過 Intellij IDEA 和 AndroidStudio 來開發,由於 AndroidStudio 是基於 Intellij 改的,因此區別不是很大。android

但就我我的的偏好來講更偏向於 Intellij,由於 AndroidStudio 是專門用來開發 Android 的,有不少配套的調試按鈕,若是用來開發一個純的 gradle 插件項目就會很彆扭,因此個人判斷原則是:api

  • 若是是一個純的 gradle 插件項目,用 Intellij IDEA。
  • 若是是 Android 項目中內嵌的 gradle 插件項目,好比一個 module 用來放插件的代碼,用 AndroidStudio。

語言

gradle 插件比較主流的開發語言是 groovy,由於 gradle 就是用 groovy 寫的。經過查看第三方寫的 gradle 插件代碼發現大部分也是用 groovy 寫的。bash

除了 groovy 還能夠用來開發 gradle 插件的語言有:網絡

  • java
  • kotlin
  • 其它基於 jvm 語言

由於 groovy 是基於 jvm 的,因此一樣基於 jvm 的也能夠用來寫 gradle 插件。但 java 和 kotlin 是靜態語言,意味着須要不停地判斷類型和強轉,相比之下,groovy 做爲動態語言就沒有這個問題。因此本文後續的插件代碼都是 groovy 寫的。app

具體開發以前讓咱們先來看看要開發的 gradle 插件要知足什麼需求。jvm

需求描述

實現一個插件,名字叫 io.helloworld.myplugin,須要實現下面的功能:maven

  • 進行 Android 自動配置
    • minSdkVersion 設置爲 21
    • targetSdkVersion 設置爲 26
    • compileSdkVersion 設置爲 29
    • buildToolsVersion 設置爲 ‘29.0.2’
  • 註冊一個 Task,名字叫 myTask

具體步驟

  • 打開 Intellij IDEA,按 file -> new -> project 建立一個新項目。在 「new project」對話框左邊選擇 gradle,右邊的 「Additional Libraries and Frameworks」只選擇 Groovy:ide

  • 下一個界面選擇表明你這個插件包的 groupId 和 ArtifactId,例如 io.helloworld.robotgradletools,版本號能夠保持默認不變 1.0-SNAPSHOTpost

    groupId、artifactId 和 version 構成了咱們這個插件包的標識 Id,另外一個項目若是想使用咱們這個插件時,就須要經過這個 Id 來聲明依賴。

  • 而後點 「next」-> 「finish」,項目結構大概像下面這樣:

  • 由於要用到 gradle 的依賴,因此須要在項目 build.gradle 腳本文件中加一條 gradle 的依賴:

    dependencies {
        implementation gradleApi()
        ...
    }
    複製代碼

    建立項目時,IDE 會默認添加上 groovy 的依賴:

    implementation 'org.codehaus.groovy:groovy-all:2.3.11'
    複製代碼

    爲了防止出現 groovy 版本不一致的問題,這裏的依賴最好換成下面這樣,讓 gradle 自動去獲取本地的 groovy 版本。

    implementation localGroovy()
    複製代碼

    而後點一下 gradle 的同步按鈕,保證 IDE 能引用到對應的類。

  • 在 groovy 文件夾下建立包 io.helloworld.robot,和前面設置的 groupId 保持一致。在這個包下建立一個 groovy 類 MyPlugin,代碼以下:

    package io.helloworld.robot
    
    import org.gradle.api.Plugin
    import org.gradle.api.Project
    
    class MyPlugin implements Plugin<Project> {
        @Override
        void apply(Project project) {
            println("beginning of plugin 'MyPlugin'")
        }
    }
    複製代碼

    能夠看到 MyPlugin 實現了 Plugin<Project> 的接口,而這個接口有一個方法 apply(Project project),猜想當咱們這個插件在 build.gradle 中應用時,這個方法會被調用,咱們在這個方法中加上一行打印調試信息的代碼。

    這裏建立的插件是給 build.gradle 用的,因此 Plugin 的泛型類型是 Project,若是給 settings.gradle 用的話,泛型類型應該是 Settings

    如今咱們的插件已經建立好了(雖然很簡陋),那怎樣才能讓 Android 項目使用到它呢?還須要再作兩件事:建立插件的聲明文件和將包含插件的軟件包發佈到 maven 倉庫。

  • 建立插件的聲明文件

    須要在 resources 文件夾下建立文件夾 META-INF/gradle-plugins,全部插件的聲明文件都要放在這個目錄下:

    插件的聲明文件都是後綴爲 properties 的配置文件,文件名就是插件的名字,例如這裏的插件名字就是 io.helloworld.myplugin。在文件中經過 implementation-class 的值關聯到上面建立的插件類 MyPlugin

    implementation-class=io.helloworld.robot.MyPlugin
    複製代碼
  • 發佈到 maven 倉庫

    由於 maven 倉庫不是這篇文章的重點,因此簡單起見,這裏將包含插件的軟件包發佈到本地倉庫。

    要發佈到本地倉庫,build.gradle 須要加上下面這些代碼:

    apply plugin: 'maven-publish'
    
    publishing {
        publications {
            mavenPub(MavenPublication) {
                // 這一行表示將 jar 包包含在要發佈的組件中
                from components.java
                // 描述性信息
                pom {
                    name = 'Robot MyPlugin'
                    description = 'This is a test project for gradle plugin.'
                    url = 'http://www.helloworld.com'
                }
            }
        }
        repositories {
            maven {
                // 本地 repo 地址,這裏寫上大家電腦上本身的地址
                url = '/Users/zhanglei/projects/repo'
            }
        }
    }
    複製代碼

    這裏使用 maven-publish 插件來發布到 maven 倉庫,其實發布到網絡上也是相似的,將上面代碼的 url 改爲網絡地址,再加上用戶名/密碼就能夠了。

    改好 build.gradle 後點一下 gradle 的同步按鈕,在 gradle 窗口的 Tasks 條目下就會看到 publishing 的 Task 分組,其中能夠找到「publish」Task:

    雙擊執行這個 Task 來發布組件,執行結束後在上述本地倉庫的地址下能夠看到組件已經發布成功:

    OK,全部的準備工做都作完了,如今可使用插件了。

  • 在 Android 項目中使用插件

    由於咱們的插件是配置 Android 相關信息,因此要在 application 類型的 module 下使用。在 AndroidStudio 中打開 module 下的 build.gradle 文件,加上下面的代碼:

    // 使用插件
    apply plugin: 'io.helloworld.myplugin'
    buildscript {
        repositories {
            // 聲明本地 repo 的地址
            maven {
                url '/Users/zhanglei/projects/repo'
            }
        }
        dependencies {
            // 聲明依賴咱們上面發佈到本地 maven 倉庫的軟件包
            classpath 'io.helloworld.robot:gradletools:1.0-SNAPSHOT'
        }
    }
    複製代碼

    由於插件發佈在本地倉庫中,因此要在 buildscript.repositories 中聲明一下倉庫地址。而後在 AndroidStudio 中同步下 gradle 就能夠看到咱們剛纔寫在 apply() 中的調試代碼輸出的 log:

    AndroidStudio 中同步 gradle 和 Intellij 中稍微有點不同:點下面這個按鈕:

    好的,咱們如今把開發插件到使用插件這條路調通了,接下來咱們在插件中完成上面說的「插件需求」,先來看看第一個:

  • 實現插件功能一:進行 Android 自動配置

    • minSdkVersion 設置爲 21
    • targetSdkVersion 設置爲 26
    • compileSdkVersion 設置爲 29
    • buildToolsVersion 設置爲 29.0.2

    在 Intellij 中打開 MyPlugin 類,在 apply() 方法中加上下面這段代碼:

    project.extensions.findByName('android').with {
        getProperty('defaultConfig').with {
            setProperty('minSdkVersion', 21)
            setProperty('targetSdkVersion', 26)
        }
        setProperty('compileSdkVersion', 29)
        setProperty('buildToolsVersion', '29.0.2')
    }
    複製代碼

    而後發佈到本地倉庫,而後在 AndroidStudio 中同步下 gradle,這就至關於在 build.gradle 中寫了:

    android {
        defaultConfig {
            minSdkVersion 21
            targetSdkVersion 26
        }
        compileSdkVersion 29
        buildToolsVersion '29.0.2'
    }
    複製代碼

    第一個需求完成了,接下來看一下第二個需求。

  • 實現插件功能二:註冊一個 Task myTask

    打開 MyPlugin,在 apply() 方法中加上下面這段代碼:

    project.task('myTask') {
        group 'helloworld'
        description 'This is a task named myTask, created in myPlugin'
        doFirst {
            println("run in myTask it $it")
        }
    }
    複製代碼

    這裏建立了一個名叫 myTask 的 Task,並設置了 group、description 和它的運行代碼。和上面同樣,將插件發佈到本地倉庫,並同步 Android 項目的 gradle。能夠看到 Android 項目中已經存在 myTask Task:

到這裏一個擁有基本功能的 gradle 插件就開發好了,若是想繼續擴展這個插件的功能,就繼續在 apply() 方法裏添加代碼。由於 apply() 方法的參數是 project,因此這裏能夠實現 build.gradle 中的全部能力。你也能夠在這個項目中開發一個新的插件,放一些特殊的 gradle 處理邏輯。

關於 gradle 插件開發就簡單介紹到這裏,因爲我也是邊開發邊學習,不免有一些不對的地方,歡迎你們評論指正。

相關文章
相關標籤/搜索