Android AndFix热补丁动态修复框架使用教程

Posted 一口仨馍

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android AndFix热补丁动态修复框架使用教程相关的知识,希望对你有一定的参考价值。

简介

已经上线的项目发现BUG,紧急修复BUG发布新版本?No,也许你需要AndFix。

AndFix 是阿里巴巴开源的 android 应用热修复工具,帮助 Anroid 开发者修复应用的线上问题。Andfix 是 “Android hot-fix” 的缩写。支持 Android 2.3 - 6.0,ARM 和 x86 架构,dalvik 运行时和 art 运行时。AndFix 的分支是 .apatch 文件。



GitHub地址 : https://github.com/alibaba/AndFix

原理图:

使用概述

1. 添加依赖

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

2 . 尽可能早的加载补丁

package com.dyk.andfixtest;

import android.app.Application;
import android.content.pm.PackageManager;

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

/**
 * Created by dyk on 2016/3/24.
 */
public class MyApplication extends Application 

    private static MyApplication instance;
    private PatchManager patchManager;

    public static MyApplication getInstance()
        return instance;
    

    @Override
    public void onCreate() 
        super.onCreate();
        instance = this;
        // 初始化patch管理类
        patchManager = new PatchManager(this);
        String appVersion = null;
        try 
            appVersion = getPackageManager().getPackageInfo(getPackageName(),0).versionName;
            // 初始化patch版本
            patchManager.init(appVersion);
            // 加载已经添加到PatchManager中的patch
            patchManager.loadPatch();
         catch (PackageManager.NameNotFoundException e) 
            e.printStackTrace();
        

    

    public PatchManager getPatchManager() 
        return patchManager;
    

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

3. 加载新补丁

MyApplication.getInstance().getPatchManager().addPatch(patchPath);

详细使用教程

1 . 添加依赖

2. 尽可能早的加载补丁

3. 修复bug,生成没有bug的apk文件

4. 对比新旧apk生成.apatch补丁文件

5. 加载新补丁,修复bug

前两步在使用概述中已经说明,不在赘述。修复bug,生成新apk也和正常一样。这里注意一个地方:生成新旧apk要使用同一个.jks签名文件。下面是一个示例

从一个Demo开始

制造bug

下面的代码假设在waitFix()里存在bug(Log.i(TAG, “waitFix bug”),我们目标是不发布新版本,改变这行log)

package com.dyk.andfixtest;

import android.app.Activity;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.View;
import android.view.Window;

import java.io.IOException;

public class MainActivity extends Activity 

    private static final String TAG = "AndFix";

    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.activity_main);
        findViewById(R.id.showLogBtn).setOnClickListener(new View.OnClickListener() 
            @Override
            public void onClick(View v) 
                waitFix();
            
        );

        findViewById(R.id.fixBtn).setOnClickListener(new View.OnClickListener() 
            @Override
            public void onClick(View v) 
                String patchPath = Environment.getExternalStorageDirectory()+"/tmp/first.apatch";
                try 
                    MyApplication.getInstance().getPatchManager().addPatch(patchPath);
                    Log.i(TAG,"fix bug, please reClick");
                 catch (IOException e) 
                    e.printStackTrace();
                    Log.i(TAG,"error:"+e.toString());
                
            
        );

    

    // 假设待修复的Bug在此方法中
    private void waitFix() 
        Log.i(TAG,"waitFix bug");
    

因为要读取.apatch文件,不要忘了添加限权。

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

此时我们签名运行apk,生成bug.apk。

// 已修复
private void waitFix() 
     Log.i(TAG,"fix bug");

修改bug后生成fix.apk。

生成.aptch补丁文件需要一个工具,点我下载。现在打开命令行(cmd),进入从刚下载工具的tools文件夹(我的是D:\\Temp\\AndFix\\AndFix-master\\tools,命令行为:d:回车,cd D:\\Temp\\AndFix\\AndFix-master\\tools)。将bug.apk、fix.apk和签名文件放入tools文件夹下。输入命令

apkpatch -o D:\\Temp\\AndFix\\output -k AndFix.jks -p admin888 -a 亚洲 -e admin888 -f fix.apk -t bug.apk

字段说明:
-o <output> : 输出目录
-k <keystore>: 打包所用的keystore
-p <password>: keystore的密码
-a <alias>: keystore 用户别名
-e <alias password>: keystore 用户别名密码
-f <new.apk> :新版本
-t <old.apk> : 旧版本

看见如上提示即生成.apatch文件成功。进入输出目录(-o 后面)。可以看到一个smail文件夹、diff.dex和一个.apatch文件。经常反编译别人apk的同学一定对smail文件夹不陌生。可以查看到代码,可惜才疏学浅看不懂.smail文件。这里我们要用到的是.apatch文件。

1. 更改.apatch文件名为first.apatch。

2. 安装bug.apk,真是个不吉利的名字。

3. 将first.apatch放入MainActivity里的patchPath路径下(我这里是/tmp/)。

4. 运行bug.apk

依次点击showLogBtn、fixBtn、showLogBtn。Log输出如下

可以看到Log输出已经改变,这也意味着带有Bug的方法被成功修复。

多次打补丁

如果本地保存了多个补丁,那么AndFix会按照补丁生成的时间顺序加载补丁。具体是根据.apatch文件中的PATCH.MF的字段Created-Time。

混淆

-keep class * extends java.lang.annotation.Annotation
-keepclasseswithmembernames class * 
    native <methods>;

探索

1. 修改first.apatch后缀名为.zip

2. 解压文件

打开META-INF中的文件PATCH.MF,可以看到如下内容

Manifest-Version: 1.0
Patch-Name: fix
Created-Time: 25 Mar 2016 08:28:00 GMT
From-File: fix.apk
To-File: bug.apk
Patch-Classes: com.dyk.andfixtest.MainActivity_CF
Created-By: 1.0 (ApkPatch)

可以发现Patch-Classes就是被改动过的文件,后面还加个_CF(CrossFire ?)。

使用dex2jar反编译classes.dex

1. 下载dex2jar和jd-gui,点我下载

2. 将classes.dex文件复制到dex2jar解压目录

3. 命令行进入dex2jar解压目录

4. 输入命令:d2j-dex2jar classes.dex

经过四招还我漂漂拳后,可以在dex2jar解压目录下发现classes-dex2jar.jar这么一个文件。

使用jd-gui打开classes-dex2jar.jar

package com.dyk.andfixtest;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import com.alipay.euler.andfix.annotation.MethodReplace;

public class MainActivity_CF extends Activity

  private static final String TAG = "AndFix";

  @MethodReplace(clazz="com.dyk.andfixtest.MainActivity", method="waitFix")
  private void waitFix()
  
    Log.i("AndFix", "fix bug");
  

  protected void onCreate(Bundle paramBundle)
  
    super.onCreate(paramBundle);
    requestWindowFeature(1);
    setContentView(2130968601);
    findViewById(2131492944).setOnClickListener(new MainActivity.1(this));
    findViewById(2131492943).setOnClickListener(new MainActivity.2(this));
  

可以发现.patch只是差异文件,这里给需要替换的方法添加了一个指定class和method的注解@MethodReplace(clazz="com.dyk.andfixtest.MainActivity", method="waitFix")。客户端sdk得到补丁文件后根据注解寻找需要替换的方法。最后由JNI层完成方法的替换。

以上是关于Android AndFix热补丁动态修复框架使用教程的主要内容,如果未能解决你的问题,请参考以下文章

android--------阿里 AndFix 热修复

Android 热补丁技术——资源的热修复

Andfix热修复框架原理及源码解析-上篇

Andfix热修复框架原理及源代码解析-上篇

Andfix热修复框架原理及源码解析-下篇

Andfix热修复框架原理及源码解析-下篇