欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Android Gradle Plugin插件开发——基础

程序员文章站 2022-06-15 20:33:35
...

结合现有开源项目讲述 GradlePluginDemo

本文有三篇讲解Android Gradle Plugin

<1>Android Gradle Plugin插件开发——基础

<2>Android Gradle Plugin插件开发——进阶

<3>Android Gradle Plugin插件开发——出师

1.首先创建一个module为Library,这里创建名称为method_timer

2.在src/main下文件全部删除,然后创建打勾文件,groovy文件拓展名为.groovy

Android Gradle Plugin插件开发——基础

com.uis.methodtimer.properties里面加上:

implementation-class=com.uis.methodtimer.MethodTimerPlugin
apply plugin: 'com.uis.methodtimer'//当使用插件的时候使用,此处文件名就是使用插件的名称:

class MethodTimerPlugin implements Plugin<Project> {
    @Override
    void apply(Project project) {
        if(project.hasProperty("android")){
            project.android.registerTransform(new MethodTimerTransform(project))
        }
    }
}

此处的Transform只做了一个时间统计

class MethodTimerTransform extends Transform {
    Project project
    MethodTimerTransform(Project project) {
        this.project = project
    }
    @Override
    String getName() {
        return "MethodTimerTransform"
    }
    @Override
    Set<QualifiedContent.ContentType> getInputTypes() {
        return TransformManager.CONTENT_CLASS
    }
    @Override
    Set<? super QualifiedContent.Scope> getScopes() {
        return TransformManager.SCOPE_FULL_PROJECT
    }
    @Override
    boolean isIncremental() {
        return false
    }
    @Override
    void transform(TransformInvocation invocation) throws TransformException, InterruptedException, IOException {
        long startTime = System.currentTimeMillis()
        DirectoryInput dir
        HashSet<JarInput> jar = new HashSet()
        invocation.inputs.each {input->
            input.directoryInputs.each {//工程下的目录
                if(dir == null && it.file != null)
                    dir = it
            }
            input.jarInputs.each {//jar和aar中的jar
                jar.add(it)
            }
        }        
	def dest = invocation.outputProvider.getContentLocation(dir.name,dir.contentTypes,dir.scopes, Format.DIRECTORY)
	FileUtils.copyDirectory(dir.file,dest)//目录输出
        ar.each {//jar输出 ,md5采用jar包名称,因为在重复打包过程中,jar路径会变化,导致包重复
            def newName = it.name.replace(".jar","")+DigestUtils.md5Hex(it.name)//it.name是jar包名称,对应名称唯一
            def desFile = invocation.outputProvider.getContentLocation(newName,it.contentTypes, it.scopes, Format.JAR)//信息会存在json中
            FileUtils.copyFile(it.file, desFile)
        }
        roject.logger.quiet("------${getName()}costtime-----"+(System.currentTimeMillis()-startTime)+"ms")
    }

3.在插件module下gradle加入:

apply plugin: 'groovy'
apply plugin: 'maven'

dependencies {
    compile gradleApi()
    compile localGroovy()
    compile 'com.android.tools.build:gradle:3.0.0'
    compile 'org.javassist:javassist:3.22.0-GA'//用于代码注入
    compile 'com.android.tools.build:transform-api:1.5.0'
}
repositories{
    jcenter()
    mavenCentral()
}

uploadArchives {
        repositories {
            mavenDeployer {//用于发布本地maven
                pom.groupId = "com.uis.methodtimer"
                pom.artifactId = "MethodTimer"
                pom.version = "0.0.1-SNAPSHOT"
                repository(url: uri('../repo'))
            }
        }
    }
task sourcesJar(type: Jar) {
    from project.sourceSets.main.groovy.srcDirs
    classifier = 'sources'
}
task javadocJar(type: Jar, dependsOn: groovydoc) {
    classifier = 'javadoc'
    from groovydoc.destinationDir
}
artifacts {
    archives javadocJar
    archives sourcesJar
}
windows使用 gradle :method_timer:uploadArchives发布本地maven,mac使用 ./gradleW :method_timer:uploadArchives

在project下gradle加入:

buildscript {
    repositories {
        jcenter()
        google()
        mavenCentral()
        maven{
            url uri('./repo')//本地maven,用于发布测试插件
        }
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.0.0'
        classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.7.3'
        classpath 'com.uis.methodtimer:MethodTimer:0.0.1-SNAPSHOT'//本地maven
    }
}

4.当在module使用 apply plugin: 'com.uis.methodtimer' 的时候会通过上面properties中定义的implementation-class的值找到com.uis.methodtimer.MethodTImerPlugin,之后调用其中的void apply(Project project);此处对于android项目,会把MethodTimerTransform注册到project中,你在当前的Module中的Tasks中可以找到
apply plugin->plugin properties->apply()->transfor()

5.当执行 ./gradlew :app:assembleDebug的时候,先执行资源,compileJavaWithJavac等task,之后执行Transform,之后转换成dex,在与资源文件打成apk包后混淆,分包,签名,刚刚在MethodTImerPlugin中注册的MethodTimerTransform是在Transform时候执行,多个transform会依次往下传递,这是打包执行的顺序:

Android Gradle Plugin插件开发——基础

如果需要查看详细信息,加上如下代码

class TimingsListener implements TaskExecutionListener, BuildListener {
    private Clock clock
    private timings = []
    @Override
    void beforeExecute(Task task) {
        clock = new org.gradle.util.Clock()
    }
    @Override
    void afterExecute(Task task, TaskState taskState) {
        def ms = clock.timeInMs
        timings.add([ms, task.path])
        task.project.logger.warn "${task.path} took ${ms}ms"
    }
    @Override
    void buildFinished(BuildResult result) {
        println result.action+"#Task timings:"
        for (timing in timings) {
            if (timing[0] >= 50) {
                printf "%7sms  %s\n", timing
            }
        }
    }
    @Override
    void buildStarted(Gradle gradle) {}
    @Override
    void projectsEvaluated(Gradle gradle) {}
    @Override
    void projectsLoaded(Gradle gradle) {}
    @Override
    void settingsEvaluated(Settings settings) {}
}
gradle.addListener new TimingsListener()

相关标签: gradle plugin