Gradle Transform
来源:互联网 发布:游戏帧数测试软件 编辑:程序博客网 时间:2024/06/04 01:36
概述
Gradle Transform是Android官方提供给开发者在项目构建阶段即由class到dex转换期间修改class文件的一套api。目前比较经典的应用是字节码插桩、代码注入技术。
基础
- TransformInput:所谓Transform就是对输入的class文件转变成目标字节码文件,TransformInput就是这些输入文件的抽象。目前它包括两部分:DirectoryInput集合与JarInput集合。
- DirectoryInput:它代表着以源码方式参与项目编译的所有目录结构及其目录下的源码文件,可以借助于它来修改输出文件的目录结构、已经目标字节码文件。
- JarInput:它代表着以jar包方式参与项目编译的所有本地jar包或远程jar包,可以借助于它来动态添加jar包。
- TransformOutputProvider:它代表的是Transform的输出,例如可以通过它来获取输出路径。
目前Transform包含如下方法:
- getName:用于指明本Transform的名字,也是代表该Transform的task的名字
- getInputTypes:用于指明Transform的输入类型,可以作为输入过滤的手段。在TransformManager定义了如下的几种类型:
public static final Set<ContentType> CONTENT_CLASS = ImmutableSet.of(CLASSES);public static final Set<ContentType> CONTENT_JARS = ImmutableSet.of(CLASSES, RESOURCES);public static final Set<ContentType> CONTENT_RESOURCES = ImmutableSet.of(RESOURCES);public static final Set<ContentType> CONTENT_NATIVE_LIBS = ImmutableSet.of( ExtendedContentType.NATIVE_LIBS);public static final Set<ContentType> CONTENT_DEX = ImmutableSet.of( ExtendedContentType.DEX);public static final Set<ContentType> CONTENT_JACK = ImmutableSet.of(JACK);public static final Set<ContentType> DATA_BINDING_ARTIFACT = ImmutableSet.of( ExtendedContentType.DATA_BINDING, CLASSES);
- getScopes:用于指明Transform的作用域,在TransformManager定义了如下的三种种类型:
public static final Set<Scope> SCOPE_FULL_PROJECT = Sets.immutableEnumSet( Scope.PROJECT, Scope.PROJECT_LOCAL_DEPS, Scope.SUB_PROJECTS, Scope.SUB_PROJECTS_LOCAL_DEPS, Scope.EXTERNAL_LIBRARIES);public static final Set<QualifiedContent.ScopeType> SCOPE_FULL_INSTANT_RUN_PROJECT = new ImmutableSet.Builder<QualifiedContent.ScopeType>() .addAll(SCOPE_FULL_PROJECT) .add(InternalScope.MAIN_SPLIT) .build();public static final Set<Scope> SCOPE_FULL_LIBRARY = Sets.immutableEnumSet( Scope.PROJECT, Scope.PROJECT_LOCAL_DEPS);
- isIncremental:用于指明是否是增量构建。
实践
新建一个标准的Android项目,在app module下的build.gradle添加如下依赖:
dependencies { compile localGroovy() compile 'com.android.tools.build:transform-api:1.5.0' compile 'commons-io:commons-io:2.5'}
采用buildSrc的方式进行开发,并将Transform封装到自定义插件中,如下buildSrc项目结构:
在该buildSrc下的build.gradle中声明Transform API依赖:
repositories { jcenter()}dependencies { compile 'com.android.tools.build:gradle:2.3.3'}
继承Transform,并重写transform方法
package demoimport com.android.build.api.transform.Contextimport com.android.build.api.transform.DirectoryInputimport com.android.build.api.transform.Formatimport com.android.build.api.transform.JarInputimport com.android.build.api.transform.Transformimport com.android.build.api.transform.TransformExceptionimport com.android.build.api.transform.TransformInputimport com.android.build.api.transform.TransformOutputProviderimport com.android.build.gradle.internal.pipeline.TransformManagerimport com.android.build.api.transform.QualifiedContent.Scopeimport com.android.build.api.transform.QualifiedContent.ContentTypeimport org.apache.commons.codec.digest.DigestUtilsimport org.apache.commons.io.FileUtilsimport org.gradle.api.Projectclass PathTransform extends Transform { Project project public PathTransform(Project project) { this.project = project } @Override void transform( Context context, Collection<TransformInput> inputs, Collection<TransformInput> referencedInputs, TransformOutputProvider outputProvider, boolean isIncremental) throws IOException, TransformException, InterruptedException { System.out.println("=======================================doPathTransform{ context=${context}, inputs=${inputs}, referencedInputs=${referencedInputs}, outputProvider=${outputProvider}, isIncremental=${isIncremental}") } @Override String getName() { return PathTransform.simpleName } @Override Set<ContentType> getInputTypes() { return TransformManager.CONTENT_CLASS } @Override Set<? super Scope> getScopes() { return TransformManager.SCOPE_FULL_PROJECT } @Override boolean isIncremental() { return false }}
在自定义task或plugin中注册该Transform,注意AppExtension就是app中build.gradle中android块:
package demoimport org.gradle.api.Pluginimport org.gradle.api.Projectimport com.android.build.gradle.AppExtensionclass PathPlugin implements Plugin<Project> { @Override void apply(Project project) { def android = project.extensions.getByType(AppExtension) android.registerTransform(new PathTransform(project)) project.task('transformPath') { doLast { System.out.println('+++++++++++++++++++++transformPath task') } } }}
在app module中使用该插件:
apply plugin: demo.PathPlugin
命令行gradle assembleDebug执行构建时,会打印log:
结论
从上述实践过程不难发现Gradle Transform更多的是提供一种可以让开发者参与项目构建的机制,而诸如修改字节码等更加具体的细节则需要开发者去实现。
阅读全文
0 0
- Gradle Transform
- Android Gradle Plugin的Transform API
- transform
- Transform
- transform
- transform
- transform
- transform
- Transform
- transform
- transform
- transform
- transform
- transform
- Transform
- transform
- transform
- transform
- 负载均衡----实现配置篇(Nginx)
- 表格第一行固定,下面
- Java 根据模板导出Excel时,如何根据后台数据设置复选框的勾选
- Qt设置无边框窗口,窗口透明度
- apt-get update 和 upgrade 的区别
- Gradle Transform
- 常见字符串常量和表达式
- 207. Course Schedule
- kdb5_util: Configuration file does not specify default realm while getting default realm
- 关于matlab学习的部分笔记(一)
- android源码函数学习之basename与dirname
- easyui datagrid在fitColumns="true"的情况下失效
- Java多线程系列--“JUC锁”02之 互斥锁ReentrantLock
- 高级指针