1、介绍和环境搭建
DSL(domain specific language):领域特定语言,解决特定问题,包括Groovy,xml等等。
Groovy是一种基于JVM的敏捷开发语言,可以使用java所用的库。
Groovy官网
http://groovy-lang.org/
下载最新稳定版本(the latest stable version of Groovy)-2.5.8版本。
检查环境变量配置
groovy -version
在Android studio中Tools - Groovy Console直接编写Groovy语言。
println "hello groovy"
2、语法
2.1、基础语法
groovy变量的类型都是对象类型,没有基本类型,因为基本类型都会装箱成对象类型。
变量的定义包括强类型定义和弱类型def定义。
def x = 10
println x.class //class java.lang.Integer
字符串除了String还有GString,GString的常用三种定义方式
def s1 = 'a single \'a\' String'
println s1 //a single 'a' String
def s2 = '''\
line one
line two
line three
'''
println s2 //line one
//line two
//line three
def s3 = "a common String"
def say = "this is ${s3}" //花括号可扩展任意的表达式
println say //this is a common String
println say.class //class org.codehaus.groovy.runtime.GStringImpl
新增常用操作符
def str = "groovy"
//println str.center(9,'a') //agroovyaa
//println str.padLeft(9,'a') //aaagroovy
//println str.padRight(9,'a') //groovyaaa
def str2 = 'Hello'
println str > str2 //true
println str[0] //g
println str[0..1] //gr
def str3 = 'gro'
println str.minus(str3) //ovy
println str - str3 //ovy
//println str.reverse() //yvoorg
println str.capitalize() //Groovy
println str.isNumber() //false
逻辑控制:
switch
def x = 1.23
def result
switch (x){
case "str":
result = 'str'
break
case [4,6,7,'inlist']: //list
result = 'list'
break
case 12..30: //范围
result = 'range'
break
case Integer:
result = 'Integer'
break
case BigDecimal:
result = 'BigDecimal'
break
default:result = 'default'
}
println result //BigDecimal
for范围
def sum = 0
for (i in 0..9){
sum += i
}
println sum //45
list循环
def sum = 0
for (i in [1,2,3,4,5,6,7,8,9]){
sum += i
}
println sum //45
map循环
def sum = 0
for (i in ['wang':1,'zhang':2,'li':3]){
sum += i.value
}
println sum //6
2.2、闭包
类似于方法
def clouser = { println "Hello groovy"}
clouser.call() //调用方式一,Hello groovy
clouser() //调用方式二,Hello groovy
有参数的闭包->
前的是参数,也可以有多个参数
def clouser = {String name -> println "${name} Hello groovy"}
clouser.call("this is") //调用方式一,this is Hello groovy
clouser("this is") //调用方式二,this is Hello groovy
隐式的it参数,不需要定义参数
def clouser = {println "Hello ${it}"}
clouser("groovy") //Hello groovy
返回值
def clouser = {String name -> return "Hello ${name}"}
println clouser("groovy") //Hello groovy
基本类型和闭包结合使用
int x = cal(5)
println x
//num的阶乘
int fab(int number) {
int result = 1
1.upto(number, { num -> result *= num })
return result
}
int fab2(int number) {
int result = 1
number.downto(1) {
num -> result *= num
}
return result
}
//累加
int cal(int number) {
int result = 0
number.times {
num -> result += num
}
return result
}
字符串和闭包结合使用
String str = '2 and 3 is 5'
//each遍历
str.each {
// String temp -> println temp.multiply(2)
String temp -> println temp
}
//find查找符合条件的第一个,findAll查找所有符合条件的放到集合
println str.find{
String s -> s.isNumber()
}
def list = str.findAll{
String s -> s.isNumber()
}
println list.toListString() //[2, 3, 5]
def result = str.any {
String s -> s.isNumber() //有一项是数字就返回true
}
println result //true
println str.every { //false
String s -> s.isNumber() //每一项都是数字就返回true
}
def list2 = str.collect{
it.toUpperCase()
}
println list2.toListString() //[2, , A, N, D, , 3, , I, S, , 5]
闭包进阶
变量:this、owner、delegate
def scriptClouser = {
println "this:" + this //代表闭包定义处的类
println "owner:" + owner //代表闭包定义处的类或者对象
println "delegate:" + delegate //代表任意对象,默认与owner一致
}
scriptClouser.call()
class Person{//内部类
def classClouser = {
println "classClouser this:" + this //代表闭包定义处的类
println "classClouser owner:" + owner //代表闭包定义处的类或者对象
println "classClouser delegate:" + delegate //代表任意对象,默认与owner一致
}
def say(){
def classClouser = {
println "method classClouser this:" + this //代表闭包定义处的类
println "method classClouser owner:" + owner //代表闭包定义处的类或者对象
println "method classClouser delegate:" + delegate //代表任意对象,默认与owner一致
}
classClouser.call()
}
}
Person person = new Person()
person.classClouser.call()
person.say()
def nextClouser = {
def innerClouser = {
println "innerClouser this:" + this //代表闭包定义处的类
println "innerClouser owner:" + owner //代表闭包定义处的类或者对象
println "innerClouser delegate:" + delegate //代表任意对象,默认与owner一致
}
innerClouser.delegate = person //修改delegate
innerClouser.call()
}
nextClouser.call()
闭包委托策略
class Student {
String name
def pretty = {
"My name is ${name}"
}
String toSting(){
pretty.call()
}
}
class Teacher {
String name
}
def stu = new Student(name: 'Sarash')
def tea = new Teacher(name: 'Qndroid')
stu.pretty.delegate = tea
stu.pretty.resolveStrategy = Closure.DELEGATE_FIRST//delegate优先
println stu.toSting() //My name is Qndroid
2.3、列表list
数组和列表定义方式
def array = [1, 2, 3, 4, 5, 6] as int[]
int[] array2 = [1, 2, 3, 4, 5, 6]
def list = [1, 2, 3, 4, 5, 6]
主要介绍特有的
//排序
def sortList = [1, -4, 5, -6, 2, 3]
//Collections.sort(sortList)
//println sortList //[-6, -4, 1, 2, 3, 5]
sortList.sort()
println sortList //[-6, -4, 1, 2, 3, 5]
//自定义排序
//Comparator mc = { a, b ->
// a == b ? 0 : Math.abs(a) < Math.abs(b) ? -1 : 1
//}
//Collections.sort(sortList, mc)
//println sortList //[1, 2, 3, -4, 5, -6]
sortList.sort { a, b ->
a == b ? 0 : Math.abs(a) < Math.abs(b) ? -1 : 1
}
println sortList //[1, 2, 3, -4, 5, -6]
//字符串排序
def sortStringList = ['123', 'a', 'groovy']
sortStringList.sort { it -> return it.size() }
println sortStringList //[a, 123, groovy]
//查找
def findList = [-3, 8, -8, 12, 4, 7]
int result = findList.find { return it % 2 == 0 }
println result //8
def result2 = findList.findAll { return it % 2 == 0 }
println result2.toListString() //[8, -8, 12, 4]
def result3 = findList.any { return it % 2 != 0 }
println result3 //true
def result4 = findList.every { return it % 2 != 0 }
println result4 //false
println findList.min() //-8
println findList.max() //12
def num = findList.count { return it % 2 == 0 } //符合条件的个数
println num //4
2.4、映射map
定义和基本操作
def colors = [red: 'ff0000', green: '00ff00', blue: '0000ff']
println colors.getClass() //class java.util.LinkedHashMap
//索引
println colors['red'] //ff0000
println colors.red //ff0000
//添加
colors.yellow = 'ffff00'
println colors.toMapString() //[red:ff0000, green:00ff00, blue:0000ff, yellow:ffff00]
其他操作
def students = [
1: [number: '0001', name: 'zhang', score: 55, sex: 'male'],
2: [number: '0002', name: 'li', score: 62, sex: 'female'],
3: [number: '0003', name: 'wang', score: 63, sex: 'female'],
4: [number: '0004', name: 'zhao', score: 66, sex: 'male']
]
//遍历
students.each {
def student -> println student.key + ":" + student.value
}
//带索引
students.eachWithIndex {
def student, int index -> println index + '::' + student.key + ":" + student.value
}
//直接遍历
students.each {
key, value -> println key + ":" + value
}
students.eachWithIndex {
key, value, index -> println index + ':::' + key + ":" + value
}
//查找
def entry = students.find { def student ->
return student.value.score >= 60
}
println entry //2={number=0002, name=li, score=62, sex=female}
def entry2 = students.findAll { def student ->
return student.value.score >= 60
}
println entry2
//计数
def count = students.count {
def student -> return student.value.score >= 60 && student.value.sex == 'male'
}
println count //1
//查找并筛选
def names = students.findAll {
def student -> return student.value.score >= 60
}.collect {
return it.value.name
}
println names //[li, wang, zhao]
//分组
def group = students.groupBy {
def student -> return student.value.score >= 60 ? '及格' : '不及格'
}
println group.toMapString()
//排序
def sort = students.sort{
def stu1 ,def stu2->
Number num1 = stu1.value.score
Number num2 = stu2.value.score
return num1 == num2 ? 0 : num1 < num2 ? -1 : 1
}
println sort.toMapString()
2.5、范围range
定义和使用
def range = 1..10
println range[0] //1
println range.contains(10) //true
println range.from //1
println range.to //10
//遍历
range.each {
println it
}
//switch中使用
def result = getGrade(75)
println result
def getGrade(Number number){
def result
switch (number){
case 0..<60:
result = '不及格'
break
case 60..<70:
result = '及格'
break
case 70..<80:
result = '良好'
break
case 80..100:
result = '优秀'
break
}
return result
}
2.6、面向对象
类、方法、接口
//groovy中默认都是public类型
class Person implements Action{
String name
Integer age
def increasseAge(Integer years) {
this.age += years
}
@Override
void eat() {}
@Override
void drink() {}
@Override
void play() {}
}
def person = new Person(name: "zhang", age: 26)
println "name:${person.name},age:${person.age}"//name:zhang,age:26
person.increasseAge(10)
println "name:${person.name},age:${person.age}"//name:zhang,age:36
interface Action{
void eat()
void drink()
void play()
}
trait DefaultAction{
abstract void eat()
void play(){
println 'i can play'
}
}
元编程
class Person {
String name
Integer age
def increasseAge(Integer years) {
this.age += years
}
//一个方法找不到时候,用它代替
def invokeMethod(String name, Object args) {
return "invokeMethod: ${name},${args}"
}
//优先级高于invokeMethod
def methodMissing(String name, Object args) {
return "methodMissing: ${name},${args}"
}
}
def person = new Person(name: 'zhang', age: 26)
println person.cry()
//为类动态添加属性
Person.metaClass.sex = 'male'
def person1 = new Person(name: 'zhang', age: 26)
println person1.sex //male
//为类动态添加方法
Person.metaClass.sexUpperCase = { -> sex.toUpperCase() }
def personn2 = new Person(name: 'zhang', age: 26)
println personn2.sexUpperCase() //MALE
//添加静态方法
Person.metaClass.static.createPerson = {
String name, int age -> new Person(name: name, age: age)
}
def personn3 = Person.createPerson('li', 18)
println personn3.name + personn3.age //li18
一次注入,应用程序其他方法都可以使用
ExpandoMetaClass.enableGlobally()
3、高级用法
3.1、json文件处理
转换成json
import groovy.json.JsonOutput
import groovy.json.JsonSlurper
class Person {
String name
Integer age
}
//转换成Json
def list = [new Person(name: 'zhang', age: 26),
new Person(name: 'li', age: 22)]
def json = JsonOutput.toJson(list)
println JsonOutput.prettyPrint(json)
//转成实体对象
def jsonSlpuer = new JsonSlurper()
jsonSlpuer.parseText()
get请求
import groovy.json.JsonSlurper
def response = getNetworkData("http://httpbin.org/get?id=123")
println response.args.id
def getNetworkData(String url){
def connection = new URL(url).openConnection()
connection.setRequestMethod('GET')
connection.connect()
def response = connection.content.text
def jsonSlurper = new JsonSlurper()
return jsonSlurper.parseText(response)
}
3.2、xml读取和生成
解析xml格式数据,创建xml格式数据,都不再详解
3.3、文件操作
读取文件
def file = new File("目标文件")
//方式一
file.eachLine {
line -> println line
}
//方式二
def text = file.getText()
println text
//方式三
def result = file.readLines()
println result
//方式四,读取部分内容
def reader = file.withReader {
reader -> char[] buffer = new char[100]
reader.read(buffer)
return buffer
}
println reader
拷贝文件
def copy(String sourcePath, String destationPath) {
try {
def desFile = new File(destationPath)
if (!desFile.exists()) {
desFile.createNewFile()
}
new File(sourcePath).withReader {
reader ->
def lines = reader.readLines()
desFile.withWriter {
writer ->
lines.each {
line -> writer.append(line + "\r\n")
}
}
}
return true
} catch (Exception e) {
}
}
对象的读写
def saveObject(Object object, String path) {
try {
def desFile = new File(path)
if (!desFile.exists()) {
desFile.createNewFile()
}
desFile.withObjectOutputStream {
out -> out.writeObject(object)
}
return true
} catch (Exception e) {
}
return false
}
def readObject(String path) {
def obj = null
try {
def file = new File(path)
if (file == null || !file.exists()) return null
file.withObjectInputStream {
input -> obj = input.readObject()
}
} catch (Exception e) {
}
return obj
}
4、Gradle介绍
Gradle用于构建应用程序,使用Groovy核心语法。
在Terminal中执行
gradlew clean //win
gradlew build //win
./gradlew clean //mac
./gradlew build //mac
gradle的生命周期
initialization初始化阶段:根据settings.gradle解析整个工程中所有的Project,构建所有的Project对应的project对象。
Configuration配置阶段:解析所有的projects对象中的task,构建好所有的task的拓扑图
Excution执行阶段:执行具体的task及其依赖task
生命周期监听
//配置阶段开始前的监听回调
this.beforeEvaluate {
println '------配置阶段开始------'
}
//配置阶段完成以后的监听回调
this.afterEvaluate {
println '------配置阶段完成------'
}
//gradle执行完毕后的回调监听
this.gradle.buildFinished {
println '------gradle执行完毕------'
}
//等同beforeEvaluate
this.gradle.beforeProject {}
//等同afterEvaluate
this.gradle.afterProject {}
5、Project
查看Project的个数
gradlew projects
./gradlew projects //mac
5.1、Project相关API
在最外层的根的build.gradle中
this.getProjects()
def getProjects(){
//只输全部projects
this.getAllprojects().eachWithIndex {
Project project, int index ->
if (index ==0){
println "this is Root project:${project.name}"
} else {
println "this is project:${project.name}"
}
}
//只输出子projects
this.getSubprojects().eachWithIndex {
Project project, int index ->
println "this is project:${project.name}"
}
//只输出根projects
println "this is Root project:" + this.getRootProject().name
}
在module的build.gradle中
//只输出父projects
println "this is parent project:" + this.getParent().name
根project中可以配置module的配置
//根project配置module为app的配置
project('app') {
Project project ->
println project.name //app
apply plugin: 'com.android.application'
group 'com.tea'
version '1.0.0-release'
dependencies {}
android {}
}
配置当前节点工程和subproject的所有project
//配置当前节点工程和subproject的所有project
allprojects {
group 'com.tea'
version '1.0.0-release'
}
println project('app').group
不包括当前节点工程,只包括他的subproject
//不包括当前节点工程,只包括他的subproject
subprojects {
Project project ->
if (project.plugins.hasPlugin('com.android.library')) {
apply from: '../publistTOMaven.gradle'
}
}
5.2、属性相关API
定义扩展属性
ext{}
所以提供扩展属性定义方式:
方式一:
可以在根build中定义
ext {
compileSdkVersion = 28
cardview = 'com.android.support:cardview-v7:28.0.0'
}
然后在需要用的build中引用
compileSdkVersion this.rootProject.compileSdkVersion
implementation this.cardview
方式二:
和根build同级定义common.gradle
ext {
android = [compileSdkVersion: 28,
buildToolsVersion: '26.0.0',
applicationId : 'com.tea',
minSdkVersion : 16,
targetSdkVersion : 26,
versionCode : 1,
versionName : '1.0.0',
multiDexEnabled : true]
signConfigs = ['storeFile' : 'tea.jks',
'storePassword': 'tea123456',
'keyAlias' : 'android',
'keyPassword' : 'tea123456']
java = ['javaVersion': JavaVersion.VERSION_1_8]
dependence = ['libCardview' : 'com.android.support:cardview-v7:28.0.0',
'libAppcompat': 'com.android.support:appcompat-v7:28.0.0']
}
在根build中引入
apply from: this.file('common.gradle')
在需要的build中使用
compileSdkVersion rootProject.ext.android.compileSdkVersion
implementation rootProject.ext.dependence.libCardview
方式三:
在gradle.properties中定义key:value
形式
mCompileSdkVersion = 28
build中使用,默认都是字符串,需要转换
compileSdkVersion mCompileSdkVersion.toInteger()
5.3、file相关API
文件路径获取
println getRootDir().absolutePath
println getBuildDir().absolutePath
println getProjectDir().absolutePath
文件定位
apply from: this.file('common.gradle')
println getContent('common.gradle')
def getContent(String path){
try {
//路径是相对于当前project查找
def file = file(path)
return file.text
}catch (GradleException e){
println "not found"
}
return null
}
文件拷贝,在app的build中拷贝文件或者文件夹
copy {
from file('build/outputs/apk/')
into getRootProject().getBuildDir().path + '/apk/'
exclude {}//补拷贝的文件
rename {}//重命名
}
文件树
fileTree('src/main/assets/'){FileTree fileTree ->
fileTree.visit {FileTreeElement element ->
println element.file.name
copy {
from element.file
into getRootProject().getBuildDir().path + '/test/'
}
}
}
5.4、依赖相关API
依赖
buildscript {
//配置工程的仓库地址
repositories { }
//配置工程的gradle插件依赖地址,app中的是项目的第三库依赖
dependencies { }
}
依赖冲突常用解决办法
compile ('rootProject.ext.dependence.libAutoScrollViewPager') {
exclude module: 'support-v4'//排除依赖
exclude group: 'com.android.support'
transitive false//禁止传递依赖
}
provided只在编译起作用,占位编译。
5.5、外部命令API
调用系统指令,执行./gradlew apkcopy
task(name: 'apkcopy') {
doLast {
def srcPath = this.buildDir.path + '/outputs/apk'
def destPath = './target/apk'
def command = "mv -f ${srcPath} ${destPath}"
exec {
try {
executable 'bash'
args '-c', command
println 'this command exec success'
}catch(GradleException e){
println 'this command exec error'
}
}
}
}
调用脚本
task stopTomcat(type:Exec) {
//dir
workingDir '../tomcat/bin'
//windows
commandLine 'cmd', '/c', 'stop.bat'
//linux
commandLine './stop.sh'
}
6、task
两种定义方式
task helloTask (group: 'com.tea',description: 'study'){
println '---------helloTask'
}
this.tasks.create(name : 'helloTask2'){
setGroup('com.tea')
setDescription('study')
println '---------helloTask2'
}
doFirst和doLast
task helloTask (group: 'com.tea',description: 'study'){
println '---------helloTask'
doFirst {
println '---------helloTask---doFirst'
}
}
helloTask.doFirst{
println '---------helloTask---doFirst2'//比闭包的先执行
}
统计Build时长
def startTime,endTime
this.afterEvaluate {Project project ->
def preBuildTask = project.tasks.getByName('preBuild')
preBuildTask.doFirst {
startTime = System.currentTimeMillis()
println "==============:" + startTime
}
def buildTask = project.tasks.getByName('build')
buildTask.doLast {
endTime = System.currentTimeMillis()
println "==============:" + endTime
println "==============:" + (endTime - startTime)
}
}
依赖
task taskX {
doLast {
println "taskX"
}
}
task taskY {
doLast {
println "taskY"
}
}
//动态依赖
task taskZ {
dependsOn this.tasks.findAll {
task ->
println task.name
return task.name.startsWith('taskX')
}
doLast {
println "taskZ"
}
}
//静态依赖
task taskZ(dependsOn: [taskX, taskY]) {
dependsOn this.tasks.findAll {
task -> return task.name.startsWith('lib')
}
doLast {
println "taskZ"
}
}
//或者
taskZ.dependsOn(taskX, taskY)
输入输出
task writeTask{
//输入
inputs.property("key","value")
def data = inputs.getProperties()
//输出
outputs.file 文件
File file = outputs.getFiles().getSingleFile()
}
执行顺序指定
mustRunAfter
7、其他模块
7.1、SourceSet
修改资源路径
sourceSets {
main{
jniLibs.srcDirs = ['libs']//修改so库文件位置
}
}
给res分模块分包
sourceSets {
main{
res.srcDirs = ['src/main/res',
'src/main/res-ad',
'src/main/res-tea']
}
}
7.2、自定义plugin
main下的java替换成groovy,新建.groovy类:
class GradleStudyPlugin implements Plugin<Project>{
@Override
void apply (Project project){
project.extensions.create('comTea',xxx(groovy类))
}
}
自定义task的类
class xxxxx extend DefaultTask{
@TaskAction
void doAction(){
//执行于gradle执行阶段的代码
}
}
main/resources/META-INF.gradle/包名.properties:
implementation-class=包名.类名
build.gradle为:
apply plugin: 'groovy'
sourceSets {
main{
groovy {
srcDir 'src/main/groovy'
}
resources {
srcDir 'src/main/resources'
}
}
}
引用和传参
apply plugin: '包名'
comTea{
//传参
}
7.3、修改apk名字
app的build中
this.afterEvaluate {
this.android.applicationVariants.all { variant ->
def output = variant.outputs.first()
def apkName = "app-${variant.baseName}" + "-${variant.versionName}.apk"
output.outputFile = new File(output.outputFile.parent,apkName)
println "------------------"
}
}
8、Jenkins
java -jar jenkins.war
Android实战应用
buildTypes和productFlavors
和main同级别,同包名,创建文件,区别使用debug还是release。可以用来实现类似gradle调用java类。
implementation
implementation:不会传递依赖;compile / api:会传递依赖;api 是 compile 的替代品。当依赖被传递时,二级依赖的改动会导致0级项目重新编译;当依赖不传递时,二级依赖的改动不会导致 0 级项目重新编译。
plugin
android{}
的内容就是对apply plugin: 'com.android.application'
的配置。
参考上述7.2、自定义plugin
。
新建Module-Java Library
-buildSrc模块
创建目录\buildSrc\src\main\resources\META-INF\gradle-plugins
,创建文件xxx.properties
implementation-class=com.plugin.demo.PluginDemo
目录buildSrc\src\main\groovy\com\plugin\demo
创建文件PluginDemo.groovy
import com.android.build.gradle.BaseExtension
import org.gradle.api.Plugin
import org.gradle.api.Project
public class PluginDemo implements Plugin<Project> {
@Override
public void apply(Project project) {
def extension = project.extensions.create('yyyy', ExtensionDemo)
project.afterEvaluate {
println "Hello ${extension.name}!"//Hello zzzzz
}
//def transform = new TransformDemo()
//def baseExtension = project.extensions.getByType(BaseExtension)
//baseExtension.registerTransform(transform)
}
}
创建文件ExtensionDemo.groovy
public class ExtensionDemo {
def name = "Author";
}
在app的build中使用plugin
apply plugin: 'xxx'
yyyy {
name 'zzzzz'
}
关于 buildSrc 目录:这是 gradle 的一个特殊目录,这个目录的 build.gradle 会自动被执行,即使不配配置进settings.gradle
。buildSrc 的执行早于任何一个 project,也早于 settings.gradle。它是一个独立的存在。 buildSrc 所配置出来的 Plugin 会被自动添加到编译过程中的每一个 project 的 classpath,因此它们才可以直接使用 apply plugin: 'xxx'
的方式来便捷应用这些 plugin。
settings.gradle 中如果配置了 ‘:buildSrc’ ,buildSrc 目录就会被当做是子 Project ,因此会被执行两遍。所以在 settings.gradle 里面应该删掉 :buildSrc
的配置。
Transform
Transform是由 Android 提供的,在项目构建过程中把编译后的文件(jar文件和 class文件)添加自定义的中间处理过程的工具。下面代码只是把编译完的内容原封不动搬运到目标位置,没有实际用处。要修改字节码,需要引入其他工具,例如 javassist。
新建TransformDemo.groovy
import com.android.build.api.transform.Format
import com.android.build.api.transform.QualifiedContent
import com.android.build.api.transform.Transform
import com.android.build.api.transform.TransformException
import com.android.build.api.transform.TransformInvocation
import com.android.build.gradle.internal.pipeline.TransformManager
import com.android.utils.FileUtils;
public class TransformDemo extends Transform {
@Override
String getName() {
return "hencoderTransform"
}
@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 transformInvocation) throws TransformException, InterruptedException, IOException {
def inputs = transformInvocation.inputs
def outputProvider = transformInvocation.outputProvider
inputs.each {
it.jarInputs.each {
File dest = outputProvider.getContentLocation(it.name, it.contentTypes, it.scopes, Format.JAR)
FileUtils.copyFile(it.file, dest)
}
it.directoryInputs.each {
File dest = outputProvider.getContentLocation(it.name, it.contentTypes, it.scopes, Format.DIRECTORY)
FileUtils.copyDirectory(it.file, dest)
}
}
}
}
buildSrc-build中改为:
repositories {
google()
jcenter()
}
dependencies {
implementation 'com.android.tools.build:gradle:3.2.1'
}
PluginDemo.groovy中添加代码
def transform = new TransformDemo()
def baseExtension = project.extensions.getByType(BaseExtension)
baseExtension.registerTransform(transform)
修改app-build中的plugin放在android{}之后。
示例:https://github.com/liangzhitao/consuming-collector