android热补丁初探
2016-02-26 14:44
239 查看
android热补丁初探----HotFixDemo
1.先来个代码结构
![](http://img.blog.csdn.net/20160226143837882?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
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就是需要补丁 改变的
2.然后系统初始化的Application,
这里进行加载了第二个dex文件
这个类为第二个dex中的唯一的一个空类
3.这个是在Activity中执行的代码片段
modify_dex.jar是加载的补丁dex文件其中只有一个bugClass文件,其中反编译的
![](http://img.blog.csdn.net/20160226153117765?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
如果补丁成功的话:会toast 这个。。。
4.我把另外两个dex(非原始apk带的)放到了assets中。
![](http://img.blog.csdn.net/20160226153341768?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
5.有一个groovy模块,用于gradle编译补丁类用的。
![](http://img.blog.csdn.net/20160226153631834?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
build.gradle中的设置是这样的
注意最上面一行的这个:apply plugin: 'groovy'
这个下来大致就是可以跑的有bug的app了。
然后是补丁的打包的过程。
打完包的名称是:
实际是一个dex文件
1:将BugClass类修复下
![](http://img.blog.csdn.net/20160226154016402?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
然后找到对应编译后的BugClass.class,要反编译下看看这个文件更新了没,
![](http://img.blog.csdn.net/20160226154203310?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
之后新建一个文件夹,将这个类对应的包名都弄对,然后将这个BugClass.class文件放入其中。
![](http://img.blog.csdn.net/20160226154822149?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
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中了,代码自行补脑了。
然后就是代码中的执行这个:
然后这个bug就被解决了。
ok!
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!
相关文章推荐
- ANDROID安卓activity与fragment,activity之间互相传值(三)
- 如何在Android中导入jar包
- 【Android 开发工具】px和dp转换工具
- Android常用开源框架分享
- 在活动中使用 Menu
- Android-SQLiteOpenHelper使用示例
- Android小问题:SingleTask启动模式时,activity的生命周期
- android-gif-drawable 加载太多的gif,有时gif动态图不动
- Android应用开发中Action bar编写的入门教程
- android 编程小技巧(1)---超实用的LogUtil
- Android SwipeRefreshLayout下拉刷新与上拉加载+滑动删除
- android开发小感
- Android studio 导入*.jar包 如 Vollley
- Android之GlSurfaceView调度Skia
- android中Intent和IntentFilter的区别
- 第3章 Android Dalvik虚拟机 第三节(上)
- Android 通知栏提示
- Android状态保存与恢复
- Android Studio——FrameLayout
- Android 自己定义 TextView drawableTop 图标与文字左对齐(效果图)