andfix 多次修改同一个方法报错的解决

关于andfix 看这

最近主管说要把热修复做下,组长把任务交给了我,那就领命开始干,网上找了几篇文章学习了下,最后选择了andfix。在网上找了几篇文章学习了下,感觉just so so嘛,我的内心开始膨胀(只是滚轮子嘛)。
遇到了几个问题,5.0以下同一个方法可以多次修改,5.0以上不行这个问题困扰我很久,报错如下:

Fatal Exception: java.lang.IllegalAccessError: Method 'void com.amour.chicme.activity.MainActivity_CF.q()' is inaccessible to class 'com.amour.chicme.activity.MainActivity_CF' (declaration of 'com.amour.chicme.activity.MainActivity_CF' appears in /data/user/0/com.amour.chicme/files/apatch/572340d6d21e9e13ac2d7556.apatch)
       at com.amour.chicme.activity.MainActivity_CF.onCreate(Unknown Source)
       at android.app.Activity.performCreate(Activity.java:6237)
       at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1107)
       at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2369)
       at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476)
       at android.app.ActivityThread.-wrap11(ActivityThread.java)
       at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344)
       at android.os.Handler.dispatchMessage(Handler.java:102)
       at android.os.Looper.loop(Looper.java:148)
       at android.app.ActivityThread.main(ActivityThread.java:5417)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

至于为什么报这个错误的原因,不知道。。。知道的哥们麻烦告诉我。
既然不能解决这个错误,那只好绕过这个坑了,于是我把将patch文件做成最初版本apk和最新修改过的apk对比生成,andfix对外提供了一个方法patchManager.removeAllPatch()从字面上就能理解这个方法了,去除所有的.apatch文件。so,在每次下载成功后patchManager.addPatch(target)前我调用前面的patchManager.removeAllPatch()方面。看起来一切是如此的合理,此时的我已经膨胀的快要爆炸了。接下来的结果让我很是意外,在修复当前patch文件完成后,再次启动app,最新的已经修复过的patch不再下载和add,此时没有进行addpatch()操作,于是app变成了最初的版本,没有任何修复完成。在我的理解中,这两步操作patchManager.removeAllPatch();patchManager.addPatch( target);可以永远只保留最后修复过的那个.apatch文件,就不会出现多次修改同一个方法的情况了,看上去完全没有问题啊,我迷茫了。。。我开始意识到andfix肯定在某个步骤中将我最后保留的.apatch文件清除了,我对着源码寻寻觅觅,发现patchManager.removeAllPatch()不仅仅只是清除了.apatch文件,他还清除了当前的SharedPreferences文件

public void removeAllPatch() {  
  cleanPatch();   
  SharedPreferences sp = mContext.getSharedPreferences(SP_NAME,   Context.MODE_PRIVATE);   
  sp.edit().clear().commit();
}

于是在init时

public void init(String appVersion) {
   if (!mPatchDir.exists() && !mPatchDir.mkdirs()) {// make directory fail
      Log.e(TAG, "patch dir create error.");
      return;
   } else if (!mPatchDir.isDirectory()) {// not directory      mPatchDir.delete();
      return;
   }
   SharedPreferences sp = mContext.getSharedPreferences(SP_NAME, Context.MODE_PRIVATE);
   String ver = sp.getString(SP_VERSION, null);
   if (ver == null || !ver.equalsIgnoreCase(appVersion)) {
      cleanPatch();
      sp.edit().putString(SP_VERSION, appVersion).commit();
   } else {
      initPatchs();
   }
}

获取到的ver为null,于是我自认为能保留下来的.apatch文件也被删除了。
接下来我采取了如下两种措施:
1、不直接调用removeAllPatch()反射调用 cleanPatch();
2、听取网上哥们的意见,在removeAllPatch()后自己将移除的SharedPreferences 文件保存下来,将版本号保存。
最后的结果还是报错,错误还是上面列出来的。
此时的我有点心累。。好受伤。。
最后和组长讨论了下,他说何不自己建立目录保存.apatch文件呢?一语惊醒梦中人啊!方案出来了:
1、在file目录下建立一个文件夹保存.apatch文件(ps:andfix就是这么做的),将下载的文件保存在里面。当然,文件名要是个唯一标识。

private void uploadFixData(final Hotfix hotfix) {
    File file = new File(getFilesDir(), "hotfix");
    if (!file.exists() && !file.mkdirs()){
        return;
    }
    final String target = file.getAbsolutePath() + "/" + hotfix.id + ".apatch";    
    ConfigManager.getInstance().downloadHotfixFile(hotfix.patchUrl, target, new RequestCallBack<File>() {
        @Override
        public void onSuccess(ResponseInfo<File> responseInfo) {
            try {
                patchManager.removeAllPatch();
                patchManager.addPatch( target);
                SPUtils.save("hotfix", "hotfixID", hotfix.id);
            } catch (Exception e) {
                addLastApatch();
                UIUtils.showToast(e.toString());
                SPUtils.save("hotfix", "hotfixID", "0");
                e.printStackTrace();
            }
        }
        @Override
        public void onFailure(HttpException e, String s) {
            addLastApatch();
        }
    });
}

2、检查有更新文件时,将先前自己保存的文件删除,再去下载文件。保证只保留一个文件,多的浪费存储空间。

private void checkAndfixData() {
    ConfigManager.getInstance().getAppHotfixData(new RequestCallBack<String>() {
        @Override
        public void onSuccess(ResponseInfo<String> responseInfo) {
            ResponseUtils responseUtils = new ResponseUtils(responseInfo.result);
            if (responseUtils.isSuccess()) {
                Hotfix hotfix = responseUtils.onSuccessModel(Hotfix.class);
                String existId = SPUtils.getString("hotfix", "hotfixID");                if (hotfix == null || TextUtils.isEmpty(hotfix.id)) {
                    return;
                } else if (hotfix != null && !hotfix.id.equals(existId)) {                                       
                    File file = new File(getFilesDir(), "hotfix");
                    if (file.exists()){
                        file.delete();
                    } 
                   uploadFixData(hotfix);
                } else {
                    addLastApatch();
                }
            } else {
                String existId = SPUtils.getString("hotfix", "hotfixID");
                if (!TextUtils.isEmpty(existId)) {
                    addLastApatch();
                }
            }
        }
        @Override
        public void onFailure(HttpException e, String s) {           
            addLastApatch();
        }
    });
}

3、addLastApatch()的实现很简单。在检查更新时如果没有更新就直接加载最后保留的那个,当然本身就没有更新文件,那就不用加载,可以通过查看保留的唯一标识来判断。

private void addLastApatch() {
    try {
        File file = new File(getFilesDir(), "hotfix");
        if (!file.exists()){
            return;
        }
      String lastApatchPath = file.getAbsolutePath() + "/" + SPUtils.getString("hotfix", "hotfixID") + ".apatch";
      patchManager.addPatch(lastApatchPath);
    } catch (IOException e) {
        e.printStackTrace();
    }
}

至此,问题解决了。试过三星NOTE3,红米note2,nexus 5,LG,没有问题,其他的没有试过,因为没有手机。。。
希望这篇文章能帮助到你,当然你不想修复多次,也就没有这个问题了,前面说了一堆废话,只是想发泄一下(还可以筹字数。。。。嘎嘎)。



文/未来蚁族(简书作者)
原文链接:http://www.jianshu.com/p/58fc4c2cb65a
著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值