Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android編程入門 >> Android熱修復實踐應用--AndFix

Android熱修復實踐應用--AndFix

編輯:Android編程入門

一直關注App的熱修復的技術發展,之前做的應用也沒用使用到什麼熱修復開源框架。在App的熱修復框架沒有流行之前,做的應用上線後發現一個小小的Bug,就要馬上發一個新的版本。我親身經歷過一周發兩個版本,真的折騰用戶的節奏~~所以,要開始考慮引入熱修復。下面記錄使用開源框架阿裡巴巴的AndFix過程。

實現的原理

這裡說的不是熱修復怎麼實現修bug的原理,這裡說的是怎麼使用AndFix。如果你想了解更多的andFix實現原理,你可以參考下面的文章:

  • https://github.com/alibaba/AndFix (AndFix的官網)
  • http://blog.csdn.net/lmj623565791/article/details/49883661 (Android大神鴻洋的Bolg文章)

 

  1. 應用啟動的時候,在 onCreate() 方法中獲取友盟的在線參數來判斷當前的應用版本是否有補丁需要下載,有則通過ThinDonloadManager來下載到SD下並且通過使用AndFix來加載到應用中。
  2. 使用極光推送消息到該應用的版本需要下載補丁,如果應用收到了消息後,應用判斷當前的版本是否需要下載補丁。如果應用沒有收到消息的通知,則下次啟動App的時候,獲取友盟在線參數來判斷是否需要下載補丁。
步驟
  1. 在gradle文件中增加相應的依賴。這裡我使用thindownlaodmanager來下載補丁,使用極光推送來推送自定義消息下載補丁通知,使用友盟在線參數來獲取補丁包的信息。也許你會問為了修復一個補丁而增加這麼多的依賴,值得嗎?我認為還可以吧,因為我的項目一般會使用到這些。

    AndFix的引入是: compile 'com.alipay.euler:andfix:0.3.1@aar'

     

  2. 導入AndFix的so庫文件以及極光推送的so庫文件;
    極光推送集成參考文檔:http://docs.jpush.io/client/android_sdk/
    注意:導入AndFix的so文件時,可以先閱讀這下個:https://github.com/zhonghanwen/AndFix-Ndk-Build-ADT

    • 接著,集成友盟在線參數
      參考官方文檔:http://dev.umeng.com/online-parameters/android-doc/intergration

     

  3. 配置友盟在線參數的參數以及推光推送自定義的內容

    • 友盟在線參數

    • 極光推送自定義消息(自定義消息有長度限制,所以補丁的下載url寫成拼接形式:站點+下載資源名稱)

    • 定義相對應的Bean

     

  4. 在啟動的自定義Application類進行初始化工作(AndFix、極光的初始化)

  5. 在程序的入口類進行友盟補丁的檢測:

    private void getUmengParamAndFix() {
        //獲取友盟在線參數對應key的values
        String pathInfo = OnlineConfigAgent.getInstance().getConfigParams(this, UMENG_ONLINE_PARAM);
        if (!TextUtils.isEmpty(pathInfo)){
            PatchBean onLineBean = GsonUtils.getInstance().parseIfNull(PatchBean.class , pathInfo);
            try {
                //進行判斷當前版本是否有補丁需要下載更新
                RepairBugUtil.getInstance().comparePath(this, onLineBean);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    

      

     

  6. 再加上推送推送的自定義內容的處理:(當推送消息過來的時候應用處於運行狀態的時候,程序會處理消息進行下載補丁包)

        private WeakHandler mHandler = new WeakHandler(new Handler.Callback() {
        @Override
        public boolean handleMessage(Message msg) {
            if (msg.what == MSG_WHAT_DOWNLOAD){
                String message = (String) msg.obj;
                if (TextUtils.isEmpty(message)) return false;
                try {
                    PatchBean bean = GsonUtils.getInstance().parse(PatchBean.class, message);
                    RepairBugUtil.getInstance().comparePath(MainActivity.this, bean);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            return false;
        }
    });
    
    
    
    //for receive customer msg from jpush server
    private MessageReceiver mMessageReceiver;
    public static final String MESSAGE_RECEIVED_ACTION = "com.zhw.andfix.MESSAGE_RECEIVED_ACTION";
    public static final String KEY_MESSAGE = "message";
    
    public void registerMessageReceiver() {
        mMessageReceiver = new MessageReceiver();
        IntentFilter filter = new IntentFilter();
        filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
        filter.addAction(MESSAGE_RECEIVED_ACTION);
        registerReceiver(mMessageReceiver, filter);
    }
    
    public class MessageReceiver extends BroadcastReceiver {
    
        @Override
        public void onReceive(Context context, Intent intent) {
            if (MESSAGE_RECEIVED_ACTION.equals(intent.getAction())) {
                String message = intent.getStringExtra(KEY_MESSAGE);
                Message msg = new Message();
                msg.what = MSG_WHAT_DOWNLOAD;
                msg.obj = message;
                mHandler.sendMessage(msg);
            }
        }
    }
    

      

     

  7. 補丁包的生成

    • 下載AndFix的補丁生成工具:here
    • 生成補丁的文件需要的文件有:原apk文件,修復Bug後生成的新apk,簽名文件。
    • 在解壓apkpatch工具的目錄下,打開命令行輸入以下命令生成補丁包。apkpatch -m <apatch_path...> -o <output> -k <keystore> -p <***> -a <alias> -e <***>
    • 將生成的補丁放到指定服務器上。(這裡我放到了七牛上)

     

  8. 自己測試一下成不成啦~

代碼

通過ThinDownloadManager下載補丁包,下載成功後使用AndFix加載補丁包的方法:

public void downloadAndLoad(Context context, final PatchBean bean, String downloadUrl) {
    if (mLocalPreferencesHelper == null) {
        mLocalPreferencesHelper = new LocalPreferencesHelper(context, SPConst.SP_NAME);
    }
    Uri downloadUri = Uri.parse(downloadUrl);
    Uri destinationUri = Uri.parse(Environment.getExternalStorageDirectory()
            .getAbsolutePath() + bean.url);
    DownloadRequest downloadRequest = new DownloadRequest(downloadUri)
            .setDestinationURI(destinationUri)
            .setPriority(DownloadRequest.Priority.HIGH)
            .setDownloadListener(new DownloadStatusListener() {
                @Override
                public void onDownloadComplete(int id) {
                    // add patch at runtime
                    try {
                        // .apatch file path
                        String patchFileString = Environment.getExternalStorageDirectory()
                                .getAbsolutePath() + bean.url;
                        BaseApplication.mPatchManager.addPatch(patchFileString);
                        Log.d(TAG, "apatch:" + patchFileString + " added.");

                        //復制且加載補丁成功後,刪除下載的補丁
                        File f = new File(patchFileString);
                        if (f.exists()) {
                            boolean result = new File(patchFileString).delete();
                            if (!result)
                                Log.e(TAG, patchFileString + " delete fail");
                        }
//                            mLocalPreferencesHelper.saveOrUpdate(SPConst.IsHavePathDownLoad, false);
                    } catch (IOException e) {
                        Log.e(TAG, "", e);
                    } catch (Throwable throwable) {

                    }
                }

                @Override
                public void onDownloadFailed(int id, int errorCode, String errorMessage) {
                    //下載失敗的時候,標注標記位,等下次重新打開應用的時候重新下載
//                        mLocalPreferencesHelper.saveOrUpdate(SPConst.IsHavePathDownLoad, true);
                    Log.e(TAG, "onDownloadFailed");

                }

                @Override
                public void onProgress(int id, long totalBytes, int progress) {
                    Log.e(TAG, "progress:" + progress);
                }
            });
    mDownloadManager = new ThinDownloadManager(THREAD_COUNT);
    mDownloadManager.add(downloadRequest);
}

  

判斷是否有補丁包需要下載的方法:

  public void comparePath(Context context, PatchBean RemoteBean) throws Exception {
    String pathInfo = mLocalPreferencesHelper.getString(SPConst.PATH_INFO);
    final PatchBean localBean = GsonUtils.getInstance().parseIfNull(PatchBean.class, pathInfo);
    //遠程的應用版本跟當前應用的版本比較
    if (BaseApplication.VERSION_NAME.equals(RemoteBean.app_v)) {
        //遠程的應用版本跟本地保存的應用版本一樣,但補丁不一樣,則需要下載重新
        /**
         *第一種情況:當本地記錄的Bean為空的時候(剛安裝的時候可能為空)並且遠程的Bean的path_v不為空的時候需要下載補丁。
         * 第二種情況:當本地記錄的path_v和遠程Bean的path_v不一樣的時候需要下載補丁。
         */
        if (localBean == null && !TextUtils.isEmpty(RemoteBean.path_v)
                || localBean.app_v.equals(RemoteBean.app_v) &&
                !localBean.path_v.equals(RemoteBean.path_v)) {
            downloadAndLoad(context, RemoteBean,
                    SPConst.URL_PREFIX + RemoteBean.url);
            String json = GsonUtils.getInstance().parse(RemoteBean);
            mLocalPreferencesHelper.saveOrUpdate(SPConst.PATH_INFO, json);
        } /*else {
            mLocalPreferencesHelper.saveOrUpdate(SPConst.IsHavePathDownLoad, false);
        }*/
    }
}

  

項目GitHub地址:https://github.com/zhonghanwen/AndFix-Bad-Practices

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved