参考文章
2. https://mp.weixin.qq.com/s?__biz=MzI1MTA1MzM2Nw==&mid=400118620&idx=1&sn=b4fdd5055731290eef12ad0d17f39d4a&scene=1&srcid=1106Imu9ZgwybID13e7y2nEi#wechat_redirect
QQ空间团队APP热补丁
3. https://m.oschina.net/blog/308583 设备的分包技术
比较偏向于使用eclipse 来进行开发, 并且这里不讲原理(因为以上博客对原理已经讲的够好了), 只讲自己的实现过程.
1.生成替换出现bug类的jar文件
App中有如下几个类
BugClass 出现bug的类
重写写这个类, 其包名,类需要与原来的类保持一致
ps: dx 工具在..\sdk\build-tools\android-4.4W,文件夹中,可以配置其环境变量,便于使用
2.防止应该该bug类的类被打上
( 1 )也就是说需要防止BugLoad类被打上
帮助类. 如 AntilazyLoad
( 2 ) 需要将BugLoad中注入AntilazyLoad引用. 由于BugLoad 和 AntilazyLoad 不在同一个dex中, 所以在代码编写的时候是不可能引用到AntilazyLoad. 所以需要将AnilazyLoad 注入到BugLoad的class字节码文件中, 这里就需要使用到 javassist库了. 当我们不再更改BugLoad,那么BugLoad的字节码文件也就不会重新生成, 那么我们可以拿到该字节码文件将 AntilazyLoad注入到BugLoad字节码中,如下
3.导入HotFix资源文件实现热修复
3. https://m.oschina.net/blog/308583 设备的分包技术
比较偏向于使用eclipse 来进行开发, 并且这里不讲原理(因为以上博客对原理已经讲的够好了), 只讲自己的实现过程.
1.生成替换出现bug类的jar文件
App中有如下几个类
BugClass 出现bug的类
package com.danale.main;
public class BugClass {
public String bug(){
return "bug class";
}
}
BugLoad 应用了bug的类
package com.danale.main;
public class BugLoad {
public String show(){
return new BugClass().bug();
}
}
那么我们需要将BugClass该类替换掉
重写写这个类, 其包名,类需要与原来的类保持一致
package com.danale.main;
public class BugClass {
public String bug(){
return "fix bug class";
}
}
需要将该BugClass 转成jar, 并将该jar使用dx工具进行转化
bin>jar cvf patch.jar com/danale/main/* //将class文件转为jar包
bin>dx --dex --output patch_dex.jar patch.jar //将jar包进行dx转化
然后将patch_dex.jar, 放置到assets 文件夹下.( 当然该文件同样可以放置到网上,这里为了方便处理)
ps: dx 工具在..\sdk\build-tools\android-4.4W,文件夹中,可以配置其环境变量,便于使用
2.防止应该该bug类的类被打上
CLASS_ISPREVERIFIED
标签
( 1 )也就是说需要防止BugLoad类被打上
CLASS_ISPREVERIFIED
标签, 那么就需要让BugLoad类引用其他dex中的类,才能防止被打上标签. 所以需要定义一个
帮助类. 如 AntilazyLoad
package dodola.hackdex;
/**
* 用于嵌入的类
*/
public class AntilazyLoad {
}
将该类同样进行1的操作
bin>jar cvf hack.jar dodola/hackdex/AntilazyLoad //将class文件转为jar包
bin>dx --dex --output hackdex_dex.jar hack.jar //将jar包进行dx转化
将 hackdex_dex.jar, 放置到assets文件夹下,(该jar需要在app发布的时候已经定义好了)
( 2 ) 需要将BugLoad中注入AntilazyLoad引用. 由于BugLoad 和 AntilazyLoad 不在同一个dex中, 所以在代码编写的时候是不可能引用到AntilazyLoad. 所以需要将AnilazyLoad 注入到BugLoad的class字节码文件中, 这里就需要使用到 javassist库了. 当我们不再更改BugLoad,那么BugLoad的字节码文件也就不会重新生成, 那么我们可以拿到该字节码文件将 AntilazyLoad注入到BugLoad字节码中,如下
package com.javassist;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtConstructor;
/**
* 用来个类添嵌入别的dex的方法
*/
public class JavassistTask {
public static void main(String[] args) throws Exception {
String path = "D:/git-work-montum/MainApp/bin/";
ClassPool classes = ClassPool.getDefault();
classes.appendClassPath(path + "classes");
CtClass c = classes.get("com.danale.main.BugLoad");
CtConstructor ctConstructor = c.getConstructors()[0];
ctConstructor.insertAfter("System.out.println(dodola.hackdex.AntilazyLoad.class);");
c.writeFile(path+"/output");
}
}
然后将 classes文件下的BugLoad.class 替换为 bin/ output/... 目录下的BugLoad.class, 可以使用反编译工具查看BugLoad.class 是否被注入成功,如下
package com.danale.main;
import dodola.hackdex.AntilazyLoad;
import java.io.PrintStream;
public class BugLoad
{
public BugLoad()
{
Object localObject = null; System.out.println(AntilazyLoad.class); }
public String show() {
return new BugClass().bug();
}
}
3.导入HotFix资源文件实现热修复
( 1 ) 此时assets文件加下已经有两个jar了, hackdex_dex.jar 和 patch_dex.jar , 由于AntilazyLoad是被注入到BugLoad中的, 为了防止AntilazyLoad找不到class, 需要在app的application的onCreate 方法中将hackdex_dex.jar加载进来, 如下:
import java.io.File;
import dodola.hotfixlib.HotFix;
import android.app.Application;
import android.content.Context;
import android.util.Log;
public class MainApp extends Application {
@Override
public void onCreate() {
super.onCreate();
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 {
Class<?> loadClass = this.getClassLoader().loadClass("dodola.hackdex.AntilazyLoad");
Log.i("MainApp", "SUCCESS : " + loadClass);
} catch (ClassNotFoundException e) {
Log.i("MainApp", "EXCEPTION : " + e.getMessage());
e.printStackTrace();
}
}
}
ps: Utils工具类就是将jar文件拷贝到dexPath处
( 2 ) 前面的准备工作做完了之后,就剩下最后一步了, 将patch_dex.jar中的BugClass 加载进来从而替换掉出现问题的类,如下
//准备补丁,从assert里拷贝到dex里
File dexPath = new File(getDir("dex", Context.MODE_PRIVATE), "patch_dex.jar");
Utils.prepareDex(this.getApplicationContext(), dexPath, "patch_dex.jar");
HotFix.patch(this, dexPath.getAbsolutePath(), "com.danale.main.*");
至此, android 热补丁完成了
源文件下载
http://download.csdn.net/detail/qq_24551315/9574232