android热修复之AndFix

     首先说下前奏,在实际开发中,由于某些不确定的因素,软件在发布之后,获取存在着一些bug,有时候我们发布的软件比较大,有的有好几十M,所以不可能再让我们的软件去更新,用户体验非常差,目前市面上的大互联网公司都有热修复的框架,实际原理都差不多,这里我们选取阿里的ANDFIX框架详细讲解他的实现过程。


原理

AndFix的原理就是方法的替换,把有bug的方法替换成补丁文件中的方法。





优点:

重大bug,需要紧急修复
可以下次迭代修复的bug
影响用户体验的行为

无需重启  


缺点:
  • 无法添加新类(内部类也不行)和新的字段、新的方法?自己试了方法可以
  • 源文件无法替换   试了下换原有的图片可以,但是新增的不行
  • 不能修改xml布局文件   不能
  • 加固后的包补丁无法使用,如果要加固,需要加固前的包来生成补丁,不过这样生成的补丁也很容易破解
  • 不能对同一个方法修复两次,否则App根本跑不起来
  • 对加载过的补丁文件要做名字修改 如果名字重叠 就不会再次加载

上面是网上流传的部分优缺点,大家可以自行斟酌,想要说的是,热修复虽然好用,但是有很多不确定性,不是万能的,所以想要有一个好的体验,最好还是在上线之前做好准备工作,测试必须充分。




使用教程:


1. 添加依赖

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

2.初始化PatchManager

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

/*
 *  @项目名:  HotFixAlibaba 
 *  @包名:    com.huhai.hotfixalibaba
 *  @文件名:   AndFixApplication
 *  @创建者:   Administrator
 *  @创建时间:  2017/3/18 9:19
 *  @描述:    TODO
 */
public class AndFixApplication extends Application {

    public static PatchManager mPatchManager;

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

        // 初始化patch管理类
        mPatchManager = new PatchManager(this);

        // 初始化patch版本
        mPatchManager.init("1.0");
        //        String appVersion = getPackageManager().getPackageInfo(getPackageName(), 0).versionName;
        //        mPatchManager.init(appVersion);

        // 加载已经添加到PatchManager中的patch
        mPatchManager.loadPatch();

    }
}

不要忘记了在清单文件中添加(重要,否则无法初始化application)

android:name=".AndFixApplication"


3.我选择是使用点击button的方式进行热修复。

 原始的mainactivity代码

package com.huhai.hotfixalibaba;

import android.os.Bundle;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;

import java.io.File;
import java.io.IOException;

public class MainActivity
        extends AppCompatActivity
{

    private static final String APATCH_PATH = "/fix.apatch"; // 补丁文件名
    private TextView mainTv;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mainTv = (TextView) findViewById(R.id.main_tv);
       // mainTv.setText("点击Toast");
        mainTv.setText("加载了补丁之前");
        mainTv.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                showToast();
            }
        });

        findViewById(R.id.main_btn).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                update();
            }
        });

    }

    private void showToast() {
        //Toast.makeText(this, "打补丁之后", Toast.LENGTH_LONG).show();
        Toast.makeText(this, "打补丁之前", Toast.LENGTH_LONG).show();
    }

    /**
     * 动态更新,加载补丁文件
     * @author zehua_chen
     * create at 2016/8/3 14:35
     */
    private void update() {
        String patchFileStr = Environment.getExternalStorageDirectory().getAbsolutePath() + APATCH_PATH;
        File   apatchPath   = new File(patchFileStr);
        if (apatchPath.exists()){
            //Toast.makeText(this, "打补文件存在--修复了", Toast.LENGTH_LONG).show();
            try {

                AndFixApplication.mPatchManager.addPatch(patchFileStr);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }else {
            Toast.makeText(this, "打补文件不存在", Toast.LENGTH_LONG).show();
        }

    }
}

4.编写到这里,就可以把程序跑起来了,注意要使用签名文件:


记住生成.jks文件,还有签名的apk文件包,将签名的apk文件自己修改名称,便于版本管理。

我选择的是将文件名称改为 andfix_v1.0.apk  ,并且得到了andfix.jks文件。





先不要管这两个文件的位置,你先得到这两个文件,把他留着后面用


5.修改你的代码,假设之前的activity中有bug,此时需要修改bug

我选择的是修改了button的文字,以及弹出吐司的内容

package com.huhai.hotfixalibaba;

import android.os.Bundle;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;

import java.io.File;
import java.io.IOException;

public class MainActivity
        extends AppCompatActivity
{

    private static final String APATCH_PATH = "/fix.apatch"; // 补丁文件名
    private TextView mainTv;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mainTv = (TextView) findViewById(R.id.main_tv);
       // mainTv.setText("点击Toast");
        mainTv.setText("加载了补丁之后");
        mainTv.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                showToast();
            }
        });

        findViewById(R.id.main_btn).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                update();
            }
        });

    }

    private void showToast() {
       Toast.makeText(this, "打补丁之后", Toast.LENGTH_LONG).show();
        //Toast.makeText(this, "打补丁之前", Toast.LENGTH_LONG).show();
    }

    /**
     * 动态更新,加载补丁文件
     * @author zehua_chen
     * create at 2016/8/3 14:35
     */
    private void update() {
        String patchFileStr = Environment.getExternalStorageDirectory().getAbsolutePath() + APATCH_PATH;
        File   apatchPath   = new File(patchFileStr);
        if (apatchPath.exists()){
            Toast.makeText(this, "打补文件存在--修复了", Toast.LENGTH_LONG).show();
            try {

                AndFixApplication.mPatchManager.addPatch(patchFileStr);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }else {
            Toast.makeText(this, "打补文件不存在", Toast.LENGTH_LONG).show();
        }

    }
}

6.再修改的基础上重新进行打包生成apk

修改名称你自己喜欢的便于管理

我修改的是---andfix_v2.0.apk

把他留着



这个时候,你应该有了两个apk,一个签名文件。


7.使用官方提供的工具apkpatch生成.apatch补丁文件

下载地址:https://github.com/alibaba/AndFix

解压后得到如下文件夹



看到没,然后把你的两个 apk还有签名文件放到该目录下。



8.使用工具生成补丁包。



命令的参数介绍:

上图所示则表示补丁包生成完成

apkpatch.bat -f andfix_v2.0.apk -t andfix_v1.0.apk -o output -k AndFixKey.jks -p andfix -a andfix -e andfix

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

  • -f <new.apk> :新apk
  • -t <old.apk> : 旧apk
  • -o <output> : 输出目录(补丁文件的存放目录)
  • -k <keystore>: 打包所用的keystore
  • -p <password>: keystore的密码
  • -a <alias>: keystore 用户别名
  • -e <alias password>: keystore 用户别名密码

这里需要注意的是,你第一次解压的时候是没有output文件夹的



到了这里,上面的文件就是工具帮我们对比了旧的apk,以及新的apk,然后生成的补丁文件。


9.加载补丁,在实际开发中,我们需要向服务器去下载这个补丁,下载存放在文件夹中,然后再去加载,为了方便跟大家一样我也是直接把文件放在手机的根目录下,然后在activity中去加载这个补丁。



10.查看效果

没有打补丁之前的效果:


将补丁文件放sd卡根目录下,点击button热更新加载之后:



效果就是这样了,是不是很简单,照着做,你也可以的

备注:我使用的andrroid studio开发工具,手机是杂牌手机 5.0系统,实测ok


代码下载地址:http://download.csdn.net/detail/qq_16177199/9785504

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值