AndFix使用说明

AndFix,全称是Android hot-fix。是阿里开源的一个热补丁框架,允许APP在不重新发布版本的情况下修复线上的bug。支持Android 2.3 到 6.0,并且支持arm 与 X86系统架构的设备。完美支持Dalvik与ART的Runtime,补丁文件是以 .apatch 结尾的文件。

参考网站:

github地址

AndFix使用说明:

http://www.jianshu.com/p/479b8c7ec3e3

Alibaba-AndFix Bug热修复框架原理及源码解析 :

http://blog.csdn.net/qxs965266509/article/details/49816007

Andfix修复的整体流程:

AndFix的实现原理是方法的替换:


具体使用:

我们以一个具体的例子来说明:

demo测试activity生命周期函数界面很简单,只是一个textView加button,当前textView显示的是有bug,那么点击button之后,就会加载补丁,textView就会显示bug第一次被修复了。

先给出TestActivityLifeCycle.java:

 package com.tulipsport.android.andfixdemos.test_activity;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.TextView; import com.tulipsport.android.andfixdemos.R;
import com.tulipsport.android.andfixdemos.utils.PatchUtils;
public class TestActivityLifeCycle extends AppCompatActivity{
@Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView text=(TextView)findViewById(R.id.test);
text.setText("有bug");
findViewById(R.id.button).setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v){
PatchUtils.loadPatch(getApplicationContext());
}
});
}

}

按照下面1-3步执行,然后打包生成一个“有bug”的apk文件,我们将它命名为1.apk。

然后,将上面的 text.setText("有bug");换成 text.setText("bug第一次被修复了");再次打包,生成apk文件,我们将它命名为2.apk。然后使用apkpatch工具,根据1.apk和2.apk生成补丁文件,有关 补丁文件的生成操作和命名方式,见5-6.

假设我们生成的补丁为2_1.apatch,现在来演示效果。

将有bug的apk安装到模拟器上:

打开app:显示有bug

我们将补丁文件放在sdcard根目录下的tulipsport_patches文件夹下,

开始演示效果:


1.使用gradle添加依赖

compile 'com.alipay.euler:andfix:0.3.1@aar'

2.使用PatchUtils

创建一个PatchUtils的工具类,用于加载补丁。

public class PatchUtils{
private static final String TAG="euler";
private static final String TULIPSPORT_PATCHES="/tulipsport_patches";
private static final String DIR="apatch";//补丁文件夹
/**
* patch manager
*/
public static PatchManager mPatchManager;
public static void loadPatch(Context context){
mPatchManager=new PatchManager(context);
mPatchManager.init(getVersionName(context));
mPatchManager.loadPatch();
try {
File dir=new File(Environment.getExternalStorageDirectory()
.getAbsolutePath() + TULIPSPORT_PATCHES);
String loadPatchName=Environment.getExternalStorageDirectory()
.getAbsolutePath() + TULIPSPORT_PATCHES + "/" +
String.valueOf(getVersionCode(context))
+ "_" +
FileUtils.getLoadPatchName(dir,
"apatch",String.valueOf(getVersionCode(context))) + ".apatch";
Log.d("loadPatchName",loadPatchName);
mPatchManager.addPatch(loadPatchName);
Log.d(TAG,"apatch:" + loadPatchName + " added.");
//复制且加载补丁成功后,删除下载的补丁
File f=new File(context.getFilesDir(),DIR);
if (f.exists()) {
boolean result=new File(loadPatchName).delete();
if (!result)
Log.e(TAG,loadPatchName + " delete fail");
}
} catch (Exception e) {
e.printStackTrace();
}
}
private static int getVersionCode(Context context){
try {
PackageInfo pi=context.getPackageManager().getPackageInfo(context.getPackageName(),0);
return pi.versionCode;
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
return 0;
}
}
private static String getVersionName(Context context){
try {
PackageInfo pi=context.getPackageManager().getPackageInfo(context.getPackageName(),0);
return pi.versionName;
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
return null;
}
}}

注意:补丁的下载位置为sdcard根目录下的tulipsport_patches文件夹,可以自行修改。

PatchUtils中使用了FileUtils类,在这里简单给出FileUtils:

package com.tulipsport.android.andfixmorebugs;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
/**
* Created by Brooks on 2016/3/9.
*/
public class FileUtils{
/**
* @param fileDir 文件目录
* @param fileType 后缀名
* @return 特定目录下的所有后缀名为fileType的文件列表
*/
public static List<String> getFiles(File fileDir,String fileType) throws Exception{
List<String> lfile=new ArrayList<String>();
File[] fs=fileDir.listFiles();
for (File f : fs) {
if (f.isFile()) {
if (fileType
.equals(f.getName().substring(
f.getName().lastIndexOf(".") + 1,
f.getName().length())))
lfile.add(f.getName());
}
}
return lfile;
}
public static String getLoadPatchName(File fileDir,String fileType,String versionCode) throws Exception{
List<String> files=getFiles(fileDir,fileType);
int maxPatchVersion=0;
for (String name : files) {
if (name.startsWith(versionCode + "_")) {
int patchVersion=Integer.valueOf(name.substring(name.indexOf("_") + 1,name.indexOf(".")));
maxPatchVersion=Math.max(maxPatchVersion,patchVersion);
}
}
return String.valueOf(maxPatchVersion);
}
}

3.添加权限

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

4.加载补丁

在需要加载补丁的地方调用:

PatchUtils.loadPatch(context);

5.生成补丁

使用工具apkpatch-1.0.3

下载地址:https://github.com/alibaba/AndFix/raw/master/tools/apkpatch-1.0.3.zip

使用命令apkpatch生成补丁。



图示参数缺一不可,否则无法生成补丁!!!

例如:

旧的apk为1.apk,新的apk为2.apk, -o表示补丁的输出目录,-k表示keystore, -p表示keystore的密码,-a表示alias, -e表示entry password。

可以看到在当前目录下生成了相应的补丁文件:



补丁命名规则如下:

6.补丁的命名规则

a_b.apatch

a表示versionCode,b表示当前的补丁的版本。

例如:如果当前的versionCode的版本为4,补丁的版本为3,则命名为4_3.apatch。

7.适用环境说明

Andfix并不能修复所有情况下出现的bug,测试结果如下:

该Demo就是用来测试上述这12种情况的。

例子中都是有bug的情况,请读者自行将bug修复,测试修复情况,使用方法见上面的具体使用

8.补丁加载的时机

可以放在自定义Application的onCreate方法中,也可以放在button的点击事件中,也可以放在监听网络变化的广播中。

例如:

放在自定义Application中:

package com.tulipsport.android.andfixmorebugs;
import android.app.Application;
/**
* Created by Brooks on 2016/3/4.
*/
public class MyApplication extends Application{
@Override
public void onCreate(){
super.onCreate();
PatchUtils.loadPatch(getApplicationContext());
}
}

或者放在监听网络变化广播中:

public class MyReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context,Intent intent){
ConnectivityManager connectivityManager=(ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo mobNetInfo=connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
NetworkInfo wifiNetInfo=connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
if (!mobNetInfo.isConnected() && !wifiNetInfo.isConnected()) {
Toast.makeText(context,"网络不可以用",Toast.LENGTH_SHORT).show();
//改变背景或者 处理网络的全局变量
} else {
//改变背景或者 处理网络的全局变量
//这里开始执行下载补丁操作,下载完成后,开始加载补丁
Toast.makeText(context,"开始加载补丁",Toast.LENGTH_SHORT).show();
PatchUtils.loadPatch(context);
}
}}

9.补丁加载流程

10.混淆

-printmapping proguard.map

首先需要生成mapping文件记录混淆规则,之后可以把printmapping 这句话注释掉,每次只使用applymapping。

-applymapping proguard.map

然后在下面加上

-keep class * extends java.lang.annotation.Annotation
-keepclasseswithmembernames class * {
native <methods>;
}
-keep class com.alipay.euler.andfix.** { *; }

11.局限性

  • 无法添加新类和新的字段

[Android]AndFix使用说明的更多相关文章

  1. Android AndFix修复方式的限制

    这里阅览了很多网上关于修复的资料,一一贴在这里便于查看: https://github.com/alibaba/AndFix  这是官方处  要了解使用,一定得看看这里. http://www.jia ...

  2. android studio使用说明

    一.学习的基本配置文档,搞好各种参数的基本配置,熟练使用. C:\Program Files\Java\jdk1.7.0_09\bin   二.problems meet in weather and ...

  3. android ActionBarSherlock使用说明

    源代码地址:https://github.com/JakeWharton/ActionBarSherlock 1.添加项目依赖包 2.修改AndroidManifest.xml中的主题(或者继承该主题 ...

  4. Android 项目的代码混淆,Android proguard 使用说明

    简单介绍 Java代码是非常easy反编译的. 为了非常好的保护Java源码,我们往往会对编译好的class文件进行混淆处理. ProGuard是一个混淆代码的开源项目.它的主要作用就是混淆,当然它还 ...

  5. GT性能测试Android版使用说明

    1 GT简介 GT(随身调) Android版是腾讯 MIG 专项测试组自行研发的 Android APP 随身调测平台,它是直接运行在手机上的“集成调测环境”(ITE, Integrated Tes ...

  6. Android.mk 使用说明

    Android.mk 详解https://blog.csdn.net/dearsq/article/details/50585537  Android.mk中的主要配置参数: 1.LOCAL_JACK ...

  7. 《android基于andFix的热修复方案》实战篇

    有篇文章说的比较简洁,大家可以参考下:AndFix使用说明 下面说说实际使用中遇到的问题 1:如何继承到gradle项目中 dependencies { compile 'com.alipay.eul ...

  8. Android(java)学习笔记153:layout_weight使用注意事项

    1. android:layout_weight使用说明: layout_weight是权重的意思,也就是各个控件所占的比重,用在LinearLayout布局中.当我们使用layout_weight的 ...

  9. Android 混淆那些事儿

    本文来自于腾讯Bugly公众号(weixinBugly),未经作者同意,请勿转载,原文地址:https://mp.weixin.qq.com/s/WmJyiA3fDNriw5qXuoA9MA 作者:l ...

随机推荐

  1. JavaWeb中文乱码问题解决思路

    1.提交页面请求或者服务器端的响应时,需要确保页面编码当时与服务器编码方式是否一致. 2.对于从服务器写入数据库中的数据和从数据库中读取到服务器中的数据,需要确保服务器编码方式与数据库编码方式是否一致 ...

  2. Delphi 中窗口文件与无窗口Pas文件的区别 (MTM)

    implementation {$R *.dfm}  ---- 带窗口的 dfm -- 一般的 windows 窗口 {$R *.fmx}  ---- 带窗口的 fmx -- 一般的 FireMonk ...

  3. [LintCode] A + B 问题

    Bit-by-Bit summation: class Solution { public: /* * @param a: The first integer * @param b: The seco ...

  4. 习惯养成和目标追踪APP推荐

    一.习惯和目标的不同 习惯:贵在坚持,每天任务一定,而完成总量不定.坚持时间越久越好. 目标:贵在按时完成,任务总量一定,但是每天完成量不做限制.有一个完成期限,但是越早越好. 上面的差别导致了相关A ...

  5. python之MySQL学习——简单的增删改查封装

    1.增删改查封装类MysqlHelper.py import pymysql as ps class MysqlHelper: def __init__(self, host, user, passw ...

  6. Struts2.0 封装请求数据和拦截器介绍

    1. Struts2 框架中使用 Servlet 的 API 来操作数据 1.1 完全解耦合的方式 Struts2 框架中提供了一个 ActionContext 类,该类中提供了一些方法: stati ...

  7. 转!java web项目 build path 导入jar包,tomcat启动报错 找不到该类

    在eclipse集成tomcat开发java web项目时,引入的外部jar包,编译通过,但启动tomcat运行web时提示找不到jar包内的类,需要作如下配置,将jar包在部署到集成的tomcat环 ...

  8. Internet Explorer 1.0到9.0截图画廊

    Internet Explorer 1.0 Windows 95 原先并没有IE,IE1.0是通过一个名叫Windows 95 Plus!Pack的扩展包来到用户的电脑中的,它的到来改变了Netsca ...

  9. 【我的Android进阶之旅】 Android Studio插件之Jenkins插件介绍

    一Jenkins插件功能介绍 1Jenkins任务列表 2切换Jenkins分组 3构建Jenkins任务 4进入构建Jenkins任务的页面 5进入最后一次构建Jenkins任务的页面 6增加Jen ...

  10. 我的Android进阶之旅------>解决Android Studio编译后安装apk报错:The APK file does not exist on disk

    1.错误描述 今天用Android Studio编译应用后安装APK的时候,报错了,错误如下所示: The APK file build\outputs\apk\OYP_2.3.4_I2Base_64 ...