Android 阿里巴巴热修复框架之AndFix的使用

一、热修复实现思路:

1.引入Andfix依赖

2.生成有bug的安装包

3.生成修复bug后的apk

4.通过工具apkpatch-1.0.3生成.apatch文件

5.安装存在bug的apk,

 6.通过文件传输工具把4中的文件导入指定文件夹(实际项目中可以放在服务器,通过网络下载)

7.在安装好的app中加载.apatch文件修复bug

二、具体实现

1.使用gradle添加依赖

    // 引入AndFix热修复模块
    implementation 'com.alipay.euler:andfix:0.5.0@aar' 

 由于本项目中用到sd卡存取,所以添加权限申请框架

    //权限申请
    implementation 'pub.devrel:easypermissions:1.1.1'

2.打包有bug的apk这里就不说了。人为的bug为打印一个没有初始化的字符串

  public static void printString()
    {
        String error=null;
        Log.e("Utils",error);

    }

3.把字符串初始化后再打包(修复bug)

  public static String printString()
    {
        String error="修复bug,初始化数据";
        Log.e("Utils",error);
        return error;
    }

4.通过命令进入apkpatch-1.0.3文件夹

执行apkpatch.bat(window系统)可以看到如下:

命令主要有两个:第一个为生成补丁文件,第一个为合并补丁文件。

用第一个命令之前先把afixkey.jks,old.apk,new.apk放入apkpatch-1.0.3文件夹下,并创建存放补丁文件夹output

apkpatch -f new.apk -t old.apk -o output/ -k afixkey.jks -p 123456 -a rongyao -e 123456

new.apk:修复后的apk ;

old.apk:存在bug的apk;

output/:补丁文件存放路径

afixkey.jks:密钥

-p后123456:密钥密码

rongyao:别名

-e后 123456:别名密码

执行成功后,output文件夹下生成3个文件,我们只需要用到.apatch

5.自行安装old.apk

6.运行app后,项目中通过代码创建加载补丁的文件夹

修改补丁前运行,点击效果如图

点击后再点击,效果如图

 

主要代码如下:

MyApplication代码如下:

package com.andfixdemo;

import android.app.Application;

public class MyApplication extends Application {

    @Override
    public void onCreate() {
        super.onCreate();
        //完成andFix模块的初始化
        initAndFix();
    }

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

AndFixPatchManager代码:

package com.andfixdemo;

import android.content.Context;

import com.alipay.euler.andfix.patch.PatchManager;

public class AndFixPatchManager {

    private static AndFixPatchManager mInstance = null;

    private static PatchManager mPatchManager = null;

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

    //初始化AndFix方法
    public void initPatch(Context context) {
        mPatchManager = new PatchManager(context);
        mPatchManager.init(Utils.getVersionName(context));
        mPatchManager.loadPatch();
    }

    //加载我们的patch文件
    public void addPatch(String path) {
        try {
            if (mPatchManager != null) {
                mPatchManager.addPatch(path);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

MainActivity代码:

package com.andfixdemo;

import android.Manifest;
import android.os.Build;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.RelativeLayout;
import android.widget.TextView;

import java.io.File;
import java.util.List;

import pub.devrel.easypermissions.AppSettingsDialog;
import pub.devrel.easypermissions.EasyPermissions;

public class MainActivity extends AppCompatActivity implements View.OnClickListener, EasyPermissions.PermissionCallbacks {

    private static String filepath = ".apatch";
    private String dir = "/mnt/sdcard/andfix/apatch/";//根据自己的情况设置
    private Button button;
    private Button button2;
    private RelativeLayout activity_main;
    private boolean orExistsDir;
    private TextView text;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
        {
            if (EasyPermissions.hasPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE})) {
                createFolder();
            } else {
                // Ask for one permission
                EasyPermissions.requestPermissions(this, "We require this permission to select photo from gallery and camera.",
                        100, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE});
            }
        }else
        {
            createFolder();
        }
    }

    @Override
    public void onPermissionsGranted(int requestCode, @NonNull List<String> perms) {
        createFolder();
    }

    @Override
    public void onPermissionsDenied(int requestCode, @NonNull List<String> perms) {
        if (EasyPermissions.somePermissionPermanentlyDenied(this, perms)) {
            new AppSettingsDialog.Builder(this).build().show();
        }
    }

    private void createFolder() {
        //新建一个File,传入文件夹目录
        File file = new File(dir);
        //判断文件夹是否存在,如果不存在就创建,否则不创建
        if (!file.exists()) {
            //通过file的mkdirs()方法创建目录中包含却不存在的文件夹
            file.mkdirs();
        }
    }


    private void initView() {
        button = (Button) findViewById(R.id.button);
        text = (TextView) findViewById(R.id.text);
        button.setOnClickListener(this);
        button2 = (Button) findViewById(R.id.button2);
        button2.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            default:
                break;
            case R.id.button:
                String str=  Utils.printString();
                text.setText(str);
                break;
            case R.id.button2:
                AndFixPatchManager.getInstance().addPatch(getPath());
                break;
        }
    }

    private String getPath() {
        return dir.concat("fix").concat(filepath);
    }
}

Utils代码: 

package com.andfixdemo;

import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.util.Log;

/**
 * Created by renzhiqiang on 17/4/22.
 */

public class Utils {

    /**
     * 获取应用程序versionname
     *
     * @param context
     * @return
     */
    public static String getVersionName(Context context) {
        String versionName = "1.0.0";
        try {
            PackageManager pm = context.getPackageManager();
            PackageInfo pi = pm.getPackageInfo(context.getPackageName(), 0);
            versionName = pi.versionName;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return versionName;
    }

    public static String printString()
    {
//        String error=null;//修复前
        String error="修复bug,初始化数据";//修复后
        Log.e("Utils",error);
        return error;
    }
}

最核心代码是:

初始化
mPatchManager = new PatchManager(context); mPatchManager.init(Utils.getVersionName(context)); 
mPatchManager.loadPatch();

加载补丁:

mPatchManager.addPatch(path);

 

CSDN地址:https://download.csdn.net/download/u010350891/10732393

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值