Gradle系列(四) Gradle插件

1. 前言

Gradle系列已完成,專一於Gradle,有以下幾篇文章html

依賴apply plugin: 'com.android.application'就是依賴了安卓的應用程序插件.而後這個插件裏面有android擴展,在官方文檔裏面有詳細描述.可是,有時候不得不本身寫一個插件,方便與業務開展.好比我以爲美團的熱修復,在每一個方法前面插邏輯的話,確定得插樁,插樁就得本身寫插件.方便快捷.Gradle+ASM能夠插樁.有興趣的能夠去了解.java

demo地址: github.com/xfhy/Gradle…android

2. 簡單插件

新建一個簡單的項目,而後建立一個buildSrc這個名字的module,這個module的名稱必須爲buildSrc.由於咱們建立的這個module是AS專門用來寫插件的,會自動參與編譯.建立好以後刪除Android那一堆東西,什麼java代碼,res,清單文件等.只剩下build.gradle和.gitignoregit

QQleEj.png

把build.gradle文件內容改爲github

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.groovyapi

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裏面引入這個插件bash

import com.xfhy.plugin.CustomPlugin
apply plugin: CustomPlugin
複製代碼

而後就能夠在命令行輸入gradlew showCustomPlugin執行這個插件.而後就能夠在命令行看到輸出了.就這樣簡單的幾步,一個簡單的插件就寫完了,雖然只是簡單地打印了hello world..閉包

3. 插件 plus

可是,咱們確定不會知足於只會輸出hello world的插件,咱們來作一個稍微有點用的插件.正如咱們日常在android{} 閉包裏面,咱們寫了不少次的app

compileSdkVersion Config.compileSdkVersion
buildToolsVersion Config.buildToolsVersion
....
複製代碼

那咱們就來作這樣一個插件,讀取這些配置信息的數據.首先在包名com.xfhy.plugin下面建立AndroidExtension.groovy,它是一個bean對象,用來保存信息的.定義以下:ide

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插件不少時候能方便咱們進行一些騷操做,用處仍是挺大的.

參考

相關文章
相關標籤/搜索