【Android】字节码插桩(一)

本文介绍了Android字节码插桩技术的基础知识,包括Transform API的使用,如何通过Transform处理编译后的class文件和jar包,以及如何注册和实现自定义的Gradle插件以实现插桩功能。示例代码展示了如何输出所有class名称和jar包。
摘要由CSDN通过智能技术生成

1 摘要

字节码插桩技术可以帮我们实现业务层模块和功能模块的关联,并在项目结构避免其耦合,比如ARouter实现各模块路由表的注册;

2 背景

一般我们使用Transform会有下面两种场景

我们需要对编译class文件做自定义的处理。 我们需要读取编译产生的class文件,做一些其他事情,但是不需要修改它。
本篇主要介绍完成字节码插桩的第一步,通过Transform将编译后的class文件和jar包找到并输出;

3 正文

Transform的基本API参考

Transform的抽象方法:

public abstract class Transform {
   
//返回一个本Transform的标记
    public abstract String getName();

    public abstract Set<ContentType> getInputTypes();

    public abstract Set<? super Scope> getScopes();

    public abstract boolean isIncremental(); // 是否支持增量编译
}

getName()就是指定自定义的Transform的名字。

输入的类型
Set getInputTypes()是指明你自定义的这个Transform处理的输入类型,输入类型共有以下几种:

  enum DefaultContentType implements ContentType {
   
        /** * The content is compiled Java code. This can be in a Jar file or in a folder. If * in a folder, it is expected to in sub-folders matching package names. */
        CLASSES(0x01),

        /** * The content is standard Java resources. */
        RESOURCES(0x02);
    }

即分为class文件或者java资源。class文件来自于jar或者文件夹。资源就是标准的java资源。

输入文件所属的范围 Scope
getScopes()用来指明自定的Transform的输入文件所属的范围, 这是因为gradle是支持多工程编译的。总共有以下几种:

/** * This indicates what the content represents, so that Transforms can apply to only part(s) * of the classes or resources that the build manipulates. */
enum Scope implements ScopeType {
   
    /** Only the project content */
    PROJECT(0x01), //只是当前工程的代码
    /** Only the project's local dependencies (local jars) */
    PROJECT_LOCAL_DEPS(0x02), // 工程的本地jar
    /** Only the sub-projects. */
    SUB_PROJECTS(0x04),  // 只包含子工工程
    /** Only the sub-projects's local dependencies (local jars). */
    SUB_PROJECTS_LOCAL_DEPS(0x08),
    /** Only the external libraries */
    EXTERNAL_LIBRARIES(0x10),
    /** Code that is being tested by the current variant, including dependencies */
    TESTED_CODE(0x20),
    /** Local or remote dependencies that are provided-only */
    PROVIDED_ONLY(0x40);
}

对于getScopes()的返回,其实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);

如果一个Transform不想处理任何输入,只是想查看输入的内容,那么只需在getScopes()返回一个空集合,在getReferencedScopes()返回想要接收的范围。

public Set<? super Scope> getReferencedScopes() {
   
    return ImmutableSet.of();
}
 

transform()
它是Transform的关键方法:

public void transform(@NonNull TransformInvocation transformInvocation) {}

它是一个空实现,input的内容将会打包成一个TransformInvocation对象,因为我们要想使用input,我们需要详细了解一下TransformInvocation参数。

TransformInvocation
我们看一下这个类相关的API:

public interface TransformInvocation {
   

    Collection<TransformInput> getInputs(); // 输入作为 TransformInput 返回

    TransformOutputProvider getOutputProvider(); //TransformOutputProvider 可以用来创建输出内容

    boolean isIncremental();
}
public interface TransformInput {
   
    Collection<JarInput> getJarInputs();
    Collection<DirectoryInput> getDirectoryInputs();
}

public interface JarInput extends QualifiedContent {
   

    File getFile(); //jar文件

    Set<ContentType> getContentTypes(); // 是class还是resource

    Set<? super Scope> getScopes();  //属于Scope:
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值