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,没有问题,其他的没有试过,因为没有手机。。。
希望这篇文章能帮助到你,当然你不想修复多次,也就没有这个问题了,前面说了一堆废话,只是想发泄一下(还可以筹字数。。。。嘎嘎)。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,793评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,567评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,342评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,825评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,814评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,680评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,033评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,687评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,175评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,668评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,775评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,419评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,020评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,206评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,092评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,510评论 2 343

推荐阅读更多精彩内容