Android 熱更新——非侵入AOP架構,android侵入aop架構

來源:互聯網
上載者:User

Android 熱更新——非侵入AOP架構,android侵入aop架構

Android 用戶端應用上線以後,一旦出現Bug,一般的解決思路是發修複包升級應用,這種方式不僅耗時,更重要的是使用者需要頻繁的升級版本,體驗不好,所以最佳化的思路是在不發版本的情況下熱更新,以期提高使用者體驗。

近期GitHub新出一種非侵入運行期AOP架構Dexposed, 下面簡單瞭解一下這個架構,GitHub地址。

簡要說明:

該架構基於AOP思想,支援經典的AOP使用情境,可應用於日誌記錄,效能統計,安全控制,交易處理,異常處理等方面。
針對Android平台,Dexposed支援函數層級的線上熱更新,例如對已經發布在應用市場上的宿主APK,當我們從crash統計平台上發現某個函數調用有bug,導致經常性crash,這時,可以在本地開發一個補丁APK,並發布到伺服器中,宿主APK下載這個補丁APK並整合後,就可以很容易修複這個crash。
Dexposed是基於久負盛名的開源Xposed架構實現的一個Android平台上功能強大的無侵入式運行時AOP架構。Dexposed的AOP實現是完全非侵入式的,沒有使用任何註解處理器,編織器或者位元組碼重寫器。

Patch原理

首先從GitHub上拉下來代碼有幾個坑需要注意:

  • 如果想直接拿過來用,你可能會失望而歸,因為patchsample這個android程式就沒有入口Activity,所以需要自行建立。
  • 注意Lib包如何添加,不能直接添加在libs這個工程自建的檔案中,應該放在lib檔案中,並手動添加java build依賴
  • 注意使用過程中不是像GitHub上那樣介紹的如此精簡,需要自行添加sunApkPatch代碼並適當添加捕獲異常操作,防止Patch包引起Crash。
  • patchsample只是個簡單的patch,如果需要增加比較複雜的patch,需要有依賴關係,為了縮小patch體積,這個依賴只能是部分依賴,所以推薦方式是將需要補丁的class檔案打jar包引入依賴即可。

接下來我們看看具體的流程:

首先需要我們動態監測AOP環境

runPatchApk();

這裡需要注意的是PatchMain.load()這個方法,該方法的主要用途是載入patch APK的所有類,並將實現IPatch的類添加到List中去,然後通過匹配載入的類或者類方法來實現非侵入式AOP。

public void runPatchApk() {    if (android.os.Build.VERSION.SDK_INT == 21) {        return;    }    if (!DexposedBridge.canDexposed(this)) {        Log.d("Hotpatch", "This device doesn't support dexposed!");        return;    }    File cacheDir = getExternalCacheDir();    if (cacheDir != null) {        String fullpath = cacheDir.getAbsolutePath() + File.separator + "PATCH_NAME.apk";        PatchResult result = PatchMain.load(this, fullpath, null);        if (result.isSuccess()) {            Log.e("Hotpatch", "patch success!");        } else {            Log.e("Hotpatch", "patch error is " + result.getErrorInfo());        }    }}
Patch實踐
public class Activity extends BaseSherlockSubActivity implements    OnNewIconUIRefreshListener {    private void showDialog() {    final AlertDialog.Builder builder = new AlertDialog.Builder(this);    builder.setTitle("Dexposed sample")            .setMessage("Please clone patchsample project to generate apk, and copy it to \"/Android/data/PACKAGE_NAME/cache/PATCH_NAME.apk\"")            .setPositiveButton("ok", new DialogInterface.OnClickListener() {                public void onClick(DialogInterface dialog, int whichButton) {                }            }).create().show();    }}

假如我們上線的代碼中如上所示,在彈層中出現文案bug,那麼該如何熱更新。
代碼修複操作在Patch工程中,添加如下代碼:

public class DialogPatch implements IPatch {    @Override    public void handlePatch(final PatchParam arg0) throws Throwable {        Class<?> cls = null;        try {            cls = arg0.context.getClassLoader().loadClass("com.android.activity.Activity");        } catch (ClassNotFoundException e) {            e.printStackTrace();            return;        }        DexposedBridge.findAndHookMethod(cls, "showDialog", new XC_MethodReplacement() {            @Override            protected Object replaceHookedMethod(MethodHookParam param) throws Throwable {                final Activity mainActivity = (Activity) param.thisObject;                AlertDialog.Builder builder = new AlertDialog.Builder(mainActivity);                builder.setTitle("Fanli Dexposed sample").setMessage("The dialog is shown from patch apk!").setPositiveButton("ok", new OnClickListener() {                    public void onClick(DialogInterface dialog, int whichButton) {                        Class<?> clsInner;                        try {                            clsInner = arg0.context.getClassLoader().loadClass("com.android.activity.OutObject");                        } catch (ClassNotFoundException e) {                            e.printStackTrace();                            return;                        }                        try {                            OutObject outObject = (OutObject) clsInner.newInstance();                            if (outObject.callFromOutMethod()) {                                AlertDialog.Builder builder = new AlertDialog.Builder(mainActivity);                                builder.setTitle("Fanli Dexposed sample").setMessage("com.android.activity.OutObject is Worked!")                                        .setPositiveButton("ok", new OnClickListener() {                                            @Override                                            public void onClick(DialogInterface dialog, int which) {                                                dialog.dismiss();                                            }                                        }).create().show();                            }                        } catch (InstantiationException e) {                            e.printStackTrace();                        } catch (IllegalAccessException e) {                            e.printStackTrace();                        }                    }                }).create().show();                return null;            }        });    }}

然後將這個patch APK 傳到Server,在主APK中通過下載patch apk到指定目錄,然後動態監測AOP環境並loadPatch即可實現熱更新。
接下來如果應用到實際項目中需要完善的有以下幾點:

Patch測試結果:

基於以上實現方案測試的環境包括:
Dalvik 4.0-4.4均已經通過
目前 ART 5.0 以及以上版本 尚未通過。(待更新Native包和Jar包)

著作權聲明:本文為博主原創文章,未經博主允許不得轉載。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.