Android Gradle Plugin插件开发——基础

结合现有开源项目讲述 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


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会依次往下传递,这是打包执行的顺序:


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

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()

展开阅读全文

没有更多推荐了,返回首页