您的位置:首页 > 移动开发 > Android开发

android热补丁初探

2016-02-26 14:44 239 查看
android热补丁初探----HotFixDemo

1.先来个代码结构



2.热补丁的文章有好多了,我这里就不赘述了。

来两个链接

QQ空间 的链接

https://mp.weixin.qq.com/s?__biz=MzI1MTA1MzM2Nw==&mid=400118620&idx=1&sn=b4fdd5055731290eef12ad0d17f39d4a&scene=1&srcid=1106Imu9ZgwybID13e7y2nEi#wechat_redirect

这还有另一片相关的文章

/article/2256113.html

理论的学习还是要很多的,不然各种搞不懂,不知道都是什么东西,大概有哪些步骤也是不清楚的。

hotfix github地址:

https://github.com/dodola/HotFix

3.这里大概总结下有哪些主要的步骤:

1.android编译生成apk后,apk解压后会有一个classes.dex 文件,android系统在加载这个dex文件时,是可以加载多个dex文件的。

2.我们可以再编译一个dex文件传到用户正在使用的app中,

3.加载到APP指定的目录,/data/data/包名/app_文件夹名/

4.然后将这个dex也加载到系统中,执行最新的dex中的class代码,把最原始的类覆盖掉。

4.其中比较关键的技术点

1.加载dex的时候,加载了多个是有加载顺序的,需要把后传上去的补丁包先去查找其中的类。

如: 原始dex 中的 Bug.class

补丁dex 中的 Bug.class

这两个需要设置成加载补丁包中Bug.class先加载

2.android在编译应用的时候,默认是只加载原始dex的,如果dex中有对应的类Bug.class 就会在这个类上打个标志CLASS_ISPREVERIFIED,

Bug.class 被打上这个标志后,这个类就不会在去找其他的dex中的Bug.class了(编译系统优化产生的这个标志)。

怎么样才能不打这个标志呢?

hotfix中采用的做法是:在类加载的时候,在类的构造方法中加载另外一个dex文件。就是demo中的hackdex_dex.jar,这个实际是个dex文件。

这个类在应用初始化的时候Application中执行加载这个dex.,在对应的其他所有类中的构造方法中都加载这个中间dex其中的一个类即可,不用做事情。

就是为了消除这个CLASS_ISPREVERIFIED标志,这样就不打标了。

注意:打补丁这里,有三个dex文件,

第一个是原始apk中带的classes.dex文件,

第二个是这个解除打标用的dex文件,这个dex文件中,有一个空的类的就ok。

第三个就是补丁的dex文件。

此步骤的实现相对麻烦些:

要在gradle中处理一些东西,即在编译apk的时候要将所有要打补丁的类的构造方法中打上一句加载第二个dex文件的话

例如:System.out.print(SecondDexClass.class);

注意:这句话不能在系统初始化的自定义Application中执行。(为什么这里不说了,去其他的博客看一下吧,要有理论支撑)

所以这要对gradle进行编程,hotfix demo中已经有写了,可以参考。

3.就是从服务器或者手机sd卡的某个位置获得补丁dex文件,然后执行加载。

理论就大概介绍到这里。

这个是代码地址:

http://download.csdn.net/detail/methods2011/9444827

下面对代码进行简单的介绍

1.首先要有bug类,打印的bug class000就是需要补丁 改变的

public class BugClass {
public String bug() {
return "bug class000";
}
}

2.然后系统初始化的Application,

这里进行加载了第二个dex文件

dodola.hackdex.AntilazyLoad

这个类为第二个dex中的唯一的一个空类

public class HotfixApplication 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 {
this.getClassLoader().loadClass("dodola.hackdex.AntilazyLoad");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}

}
}




3.这个是在Activity中执行的代码片段

//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
//准备补丁,从assert里拷贝到dex里
File dexPath = new File(getDir("dex", Context.MODE_PRIVATE), "modify_dex.jar");
Utils.prepareDex(this.getApplicationContext(), dexPath, "modify_dex.jar");
//                DexInjector.inject(dexPath.getAbsolutePath(), defaultDexOptPath, "dodola.hotfix
// .BugClass");
HotFix.patch(this, dexPath.getAbsolutePath(), "com.method.hotfixdemo_01.BugClass");
return true;
}
if (id == R.id.action_test) {
LoadBugClass bugClass = new LoadBugClass();
Toast.makeText(this, "测试调用方法:" + bugClass.getBugString(), Toast.LENGTH_SHORT).show();
return true;
}


modify_dex.jar是加载的补丁dex文件其中只有一个bugClass文件,其中反编译的



如果补丁成功的话:会toast 这个。。。

4.我把另外两个dex(非原始apk带的)放到了assets中。





5.有一个groovy模块,用于gradle编译补丁类用的。



build.gradle中的设置是这样的

apply plugin: 'groovy'

repositories {
mavenCentral()
}

dependencies {
compile gradleApi()
compile localGroovy()
compile 'org.javassist:javassist:3.18.+'
}


注意最上面一行的这个:apply plugin: 'groovy'

这个下来大致就是可以跑的有bug的app了。

然后是补丁的打包的过程。

打完包的名称是:

modify_dex.jar

实际是一个dex文件

1:将BugClass类修复下



然后找到对应编译后的BugClass.class,要反编译下看看这个文件更新了没,



之后新建一个文件夹,将这个类对应的包名都弄对,然后将这个BugClass.class文件放入其中。



modify.jar就是 用命令行执行 jar -cvf modify.jar *

modify_dex.jar 使用android\sdk\build-tools\23.0.2\dx.bat 文件进行编译的

dx --dex --output=modify_dex.jar modify.jar

之后这个dex就可以最为补丁送到正在使用的app中了,代码自行补脑了。

然后就是代码中的执行这个:

File dexPath = new File(getDir("dex", Context.MODE_PRIVATE), "modify_dex.jar");
Utils.prepareDex(this.getApplicationContext(), dexPath, "modify_dex.jar");
//                DexInjector.inject(dexPath.getAbsolutePath(), defaultDexOptPath, "dodola.hotfix
// .BugClass");
HotFix.patch(this, dexPath.getAbsolutePath(), "com.method.hotfixdemo_01.BugClass");

然后这个bug就被解决了。

ok!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: