Android热修复之AndFix使用教程

作者: Zach_C | 来源:发表于2016-08-03 15:49 被阅读8989次

    AndFix的github地址

    AndFix

    全称Android hot-fix,是alibaba的Android热修复框架,支持Android 2.3到6.0的版本,支持arm与X86系统架构,支持Dalvik和ART Runtime。

    原理

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

    原理-替换方法.png

    使用教程

    1. 添加依赖和混淆

        compile 'com.alipay.euler:andfix:0.4.0@aar'
    }```
       **混淆:**
    

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

    
    
    **2. 在Application.onCreate()中初始化PatchManager**
    
    

    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();
    
    }
    

    }

    **3. 找个地方加载补丁,我们这里为了演示,点击按钮进行加载补丁**
    
    findViewById(R.id.main_btn).setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            update();
        }
    });
    

    private static final String APATCH_PATH = "/fix.apatch"; // 补丁文件名

      
    
    private void update() {
        String patchFileStr = Environment.getExternalStorageDirectory().getAbsolutePath() + APATCH_PATH;
        try {
            AndFixApplication.mPatchManager.addPatch(patchFileStr);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    PatchManager的addPatch方法加载新补丁,项目中可以在下载补丁文件之后调用,这里为了演示就把补丁文件放在本地的SD卡中了,代码中patchFileStr就是补丁存放的位置,**.apatch**就是生成补丁文件的后缀名,fix就是补丁文件的名字,这里我们将其名字写死。
    我们看一下打补丁之前MainActivity的所有代码
    

    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.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();
    }
    
    /**
     * 动态更新,加载补丁文件
     * @author zehua_chen
     * create at 2016/8/3 14:35
     */
    private void update() {
        String patchFileStr = Environment.getExternalStorageDirectory().getAbsolutePath() + APATCH_PATH;
        try {
            AndFixApplication.mPatchManager.addPatch(patchFileStr);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    

    }

    **4. 我们将以上应用打包,我们命名为andfix_v1.0**
    ![andfix_v1.0.png](http:https://img.haomeiwen.com/i1689990/fea1230a4b800532.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
    
    **5. 修改MainActivity中的代码,打包成andfix_v2.0**
    
    private void showToast() {
        Toast.makeText(this, "打补丁之后", Toast.LENGTH_LONG).show();
    }
    
    mainTv.setText("加载了补丁之后");
    
    上面代码可知,我们只修改TextView的文字和TextView点击之后的Toast内容,然后打包
    ![andfix_v2.0.png](http:https://img.haomeiwen.com/i1689990/6375e8976f9aba23.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
    
    **6. 使用官方提供的工具[apkpatch](https://github.com/alibaba/AndFix/blob/master/tools/apkpatch-1.0.3.zip)生成.apatch补丁文件**
    点击上面的链接下载apkpatch之后解压
    ![apkpatch.png](http:https://img.haomeiwen.com/i1689990/d694879c1ef977f8.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
    将两个apk文件和该app的签名文件放入到该目录中
    ![加入签名文件和apk.png](http:https://img.haomeiwen.com/i1689990/9217393c8a6016e1.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
    
    使用命令生成.apatch补丁文件,先cmd进入该目录
    
    
    ![进人apkpatch目录.png](http:https://img.haomeiwen.com/i1689990/86d824a35b3a5f2d.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
    使用命令生成补丁
    ![生成补丁文件.png](http:https://img.haomeiwen.com/i1689990/4ea5d937652ad95f.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
    上图所示则表示补丁包生成完成
    
    <u>apkpatch.bat -f andfix_v2.0.apk -t andfix_v1.0.apk -o output -k AndFixKey.jks -p andfix -a andfix -e andfix</u>
    
    <u>apkpatch.bat -f 新apk -t 旧apk -o 输出目录 -k app签名文件 -p 签名文件密码 -a 签名文件别名 -e 别名密码</u>
    
    * -f <new.apk> :新apk
    * -t <old.apk> : 旧apk
    * -o <output> : 输出目录(补丁文件的存放目录)
    * -k <keystore>: 打包所用的keystore
    * -p <password>: keystore的密码
    * -a <alias>: keystore 用户别名
    * -e <alias password>: keystore 用户别名密码
    
    生成的output文件:
    ![生成的output文件.png](http:https://img.haomeiwen.com/i1689990/388d2802c9ec436a.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
    
    ![apatch补丁文件.png](http:https://img.haomeiwen.com/i1689990/ebf6c69cc76890e5.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
    
      将生成的.apatch补丁文件改成代码中写死的fix.apatch
    ![改名成fix.apatch.png](http:https://img.haomeiwen.com/i1689990/8d2aeead99d107d1.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
    
    **7.运行andfix_v1.0查看修复之前的效果,把补丁文件push到sd卡目录下, 点击Button更新按钮加载补丁文件,再看其效果,到这里我们就完成了AndFix的热修复了**
    
    ![打开File Explorer.png](http:https://img.haomeiwen.com/i1689990/1c2eb8b8edbe4209.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
    
    ![push fix.apatch文件到sd卡中.png](http:https://img.haomeiwen.com/i1689990/c9be1be105ffa32c.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
    
    * 运行andfix_v1.0没有点击动态更新按钮,点击TextView
    ![打补丁之前.jpg](http:https://img.haomeiwen.com/i1689990/cd3785eaec76e2f9.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
    * 点击动态更新Button之后再Toast,我们发现Tost的内容变了,但是TextView的内容没换
    ![动态更新再Toast.jpg](http:https://img.haomeiwen.com/i1689990/f38474939eeb74c5.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
    
    * 退出之后我们重新进入该应用就会发现TextView的内容也变化了。
    ![打补丁之后,退出再重新进入.jpg](http:https://img.haomeiwen.com/i1689990/5c5880c9d9525a77.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
    

    相关文章

      网友评论

      • b2d78b1a7ddf:博主,我尝试的一直没反应,是什么原因呢?方便指导吗?谢谢(qq:3480644007)
      • 郑永博:可以把mac怎么生成patch文件的命令给出来一下么 ?
      • 9b979b9665bc:求助!!! :pray: 现在官网的apkpatch-1.0.3 下载不了了吗,我从网上搜的,运行命令时,一直报错,有成功的吗?:pray:
      • 27902aa78e16:我的吐司也没变 什么原因
      • 27902aa78e16:为什么执行 apkpatch.bat 没有生成
        9b979b9665bc:你运行apkpatch.bat时,有报错吗?
      • 客观开发者:完美一样的效果。
      • luck_android:请问是否需要配置环境变量,为什么我使用命令行生成. apatch文件,提示-bash: apkpatch: command not found
      • c356d8511d88:大家好,按照步骤,最后运行时出现AndFixApplication.mPatchManager.addPatch(patchFileStr);这一行的空指针,求助
      • f0cf0e17c2c6:新加一个属性就没法打补丁,重大bug不是一两句代码就能搞定的,改多了不知道还能生成补丁不,感觉还是很有局限性
      • 07aa6ebbbe65:大神,如果应用被加固了,还可以热修复么?加固和热修复会冲突么?
      • 1c20410c5863:为什么打上补丁之后,吐司是正确的,TextView文字没变,但是按你说的,把应用返回之后,再点APP点不进去,闪退是怎么回事?????????
        71ab45a13ae1:同样问题,有没有大神解决的
        天高云淡wl:同样问题,怎么解决?
        王少华Jump:你现在解决了吗,现在也是这个问题。
      • keien:解决了,是忘记加存储权限了,不过最后还是报错了 java.lang.VerifyError
        坑太多了啊
      • keien:我查看data/data/包名/files/apatch/fix.apatch 这个文件大小是0,
        明明我放在sd根目录下的fix.apatch是有16329k
        b2d78b1a7ddf:请问,andfix的热修复,你能成功吗?能不能加个好友讨论一下(3480644007),感谢
      • 寂静台风: Process: com.yejun.andfix, PID: 2278
        java.lang.NullPointerException: Attempt to invoke virtual method 'void com.alipay.euler.andfix.patch.PatchManager.addPatch(java.lang.String)' on a null object reference
        at com.yejun.andfix.MainActivity.update(MainActivity.java:58)
        at com.yejun.andfix.MainActivity.access$100(MainActivity.java:12)
        at com.yejun.andfix.MainActivity$2.onClick(MainActivity.java:37)
        at android.view.View.performClick(View.java:4785)
        at android.view.View$PerformClick.run(View.java:19888)
        at android.os.Handler.handleCallback(Handler.java:739)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:135)
        at android.app.ActivityThread.main(ActivityThread.java:5276)
        at java.lang.reflect.Method.invoke(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:372)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:911)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:706)
        12-23 11:43:29.051 1363-1380/? E/ActivityManager: Invalid thumbnail dimensions: 0x0
      • Android_Liu:FATAL EXCEPTION: main
        Process: com.cainiaotv.hotfix, PID: 3332
        java.lang.NoSuchMethodError: Landroid/animation/Animator;.addListener
        at com.cainiaotv.hotfix.MainActivity.showToast(MainActivity.java)
        at com.cainiaotv.hotfix.MainActivity.access$000(MainActivity.java:16)
        at com.cainiaotv.hotfix.MainActivity$1.onClick(MainActivity.java:46)
        at android.view.View.performClick(View.java:4747)
        at android.view.View$PerformClick.run(View.java:19454)
        at android.os.Handler.handleCallback(Handler.java:733)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:146)
        at android.app.ActivityThread.main(ActivityThread.java:5752)
        at java.lang.reflect.Method.invokeNative(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:515)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1291)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1107)
        at dalvik.system.NativeStart.main(Native Method)
        大神 打补丁之后 点击toast 就报错 怎么回事啊
        Zach_C:@Android_Liu 你好,方法没有找到,补丁的代码没有问题么?
      • WHOKNOWME:写的不错。
        想问下一,你用下来有遇到什么坑吗?
        Zach_C:@WHOKNOWME 没有用
        WHOKNOWME:你们公司的项目用的是什么热修复技术?
        Zach_C:@WHOKNOWME 不好意思,这当然我也只是尝试用用,并没有用到自己项目中,所以对其中的坑可能不太了解,据我了解现阶段热更新这类技术中的坑还是挺多的,这也是为没有用到公司项目中的原因
      • 萌芽哦:怎么连续打补丁呢,我试了试,补丁只能生效一次,打过补丁之后,再有新补丁打不上哦貌似,有办法没有?
        Yellon:@anhao_chan 对于二次补丁或者更多次补丁这块我有点疑问想要请教一下。 第一次补丁成功之后。如何再打第二次补丁。。如果code2和code1的补丁A.apatch升级后。再用code3和code2的补丁B.apatch升级。那么就完成了两次次升级么?
        8d163c981424:保存的patch的文件名不能相同
        Zach_C:@萌芽哦 你好,新补丁得在修改后的基础上补丁额
      • 捡淑:mk
        Zach_C:@捡淑 多谢关注 :smiley:
      • 5c86e01fae2c:学习一下
        Zach_C:@偶尔犯贱 多谢关注 :smiley:
      • Yang_Bob:混淆怎么弄呢
        Zach_C:@bobyang912 放的路径对么,是不是用了加固保
        Yang_Bob:@anhao_chan 发现直接混淆过后补丁加载完没有作用了,是不是前后两次混淆后不能识别了,需要mapping.txt标志一下,试了几下没效果,可否测试下成功后接着更新完
        Zach_C:@bobyang912 多谢提醒,不好意思忘了把混淆写上了
        -keep class * extends java.lang.annotation.Annotation
        -keepclasseswithmembernames class * {
        native <methods>;
        }
      • 漫唐:写的很好,清楚简明

      本文标题:Android热修复之AndFix使用教程

      本文链接:https://www.haomeiwen.com/subject/jxvqsttx.html