资料
Android Gradle Plugin插件开发——基础Android Gradle Plugin插件开发——进阶
Android Studio Plugin 插件开发教程(一) —— 开发你的第一个插件Android Studio Plugin 插件开发教程(二) —— 插件SDK中的常用对象介绍
Android Studio Plugin 插件开发教程(三) —— 制作一个自动生成数据库代码的插件
Android Studio Plugin 插件开发教程(四) —— 为自动生成数据库代码的插件添加UI
buildSrc使用,依赖统一管理
Android Gradle 插件版本说明
Gradle学习系列(一):Groovy学习Gradle学习系列(二):Gradle核心探索
Gradle学习系列(三):Gradle插件
Gradle学习系列(四):Gradle依赖
Gradle学习系列(六):Gradle 源码解析
Gradle学习系列(七):Android Gradle Plugin 源码解析
项目结构
1. 新建buildSrc目录
gradle sync一下,就可以自动识别该目录
2. 建目录
路径有:
src/main/groovy (包名)
com/joyy/router/*.groovy
src/main/resources/META-INF/gradle-plugins/(资源路径)
com.joyy.router.properties
2.1 src/main/groovy中是你要开发的代码
一般都用package管理,但不强制
MyPlugin.groovy 对外提供的plugin
package com.joyy.router
import org.gradle.api.Plugin
import org.gradle.api.Project
class MyPlugin implements Plugin<Project> {
@Override
void apply(Project target) {
println "MyPlugin apply(Project)"
//target.android.registerTransform(new MyTransform(target))
target.android.registerTransform(new TimePluginTransform())
}
}
TimePluginTransform
package com.joyy.router;
import com.android.build.api.transform.*;
import com.android.build.gradle.internal.pipeline.TransformManager
import com.android.utils.FileUtils
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassReader
import org.objectweb.asm.ClassWriter;
class TimePluginTransform extends Transform {
@Override
public String getName() {
return TimePluginTransform.class.getSimpleName()
}
@Override
public Set<QualifiedContent.ContentType> getInputTypes() {
return TransformManager.CONTENT_CLASS
}
/**
* 指Transform要操作内容的范围,官方文档Scope有7种类型:
* <p>
* EXTERNAL_LIBRARIES 只有外部库
* PROJECT 只有项目内容
* PROJECT_LOCAL_DEPS 只有项目的本地依赖(本地jar)
* PROVIDED_ONLY 只提供本地或远程依赖项
* SUB_PROJECTS 只有子项目。
* SUB_PROJECTS_LOCAL_DEPS 只有子项目的本地依赖项(本地jar)。
* TESTED_CODE 由当前变量(包括依赖项)测试的代码
* SCOPE_FULL_PROJECT 整个项目
*/
@Override
public Set<? super QualifiedContent.Scope> getScopes() {
return TransformManager.SCOPE_FULL_PROJECT
}
@Override
public boolean isIncremental() {
return false;
}
@Override
void transform(TransformInvocation transformInvocation) throws TransformException, InterruptedException, IOException {
transformInvocation.inputs.each { TransformInput input ->
input.directoryInputs.each { DirectoryInput directoryInput ->
if (directoryInput.file.isDirectory()) {
directoryInput.file.eachFileRecurse { File file ->
tranformFile(file)
}
} else {
tranformFile(file)
}
// Transform 拷贝文件到 transforms 目录
File dest = transformInvocation.outputProvider.getContentLocation(
directoryInput.getName(),
directoryInput.getContentTypes(),
directoryInput.getScopes(),
Format.DIRECTORY);
// 将修改过的字节码copy到dest,实现编译期间干预字节码
FileUtils.copyDirectory(directoryInput.getFile(), dest);
}
input.jarInputs.each { JarInput jarInput ->
def jarName = jarInput.name
def dest = transformInvocation.outputProvider.getContentLocation(jarName,
jarInput.contentTypes, jarInput.scopes, Format.JAR)
FileUtils.copyFile(jarInput.getFile(), dest)
}
}
}
// 处理响应的文件
private void tranformFile(File file) throws IOException {
def name = file.name
//println file.getAbsolutePath()
if (filerClass(name)) {
//println file.getAbsolutePath()
ClassReader reader = new ClassReader(file.bytes)
ClassWriter writer = new ClassWriter(reader, ClassWriter.COMPUTE_MAXS)
ClassVisitor visitor = new TimePluginClassVisitor(writer)
reader.accept(visitor, ClassReader.EXPAND_FRAMES)
byte[] code = writer.toByteArray()
def classPath = file.parentFile.absolutePath + File.separator + name
println classPath
FileOutputStream fos = new FileOutputStream(classPath)
fos.write(code)
fos.close()
}
}
private boolean filerClass(String name) {
//return name.endsWith("Activity.class")
return name.endsWith("Fragment.class")
}
}
2.2 src/main/resources存放资源
这里我用到了配置文件
META-INF/gradle-plugins,这里放了一个配置文件, *.properties, 此时这个*就是你plugin的名称
上传
maven-publish.gradle
// apply plugin: 'maven'
// https://github.com/expo/expo/issues/12774
// https://docs.gradle.org/current/userguide/publishing_maven.html
// https://docs.gradle.org/current/userguide/publishing_maven.html
// https://developer.android.com/studio/build/maven-publish-plugin
//读取工程的配置
Properties gradleProperties = new Properties()
gradleProperties.load(project.rootProject.file("gradle.properties").newDataInputStream())
def VERSION_NAME = gradleProperties.getProperty("VERSION_NAME")
def POM_URL = gradleProperties.getProperty("POM_URL")
def GROUP_ID = gradleProperties.getProperty("GROUP_ID")
// 本项目下的gradle.properties文件
Properties projectGradleProperties = new Properties()
projectGradleProperties.load(project.file('gradle.properties').newDataInputStream())
def POM_ARTIFACT_ID = projectGradleProperties.getProperty("POM_ARTIFACT_ID")
println("maven-publish VERSION_NAME=$VERSION_NAME")
println("maven-publish POM_URL=$POM_URL")
println("maven-publish POM_URL=$POM_URL")
println("maven-publish GROUP_ID=$GROUP_ID")
pluginManager.apply('maven-publish')
publishing {
publications {
m1(MavenPublication) { // m1也就是个名称
groupId "${GROUP_ID}"
version "${VERSION_NAME}"
artifactId POM_ARTIFACT_ID
from components.java
// artifact sourcesJar
}
}
repositories {
maven {
url(uri(POM_URL))
}
}
}
每个模块build.gradle中添加
// 应用发布功能
apply from : rootProject.file("maven-publish.gradle")
根目录下的gradle.properties
# Project-wide Gradle settings.
# IDE (e.g. Android Studio) users:
# Gradle settings configured through the IDE *will override*
# any settings specified in this file.
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
# AndroidX package structure to make it clearer which packages are bundled with the
# Android operating system, and which are packaged with your app"s APK
# https://developer.android.com/topic/libraries/support-library/androidx-rn
android.useAndroidX=true
# Automatically convert third-party libraries to use AndroidX
android.enableJetifier=true
# Kotlin code style for this project: "official" or "obsolete":
kotlin.code.style=official
POM_URL=/Users/flannery/Desktop/AndroidHelper/repo
GROUP_ID=com.joyy.router
VERSION_NAME=1.0.1
每个模块的gradle.properties
POM_ARTIFACT_ID=router-processor
使用
buildSrc中
- 在module中
// 应用我们的 路由插件
apply plugin: 'com.imooc.router'
maven中
- 根目录下的build.gradle
// Top-level build file where you can add configuration options common to all sub-projects/modules.
apply from: "common.gradle"
buildscript {
repositories {
println("[根目录build.gradle] repositories")
google()
mavenCentral()
}
dependencies {
classpath "com.android.tools.build:gradle:7.0.0"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.20"
}
}
- 在moudle中
// 应用我们的 路由插件
apply plugin: 'com.imooc.router'