Gradle Plugin

Posted by OOFTF Blog on April 15, 2021

如何编写一个 Gradle 插件

项目结构

Plugin 项目结构

build.gradle ###

1
2
3
4
5
6
7
8
apply plugin: 'groovy'

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    //gradle-api-6.7.1 对应 gradle/wrapper/gradle-wrapper.properties 文件内声明的版本 
    implementation gradleApi()  
}

ooftf-spy.properties

1
implementation-class=com.ooftf.spy.plugin.ApiInspectPlugin

ApiInspectPlugin

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package com.ooftf.spy.plugin
import org.gradle.api.Plugin
import org.gradle.api.Project

/**
 * Created by ooftf on 2021/3/2.
 */
class ApiInspectPlugin implements Plugin<Project> {

    @Override
    void apply(Project project) {
        // TODO SOMETING
    }
}

Extension

ApiInspectExtension

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package com.ooftf.spy.plugin

import org.gradle.api.Action
import org.gradle.api.Project
import org.gradle.api.model.ObjectFactory

/**
 * Created by ooftf on 2021/3/2.
 */
class ApiInspectExtension {

    boolean enable = true
    boolean inspectSystemApi = false
    boolean interruptBuild = true
    ApiInspectExcludeExtension exclude
    ApiInspectExtension(Project project) {
        try {
            ObjectFactory objectFactory = project.getObjects()
            exclude = objectFactory.newInstance(ApiInspectExcludeExtension.class)
        } catch (Exception e) {
            exclude = ApiInspectExcludeExtension.class.newInstance()
        }
    }
    void exclude(Action<ApiInspectExcludeExtension> action) {
        action.execute(exclude)
    }
}

ApiInspectExcludeExtension

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package com.ooftf.spy.plugin
import com.google.common.base.Strings

/**
 * Created by ooftf on 2021/3/2.
 */
class ApiInspectExcludeExtension {
    Set<FilterItem> apis = new HashSet<>()
    void api(String name = "", String occurName = "", String method = "", String lineNumber = "") {
        if (Strings.isNullOrEmpty(name) && Strings.isNullOrEmpty(occurName) && Strings.isNullOrEmpty(method) && Strings.isNullOrEmpty(lineNumber))
            return
        FilterItem item = new FilterItem()
        item.name = name
        item.occurName = occurName
        item.method = method
        item.lines = lineNumber
        apis.add(item)
    }
}

获取 Extension 数据

1
2
3
4
5
6
7
8
9
class ApiInspectPlugin implements Plugin<Project> {

    @Override
    void apply(Project project) {
        project.extensions.create("spy", ApiInspectExtension.class, project)    
        ApiInspectExtension apiInspectExtension = project.extensions.findByType(ApiInspectExtension.class)
    }
}

使用插件 gradle.build

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
apply plugin: 'ooftf-spy' // ooftf-spy 对应\resources\META-INF\gradle-plugins\ooftf-spy.properties 的文件名
// spy 对应  project.extensions.create("spy", ApiInspectExtension.class, project) 第一个参数"spy"
// spy 内部结构对应 ApiInspectExtension 的结构
spy {
    enable true //Whether api inspect is enabled.
    inspectSystemApi false //Whether to inspect the system api.
    interruptBuild false //Whether interrupt build when find error
    // 对应 ApiInspectExtension.exclude(Action<ApiInspectExcludeExtension> action)
    exclude {
        // 对应 ApiInspectExcludeExtension.api(String name = "", String occurName = "", String method = "", String lineNumber = "")
        api 'com.blankj.utilcode.', 'com.didichuxing.doraemonkit.'
        api 'com.blankj.utilcode.', 'com.didichuxing.doraemonkit.'
        api 'okhttp3.internal.platform.Platform', 'okhttp3.logging.HttpLoggingInterceptor'
        api 'kotlinx.atomicfu.InterceptorKt', 'kotlinx.atomicfu.AtomicFU'
    }
}

指定 plugin 名字的两种方式,选其一

1. \resources\META-INF\gradle-plugins\ooftf-spy.properties

1
implementation-class=com.ooftf.spy.plugin.ApiInspectPlugin

2. build.groovy (新,推荐)

1
2
3
4
5
6
7
8
9
10
11
12
plugins {
    id 'java-gradle-plugin'
}
gradlePlugin {
    plugins {
        simplePlugin {
            id = 'ooftf-spy'
            implementationClass = 'com.ooftf.spy.plugin.ApiInspectPlugin'
        }
    }
}