Android热修复(2):AndFix热修复框架的使用

AndFix的github地址

AndFix

AndFix是一个在线修复bug的解决方案,而不是重新发布Android应用程序。它是以Android库的形式发布的。

Andfix是“Android热修复”的缩写。

AndFix支持Android版本从2.3到7.0,ARM和X86架构,Dalvik和ART runtime, 32位和64位。

AndFix补丁的压缩文件格式是.apatch。它从您自己的服务器发送到客户端,以修复应用程序的错误。

原理

AndFix的原理就是方法的替换,把有bug的方法替换成补丁文件中的方法,AndFix只能修复方法级别的bug。

在这里插入图片描述

使用教程

1.添加依赖

dependencies {
	compile 'com.alipay.euler:andfix:0.5.0@aar'
}

AndFixPatchManager:对Andfix进行封装

/**
 * Created by xiaoyehai on 2018/11/26 0026.
 * 管理AndFix所有的api
 */

public class AndFixPatchManager {

    private static AndFixPatchManager mInstance = null;

    private PatchManager mPatchManager = null;

    public static AndFixPatchManager getInstance() {
        if (mInstance == null) {
            synchronized (AndFixPatchManager.class) {
                if (mInstance == null) {
                    mInstance = new AndFixPatchManager();
                }
            }
        }
        return mInstance;
    }

    /**
     * 初始化AndFix
     *
     * @param context
     */
    public void initPatch(Context context) {
        mPatchManager = new PatchManager(context);
        mPatchManager.init(getVersionName(context));
        mPatchManager.loadPatch();
    }

    /**
     * 加载patch文件
     *
     * @param path
     */
    public void addPatch(String path) {
        if (mPatchManager != null) {
            try {
                mPatchManager.addPatch(path);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }


    /**
     * 获取应用程序版本名称信息versionName
     *
     * @param context
     * @return 当前应用的版本名称
     */
    public static String getVersionName(Context context) {
        try {
            PackageManager packageManager = context.getPackageManager();
            PackageInfo packageInfo = packageManager.getPackageInfo(context.getPackageName(), 0);
            return packageInfo.versionName;

        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}

2.初始化AndFix

public class AndFixApplication extends Application {

    @Override
    public void onCreate() {
        super.onCreate();

        //初始化AndFix
        initAndFix();
    }

    private void initAndFix() {
        AndFixPatchManager.getInstance().initPatch(this);
    }
}

3.先准备一个有bug的release版apk:old.apk

public class MainActivity extends AppCompatActivity {

    //补丁文件后缀名
    private static final String FILE_END = ".apatch";

    //apatch文件路径
    private String mPatchDir;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mPatchDir = getExternalCacheDir().getAbsolutePath() + "/apatch/";

        //创建文件夹
        File file = new File(mPatchDir);
        if (file == null || !file.exists()) {
            file.mkdir();
        }
    }

    /**
     * 产生bug代码
     *
     * @param view
     */
    public void creatBug(View view) {
        String[] array = {"00", "11", "22", "33"};
       Toast.makeText(this, array[4], Toast.LENGTH_SHORT).show(); //数组越界
    }


    /**
     * 点击按钮加载补丁文件,修复bug
     * 项目中可以在下载补丁文件之后调用,这里为了演示就把补丁文件放在本地的SD卡中了
     *
     * @param view
     */
    public void fixBug(View view) {
        AndFixPatchManager.getInstance().addPatch(getPatchName());
        Toast.makeText(this, "修复了bug", Toast.LENGTH_SHORT).show();
    }

    /**
     * 获取patch文件路径
     *
     * @return
     */
    private String getPatchName() {

        //AndFix:apatch文件名
        return mPatchDir.concat("AndFix").concat(FILE_END);
    }
}

4.修复bug后的release版apk:new.apk

  public void creatBug(View view) {
        String[] array = {"00", "11", "22", "33"};
        Toast.makeText(this, array[3], Toast.LENGTH_SHORT).show(); //修复bug后代码
    }

5.使用apkpatch-1.0.3.jar工具用命令生成.apatch文件

apkpatch-1.0.3.jar工具可以在github官网下载。

在这里插入图片描述

进入apkpatch-1.0.3文件夹文件夹,使用如下命令生成补丁.apatch文件:

apkpatch.bat -f new.apk -t old.apk -o outputs -k lantu.jks -p 123456 -a lantu -e 123456

apkpatch.bat -f 新apk -t 旧apk -o 输出目录 -k app签名文件 -p 签名文件密码 -a 签名文件别名 -e 别名密码

命令行参数说明:
在这里插入图片描述
生成的.apatch文件:
在这里插入图片描述

5.修复测试

把补丁文件放入内存卡中,发现bug已经被修复。

实际开发中把补丁文件从服务器下载下来,自动加载补丁文件,修复bug。

注意每次appversion变更都会导致所有补丁被删除,如果appversion没有改变,则会加载已经保存的所有补丁。

在需要的地方调用PatchManager的addPatch方法加载新补丁,比如可以在下载补丁文件之后调用。

AndFix在服务中实现

步骤:

1.检查服务端是否有新的apatch文件
2.有:下载apatch文件
3.加载下载好的apatch文件,修复bug

/**
 * Created by xiaoyehai on 2018/11/27 0027.
 * 1.检查服务端是否有新的apatch文件
 * 2.有:下载apatch文件
 * 3.加载下载好的apatch文件,修复bug
 */

public class AndFixService extends Service {

    public static final String TAG = AndFixService.class.getSimpleName();

    private static final int DOWNLOAD_APATCH = 0x01;

    private static final int UPDATE_APATCH = 0x02;

    public static final String UPDATE_PATCH_URL = "";

    public static final String DOWNLOAD_PATCH_URL = "";

    //存放apatch文件的目录
    private String mPatchFileDir;

    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);

            switch (msg.what) {
                case DOWNLOAD_APATCH: //下载apatch文件
                    downloadPatch();
                    break;
                case UPDATE_APATCH: //检查服务端是否有新的apatch文件
                    checkApatchUpdate();
                    break;
            }
        }
    };

    @Nullable
    @Override

    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        init();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        mHandler.sendEmptyMessage(UPDATE_APATCH);
        return START_NOT_STICKY; //服务被系统回收之后不会自动重启
    }

    private void init() {
        mPatchFileDir = getExternalCacheDir().getAbsolutePath() + "/apatch/";
        File patchDir = new File(mPatchFileDir);
        try {
            if (patchDir == null || !patchDir.exists()) {
                patchDir.mkdirs();
            }
        } catch (Exception e) {
            e.printStackTrace();
            stopSelf(); //停止服务
        }

    }

    /**
     * 检查服务端是否有新的apatch文件
     */
    private void checkApatchUpdate() {
        //获取服务器信息,判断是否有新的apatch文件
        OkHttpManager.getInstance().asyncJsonStringByURL(UPDATE_PATCH_URL, new OkHttpManager.StringCallback() {
            @Override
            public void onResponse(String result) {
                //有新的apatch文件,下载文件
                mHandler.sendEmptyMessage(DOWNLOAD_APATCH);
            }

            @Override
            public void onFailure(IOException e) {
                stopSelf();
            }
        });
    }

    /**
     * 下载apatch文件
     */
    private void downloadPatch() {
        DownloadManager.getInstance().downloadFile(DOWNLOAD_PATCH_URL, mPatchFileDir, new DownloadManager.FileCallback() {
            @Override
            public void onSuccess(File file) {
                //文件下载成功,加载apatc文件,修复bug
                AndFixPatchManager.getInstance().addPatch(file.getAbsolutePath());
            }

            @Override
            public void onProgress(int progress, long total) {
                Log.e(TAG, "onProgress: " + progress);
            }

            @Override
            public void onError(Call call, Exception e) {
                stopSelf();
            }
        });
    }
}

在app启动页面启动服务:

//启动服务
Intent inten = new Intent(this, AndFixService.class);
startService(inten);

Android热修复(1):热修复的介绍和原理解析

Android热修复(3):Tinker的使用

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值