和android热修复AndFix技术亲密接触

黄沙百战穿金甲,不破楼兰终不还。这篇文章主要讲述和android热修复AndFix技术亲密接触相关的知识,希望能为你提供帮助。
每次回家都偷懒, 不想整理一下, 今天周末, 强迫自己整理下, 内容一定很全。
前言 随着app版本升级迭代, 难免有些bug会出现, 用户升级新版的代价较高, 如果能给app打热补丁, 热更新掉app的bug, 岂不更好。
Andfix andfix是阿里的一个热修复框架, 更新至今, 已经相对完善了, 可以满足我们日常需求。它有很多优点, 比如:
1.热修复免重启app
2.更新包小
3.支持360加固( 很多blog上说不支持, 其实是支持的, 下文会介绍怎么用)
至于缺点吗, 我不说, 哈哈。
下图为热修复图解

和android热修复AndFix技术亲密接触

文章图片

使用方式 1.在android studio里添加依赖
compile ' com.alipay.euler:andfix:0.5.0@ aar'

1.在Application的onCreate方法中初始化andfix
// 初始化patch管理类 mPatchManager = new PatchManager(this); // 初始化patch版本 String appVersion = " 1.0" ; try { appVersion = getPackageManager().getPackageInfo(getPackageName(), 0).versionName; //获取app版本号 } catch (PackageManager.NameNotFoundException e) { e.printStackTrace(); } mPatchManager.init(appVersion); // 加载已经添加到PatchManager中的patch mPatchManager.loadPatch();

在热修复版本时, appversion不用变。
页面布局
为了方便测试, 主页面放3个button, 第一个用来显示是否有bug, 第二个用来从网络上下载热修复包( 需自建web服务) , 然后热修复, 第三个用来从本地文件中加载热修复包( 无需自建web服务) 。
和android热修复AndFix技术亲密接触

文章图片

代码
public class MainActivity extends AppCompatActivity { private MyApplication app; private static final String LOCAL_NAME = " local.apatch" ; //本地SD卡中的更新文件[ 2选1] private static final String NET_NAME = " net.apatch" ; //网络上的更新文件[ 2选1] private final String url= " http://192.168.1.2/net.apatch" ; @ Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //用于模拟是否有bug findViewById(R.id.button2).setOnClickListener(new View.OnClickListener() { @ Override public void onClick(View view) { Toast.makeText(MainActivity.this, " 出现bug" , Toast.LENGTH_SHORT).show(); //Toast.makeText(MainActivity.this, " bug已经修复" , Toast.LENGTH_SHORT).show(); //[ 第二个版本注释第一行, 取消第二行注释] } }); //网络下载并热修复 findViewById(R.id.button).setOnClickListener(new View.OnClickListener() { @ Override public void onClick(View view) { fix(); } }); //本地热修复 findViewById(R.id.button3).setOnClickListener(new View.OnClickListener() { @ Override public void onClick(View view) { update(); } }); } .....

更新的两个方法
//本地热更新 private void update() { String patchFileStr = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator+ LOCAL_NAME; try { MyApplication.mPatchManager.addPatch(patchFileStr); } catch (IOException e) { e.printStackTrace(); } } //网络下载热更新 private void fix() { new Thread(){ @ Override public void run() { try { String patchFileStr = Environment.getExternalStorageDirectory().getAbsolutePath(); downLoadFromUrl(url, NET_NAME, patchFileStr); MyApplication.mPatchManager.addPatch(patchFileStr); //热修复 } catch (Exception e) { e.printStackTrace(); } } }.start(); }

为了减少代码量, 这里网络请求没有使用框架, 而是自己写的网络请求方法
/** * 从网络Url中下载文件 * * @ param urlStr * @ param fileName * @ param savePath * @ throws IOException */ public static void downLoadFromUrl(String urlStr, String fileName, String savePath) throws IOException { URL url = new URL(urlStr); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); //设置超时间为3秒 conn.setConnectTimeout(3 * 1000); //防止屏蔽程序抓取而返回403错误 conn.setRequestProperty(" User-Agent" , " Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)" ); //得到输入流 InputStream inputStream = conn.getInputStream(); //获取自己数组 byte[] getData = readInputStream(inputStream); //文件保存位置 File saveDir = new File(savePath); if (!saveDir.exists()) { saveDir.mkdir(); } File file = new File(saveDir + File.separator + fileName); FileOutputStream fos = new FileOutputStream(file); fos.write(getData); if (fos != null) { fos.close(); } if (inputStream != null) { inputStream.close(); } System.out.println(" info:" + url + " download success" ); }/** * 从输入流中获取字节数组 * * @ param inputStream * @ return * @ throws IOException */ public static byte[] readInputStream(InputStream inputStream) throws IOException { byte[] buffer = new byte[1024]; int len = 0; ByteArrayOutputStream bos = new ByteArrayOutputStream(); while ((len = inputStream.read(buffer)) != -1) { bos.write(buffer, 0, len); } bos.close(); return bos.toByteArray(); }

编译 项目编译需要自备签名文件, 如果没有的话, 自己创建一个
和android热修复AndFix技术亲密接触

文章图片

和android热修复AndFix技术亲密接触

文章图片

生成含bug的apk
将生成出的app-release.apk文件重命名为bug.apk
生成解决bug的apk
和android热修复AndFix技术亲密接触

文章图片

把出现bug的那条toast注释掉, 改为bug已修复的toast
再次编译将生成的app-release.apk文件重命名为fixedbug.apk
生成apatch 这里需要去下载工具
https://github.com/alibaba/AndFix

tools文件夹里是工具, 下载到本地
和android热修复AndFix技术亲密接触

文章图片

顺便将刚刚两个bug.apk和fixedbug.apk以及签名文件放入文件夹
因为我们只有一个fixedbug.apk所以我们用下面的生成代码
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.

具体做法
1.先打开cmd或者终端, cd到当前目录下
2.敲入
apkpatch-1.0.3/apkpatch.sh -f fixedbug.apk-t bug.apk-o Out -k a.jks -p 123456 -a 654321 -e 654321

和android热修复AndFix技术亲密接触

文章图片

3.这个时候这个out文件夹下apatch文件就是热更新包
和android热修复AndFix技术亲密接触

文章图片

4.将此文件改名net.apatch放入www目录下
保证刚刚的http://192.168.1.2/net.apatch路径可以访问
开始测试 先安装bug.apk到手机上
1.打开ddms
和android热修复AndFix技术亲密接触

文章图片

2.将net.apatch复制一份命名为local.apatch拉入手机中
和android热修复AndFix技术亲密接触

文章图片

可以顺便将bug.apk也放入手机, 方便安装( 或其它方式安装bug.apk)
3.打开app, 运行如图
和android热修复AndFix技术亲密接触

文章图片

出现bug
4.点击本地文件热修复, 然后再次点击显示
和android热修复AndFix技术亲密接触

文章图片

提示bug已修复
至此从本地文件热修复演示完成
5.卸载app, 重新安装然后点击显示, 出现bug, 点击网络下载热修复, 再次点击显示, 提示bug已修复( 同上图)
总结 至此两种方法热修复均解决了appbug, 代码不复杂, 需要源码请留言。
补充 当团队协作时, 多个小组生成出多个apatch文件, 可以使用工具合并
apkpatch -m < apatch_path...> -o < output> -k < keystore> -p < ***> -a < alias> -e < ***> -a,--alias < alias> keystore entry alias. -e,--epassword < ***> keystore entry password. -k,--keystore < loc> keystore path. -m,--merge < loc...> path of .apatch files. -n,--name < name> patch name. -o,--out < dir> output dir. -p,--kpassword < ***> keystore password.

【和android热修复AndFix技术亲密接触】混淆代码
-keep class * extends java.lang.annotation.Annotation -keepclasseswithmembernames class * { native < methods> ; }


    推荐阅读