亲自实践Andfix 流程记录
来源:互联网 发布:苹果 淘宝 编辑:程序博客网 时间:2024/05/29 19:11
今天心血来潮,写一个最近在探究的热更新。网上有很多资料和教程,github也有阿里官方的介绍(官方库),但是每个人遇到的情况不同 ,可能会出现各种问题,这里我就以我的情况记录一下,以备自己和大家参考借鉴。
首先描述一下我的环境:
电脑:mac os x 10.11.3
安卓开发工具:android studio 2.2.2。
测试手机:readmi3
android版本:5.1.1 MIUI 8.0.1
首先,我也是查阅了很多资料和blog,了解了热修复的概念和基本实现原理。我就简单介绍一下热修复,所谓热修复,就如同AS的instant run ,可以在不重新安装apk的情况下,更改代码,实现代码更新。实现方式有很多种,市面上以阿里巴巴andfix和腾讯Tinker的比较出名。我这里亲测了andfix,使用比较简单,效果也出来了,只不过有一定限制,只能修改(增删改)类中的方法,对资源文件及其他文件无法修改。不过我相信虽然有此限制,但是阿里的团队都在用,说明是好用的。至于如何能做到够用,我猜测是使用预测类和方法来做到热更新。
下面就开始介绍我的试验流程
1 下载官方的demo,直接提取其中的导入sample文件夹中的AndFixDemo至AS,我是以eclipse的类型导入的,然后就自动转成了AS工程结构。
2 引入andfix库,两种方式,第一种直接gradle引入,但是无法修改源码,会有个问题,之后会提到
dependencies { compile 'com.alipay.euler:andfix:0.5.0@aar'}第二种就是引入第三方库
这种方式分两步,1 引入Andfix库,这个官方给的不是很好,我就参考了别的大神给的,虽然
AndFix
类中有个小bug ,修复后如下:Runtime.getRuntime().loadLibrary("andfix");
当然载入的是so库,2 就是要在jniLibs中添加这个so文件,我为了减小apk大小 或者是偷懒,只在armeabi中添加了libandfix.so
我最后选择了第二种方式,因为如果使用第一种,那么PatchManager 的
public void addPatch(String path) throws IOException {
默认就会只更新相同名称的apatch一次,也就不能很好地实现多次fix,当然,如果每次名称不一样,那就还是会加载两个文件。看了PatchManager源码知道:
private static final String DIR = "apatch";//补丁文件夹
mPatchDir = new File(mContext.getFilesDir(), DIR);
andfix会把add的patch文件都复制到mPatchDir中,但是如果名字相同就不会再次去重复add,也就是说如果要保证多次fix,需要保证每次add的apatch文件名不同。FileUtil.copyFile(src, dest);// copy to patch's directory
所以我就参考大神的做法,把PatchManager中的addPatch方法修改成:
public void addPatch(String path) throws IOException { File src = new File(path); File dest = new File(mPatchDir, src.getName()); if (!src.exists()) { throw new FileNotFoundException(path); } if (dest.exists()) { Log.d(TAG, "patch [" + src.getName() + "] has be loaded."); boolean deleteResult = dest.delete(); if (deleteResult) Log.e(TAG, "patch [" + dest.getPath() + "] has be delete."); else { Log.e(TAG, "patch [" + dest.getPath() + "] delete error"); return; } } FileUtil.copyFile(src, dest);// copy to patch's directory Patch patch = addPatch(dest); if (patch != null) { loadPatch(patch); }}基本思路是:每次addPatch的文件如果存在,就会先删除这个文件,然后重新add进去,这样就保证了每次修复文件的名称可以一样。
当然还有一步,为了减少不必要存储,我们把
File f = new File(this.getFilesDir(), DIR + APATCH_PATH);if (f.exists()) { boolean result = new File(patchFileString).delete(); if (!result) Log.e(TAG, patchFileString + " delete fail");}从sd卡中push或下载的文件删除,代码如下
// .apatch file pathmPatchManager.addPatch(patchFileString);Log.d(TAG, "apatch:" + patchFileString + " added.");//这里我加了个方法,复制加载补丁成功后,删除sdcard的补丁,避免每次进入程序都重新加载一次File f = new File(this.getFilesDir(), DIR + APATCH_PATH);if (f.exists()) { boolean result = new File(patchFileString).delete(); if (!result) Log.e(TAG, patchFileString + " delete fail");}
3 接下来就是在MainApplication中初始化andfix和loadPatch,addPatch.
public void onCreate() { super.onCreate(); String patchFileString = Environment.getExternalStorageDirectory() .getAbsolutePath() + APATCH_PATH; // initialize mPatchManager = new PatchManager(this); mPatchManager.init(BuildConfig.VERSION_NAME); Log.d(TAG, "inited."); // load patch mPatchManager.loadPatch(); Log.d(TAG, "apatch loaded."); // add patch at runtime try { // .apatch file path mPatchManager.addPatch(patchFileString); Log.d(TAG, "apatch:" + patchFileString + " added."); //这里我加了个方法,复制加载补丁成功后,删除sdcard的补丁,避免每次进入程序都重新加载一次 File f = new File(this.getFilesDir(), DIR + APATCH_PATH); if (f.exists()) { boolean result = new File(patchFileString).delete(); if (!result) Log.e(TAG, patchFileString + " delete fail"); } } catch (IOException e) { Log.e(TAG, "", e); }}4 现在可以在MainActivity实现热修复操作了。为了直观,我没有使用log的方式观察结果,我用了toast方式,在oncreate方法中toast一个当前时间,然后生成签名apk,作为old.apk 安装在手机上,然后修改toast的时间为当前时间,再次生成签名apk,作为new.apk.统统放在了桌面。
然后我们要把两个apk的不同通过工具生成apatch文件,我们就需要工具了apkpatch,这是官方提供的。怎么用呢?
首先我把下载的文件夹解压放在了桌面,右键文件在此文件夹下打开终端,不知道这个的可以百度。然后输入
./apkpatch.sh -f /Users/guolinyao/Desktop/new.apk -t /Users/guolinyao/Desktop/old.apk -o /Users/guolinyao/Desktop/ -k /Users/guolinyao/Documents/高顿实习平台/Hishixi签名文件/hishixi.keystore -p hishixi -a haishixi -e hishixi
当然我们的路径是不一样的:关于写法 规则在这里:
usage: apkpatch -f <new> -t <old> -o <output> -k <keystore> -p <***> -a <alias> -e <***> -a,--alias <alias> keystore entry alias. -e,--epassword <***> keystore entry password. -f,--from <loc> new Apk file path. -k,--keystore <loc> keystore path. -n,--name <name> patch name. -o,--out <dir> output dir. -p,--kpassword <***> keystore password. -t,--to <loc> old Apk file path.
生成了patch文件我直接改成了out.apatch因为在初始化时,addpatch方法传的也是这个文件名,要对应!!!
接下来
把out.apatch放入scared
adb push out.apatch的文件路径 sdcard/ 这个也不能错!
可以通过adb命令adb shell >cd sdcard > ls 查看是否存在该文件
好了,现在再次打开刚安装的app,你就会发现toast的时间变了。
最常规的过程讲完了,现在开始讲讲几个小心得。首先,关于加固,我是加固应用的,同样可以使用andfix但是需要在加固前apk制作apatch文件;关于版本更新,andfix默认在版本更新时会删除所有apatch文件;关于混淆,官方说明了;关于patch文件如何分发,我是想在服务端给一个标志是否下载patch文件,每次进入app判断,大家有好的建议希望能够一起分享哦!
demo下载
- 亲自实践Andfix 流程记录
- AndFix 使用实践
- AndFix简单实践
- Andfix学习记录
- svn 亲自实践操作
- android热修复实践-andfix
- andfix中的java hook流程
- 全局变量的设定(亲自实践)
- Excel智能填充(亲自实践)
- Excel对齐小数点(亲自实践)
- Android热修复实践应用--AndFix
- android 热修补之andfix实践
- Android热修复实践应用--AndFix
- Android热修复实践应用--AndFix
- Android热修复实践应用--AndFix
- Android热修复实践应用--AndFix
- Android热修复实践应用--AndFix
- Android热修复实践应用--AndFix
- Tomcat性能优化
- 机器学习实验(十一):基于WiFi fingerprints用自编码器(Autoencoders)和神经网络(Neural Network)进行定位_2(keras版)
- excel match 某个值是否在特定列
- UITextView如何绘制圆角和添加背景图片
- k近邻算法
- 亲自实践Andfix 流程记录
- OpenAL播放pcm或wav数据流-windows/ios/android(一)
- React Native客户端服务器分开集成方案
- excel数据以千位单位K显示
- 自动化笔记-iframe
- Spark运行模式
- android键盘弹出、关闭、遮挡问题
- 失败中总结经验
- 遵循学术写作的九步骤,让写论文变成一件简单的事