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()
推荐阅读
-
零基础学习教程之Linux下搭建android开发环境
-
android开发基础教程—SharedPreferences读写
-
android开发基础教程—三种方式实现xml文件解析
-
android开发基础教程—打电话发短信
-
零基础学习教程之Linux下搭建android开发环境
-
详解如何使用Android Studio开发Gradle插件
-
解析离线安装Eclipse的Android ADT开发插件的具体操作(图文)
-
Android开发基础之创建启动界面Splash Screen的方法
-
Android gradle插件打印时间戳的方法详解
-
android开发基础教程—SharedPreferences读写