Android 源码系列之<十八>自定义Gradle Plugin,优雅的解决第三方Jar包中的bug<中>

本文是Android源码系列的第十八篇,重点介绍如何通过自定义Gradle Plugin优雅地修复第三方Jar包中的bug。借助Javassist库,详细阐述了在transform()方法中修改class文件的步骤,并定义了BytecodeFixExtension类来存储修复配置。修复配置包括依赖的Jar包、修复信息等,如className、methodName、injectValue和injectLine。通过示例解释了如何指定修复的类、方法、插入代码和位置。
摘要由CSDN通过智能技术生成

       转载请注明出处:http://blog.csdn.net/llew2011/article/details/78548660

       在上篇文章Android 源码系列之<十七>自定义Gradle Plugin,优雅的解决第三方Jar包中的bug<上>中由于篇幅原因我们主要讲解了如何创建自定义Gradle Plugin以及修复第三方Jar包中的bug的思路,如果你还没看过上篇文章,强烈建议阅读一下。这篇文章就带领小伙伴们借助Javassist开源库实现对class文件的修改。

        上篇文章中我们讲到了修改第三方Jar包的时机是在BytecodeFixTransform的transform()方法中,也就是在待修改Jar包在被拷贝目标文件夹之前先做修改,修改完成之后我们直接把修改过的Jar包拷贝进目标文件夹而不是原来的Jar包。既然要修改Jar包里的class文件,我们就要知道是哪一个class需要修复,然后还要是class里边的哪一个方法需要修复,还要清楚要修复的内容是什么等等,因此我定义一个BytecodeFixExtension类来表示修复配置,如下所示:

package com.llew.bytecode.fix.extension

public class BytecodeFixExtension {

    /**
     * 字节码修复插件是否可用,默认可用
     */
    boolean enable = true

    /**
     * 是否开启日志功能,默认开启
     */
    boolean logEnable = true

    /**
     * 是否保留修复过的jar文件,默认保留
     */
    boolean keepFixedJarFile = true

    /**
     * 时候保留修复过的class文件,默认保留
     */
    boolean keepFixedClassFile = true

    /**
     * 构建字节码所依赖的第三方包绝对路径,默认包含了Android.jar文件
     */
    ArrayList<String> dependencies = new ArrayList<String>()

    /**
     * 配置文件集合,配置格式:className##methodName(param1,param2...paramN)##injectValue##injectLine
     */
    ArrayList<String> fixConfig = new ArrayList<>();

    // 省略了setters and getters 方法
}

       在BytecodeFixExtension中需要注意dependencies和fixConfig的配置。dependencies表示在利用Javassist修复class文件时所依赖的Jar包,例如修复上篇文章中提到的getMobileAPInfo()方法就需要引入ContextCompat类,因此需要添加ContextCompat所在Jar包的绝对路径。fixConfig表示修复信息集合,它的格式是固定的,必须以##做分隔符,格式如下:className##methodName(param1,param2...paramN)##injectValue##injectLine,具体字段说明如下所示:

  • className:表示全类名
            例如:com.tencent.av.sdk.NetworkHelp
  • methodName(param1,param2...paramN):表示方法名及相关参数,参数只写类型且必须以逗号(,)分隔,非基础数据类型要写全路径
            例如:getAPInfo(android.content.Context)
            例如:getAPInfo(android.content.Context, int)
  • injectValue:表示待插入代码块,注意代码块要有分号(;),其中$0表示this;$1表示第一个参数;$2表示第二个参数;以此类推
            例如:$1 = null;System.out.println("I have hooked this method by BytecodeFixer Plugin !!!");
                       $1 = null;就是表示把第一个参数置空;接着是打印一句日志
           【注意:】如果injectValue为{}表示给原有方法添加try-catch操作
  • injectLine:表示插在方法中的哪一行,该参数可选,如果省略该参数则默认把injectValue插在方法的最开始处
            injectLine > 0 插入具体行数
            injectLine = 0 插入方法最开始处
            injectLine < 0 替换方法体
       上边讲解了配置文件的规则,接下来就是实现具体的Jar包的修改了,创建BytecodeFixInjector类,该类的职责就是进行Jar包文件的修复,然后把修复后的Jar包返回给调用者。代码如下:
package com.llew.bytecode.fix.injector

import com.llew.bytecode.fix.extension.BytecodeFixExtension
import com.llew.bytecode.fix.task.BuildJarTask
import com.llew.bytecode.fix.utils.FileUtils
import com.llew.bytecode.fix.utils.Logger
import com.llew.bytecode.fix.utils.TextUtil
import javassist.ClassPool
import javassist.CtClass
import javassist.CtMethod
import org.gradle.api.Project

import java.util.jar.JarFile
import java.util.zip.ZipFile

public class BytecodeFixInjector {

    private static final String INJECTOR  = "injector"
    private static final String JAVA      = ".java"
    private static final String CLASS     = ".class"
    private static final String JAR       = ".jar"

    private static ClassPool sClassPool
    private static BytecodeFixInjector sInjector

    private Project mProject
    private String mVersionName
    private Byteco
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值