Android 在项目中添加Hotfix热修复

开源框架地址
https://github.com/dodola/HotFix

实现原理来自:安卓App热补丁动态修复技术介绍,在这就不解释了。

一 配置项目

首先将开源项目中的buildSrc、hackdex、hotfixlib这三个Import Module到自己的项目中。
第二步将开源项目中assets下的hackdex_dex.jar复制到自己项目assets下。
第三步在app下的gradle中添加几句话(详细位置对照开源项目中代码位置)

task('processWithJavassist') << {
    String classPath = file('build/intermediates/classes/debug')//项目编译class所在目录
    dodola.patch.Patchclass.process(classPath, project(':hackdex').buildDir
            .absolutePath + '/intermediates/classes/debug')//第二个参数是hackdex的class所在目录            
}

applicationVariants.all { variant ->
    variant.dex.dependsOn << processWithJavassist //在执行dx命令之前将代码打入到class
}

注意项目编译class所在的目录如果是正式打包的版本是在这个文件夹下

task('processWithJavassist') << {
    String classPath = file('build/intermediates/classes/release')//项目编译class所在目录
    dodola.patch.Patchclass.process(classPath, project(':hackdex').buildDir
            .absolutePath + '/intermediates/classes/release')//第二个参数是hackdex的class所在目录
}

有的会突然报这个错误

这里写图片描述

解决方法也很简单,把项目目录下的gradle改成1.3.0就可以了,版本太高task运行好像不行。

这里写图片描述

第四步在自己项目Application的onCreate中添加上一段代码

        // 把assets目录下的hackdex_dex.jar插入到dexElements
        File dexPath = new File(getDir("dex", Context.MODE_PRIVATE), "hackdex_dex.jar");
        Utils.prepareDex(this.getApplicationContext(), dexPath, "hackdex_dex.jar");
        HotFix.patch(this, dexPath.getAbsolutePath(), "dodola.hackdex.AntilazyLoad");
        try {
            this.getClassLoader().loadClass("dodola.hackdex.AntilazyLoad");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        try {
            // 如果有补丁包就加载补丁包  在APP接到打补丁通知后 退出前下载到自定义目录下
            // 在这里是根目录下的Download目录下  补丁包起名叫做eclair_dex.jar
            File newDexPath = new File(Environment.getExternalStorageDirectory() + "/Download/eclair_dex.jar");
            if (newDexPath.exists()) {
                Utils.prepareDex(this.getApplicationContext(), newDexPath, "eclair_dex.jar");
                HotFix.patch(this, newDexPath.getAbsolutePath(), "");
            }
        } catch (Exception e) {
        }

最后修改依赖的buildSrc中的PatchClass

        List<String> list = new ArrayList<>();
        list.add("com.eclair.activities.Card_Act");
        list.add("com.eclair.activities.DigitalDetailsWeb_Act");
        list.add("com.eclair.activities.MainActivity");
        list.add("com.eclair.activities.Map_Act");
        ...
        println(lib)
        ClassPool classes = ClassPool.getDefault()
        classes.appendClassPath(buildDir)
        classes.appendClassPath(lib)

        for (int i = 0; i < list.size(); i++) {
            //下面的操作比较容易理解,在将需要关联的类的构造方法中插入引用代码
            CtClass c = classes.getCtClass(list.get(i))
            if (c.isFrozen()) {
                c.defrost()
            }
            println("====添加构造方法====" + i)
            def constructor = c.getConstructors()[0];
            constructor.insertBefore("System.out.println(dodola.hackdex.AntilazyLoad.class);")
            c.writeFile(buildDir)
        }

这个文件的作用就是在编译的时候把.class文件的构造方法中加入System.out.println(dodola.hackdex.Antilazyload.class);
目的是为了防止被打上CLASS_ISPREVER IF IED标志。
因为不知道可能出现哪些BUG,所以我干脆把所有的类全都打上了 。。。哈哈哈
把类名存到list中循环插入
然后点击运行我们的项目,有时会报这种错误

这里写图片描述

然后根据输出 i 的位置找到出问题的类 发现

这里写图片描述

这个类的构造方法中传入了Context,既然不能这样插入,那我们就直接在这个类的构造方法中加入

这里写图片描述

然后就不需要在PatchClass文件中插入了
好啦,项目的配置完事了,我们来做个补丁测试一下吧~

二 制作补丁文件

首先,我们修改一下代码,在这里我将Music_Fragment中的

这里写图片描述

修改为

这里写图片描述

好啦然后我们从新运行/打包一下我们的App 然后在项目文件下的
app\build\intermediates\classes\release寻找我们刚才修改类的.class文件
如果是直接运行的,那么应该在
app\build\intermediates\classes\debug下
注意不能直接从Studio中复制!!

这里写图片描述

全部复制出来,然后,新建一个文件夹目录是这个类的包名例如 我这个类的所在包名是com.eclair.fragments
那么就新建一个com文件夹,里面再新建eclair然后再新建fragments,最后把复制的class文件放到fragments文件夹下
也可以直接将com目录复制出来,打成jar包的时候选择哪些.class文件
接下来在运行cmd :jar cvf 起的名字.jar com目录下所有文件

这里写图片描述

在这里我把com文件夹放在了D盘下的thishotfix文件夹中,cmd运行的时候也在D:thishotfix中
如果是全部复制出来的可以一个文件一个文件的选择 但是要一个不能落下 一个类可能会有很多.calss

这里写图片描述

我在这演示一下所以只添加了两个
每个文件之间用空格分开
jar cvf xxx.jar 文件 文件 文件
输入完成后回车,如果成功应该会是这样的

这里写图片描述

这时运行目录下应该多了一个 xxx.jar
现在,这个jar文件还不能直接当作补丁,需要dx工具转化一下,这个工具在你的Android SDK目录下的build-tools中,任意点开一个版本就可以看到dx.bat和lib文件夹下的dx.jar,如果没有,可以去万能的百度寻找,我们直接切换cmd目录到这里。
然后运行 dx –dex –output 你程序中约定好的补丁名字.jar 刚才生成的.jar

这里写图片描述

运行完成后会在当前目录找到这个jar,在这里我是eclair_dex.jar,这个就是做好的补丁文件。
然后运行我们之前的App,完全关闭之后再把补丁文件放到事先约定好的文件目录下,从新打开App你就会发现打上补丁了~
在这里是模拟下载完成从新开启软件打补丁

这里写图片描述

这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值