Android Hotpatch系列之-項目介紹

    在手淘工做期間,內部有一套解決方案,給線上apk打補丁,直接修復bug,不用客戶端升級,有嚴重線上bug,找到問題,寫個patch,推上線就把問題解決了,用過的都說好。前段時間,他們終於把這套東西的Android端開源了,Dexposed,具體能夠看詳細的項目介紹。其功能就是能夠加載類,替換原先apk裏面某個類的方法,或者在方法以前,方法以後作些什麼,好比在方法執行以前,修改傳入方法的參數了,方法執行之後,修改方法的返回值,或者就是徹底替換掉原先的方法。
java

    項目裏面有一個sample,介紹瞭如何加載一個外部apk包,而後替換宿主apk裏面類的方法。其實這就已經完成了80%的工做了,我作的工做只是將Patch獲取從本地加載改爲了去服務器獲取,以及添加了Patch apk的校驗(md5和簽名信息)。git

    Hotpatch的工做流程是:github

         1.實現一個從服務器端獲取Patch信息的接口(上傳本地客戶端版本等信息,服務器好根據這些信息來判斷是否有對應的Patch包),並將這個信息注入給HotpatchManager。
tomcat

         2.檢測客戶端是否能夠支持。(Android L和Android M)目前都不支持,最低支持2.3服務器

         3.若是客戶端支持,那就調用第一步注入的Patch包獲取類,獲取到對應的Patch信息。下載Patch apk文件。app

         4.校驗。獲取下載好的Patch apk md5簽名信息和服務器給的Patch信息的md5值是否同樣,而後還要校驗Patch apk和宿主apk簽名是否一致。加校驗是爲了防止Patch apk被篡改,若是load進去了一個第三方的Patch,那就是引狼入室了。必定不能去掉校驗,不能去掉,不能去掉,重要的事情說三遍!!!ide

         5.校驗成功,就load Patch apk。ui

   下面是貼代碼時間:url

public class HotpatchManager {
    private static HotpatchManager INSTANCE=new HotpatchManager();
    private HotpatchManager() {

    }

    public static HotpatchManager getInstance(IPatchInfoRequest request){
        RequestManager.getInstance().setIPatchInfoRequest(request);
        return INSTANCE;
    }

    public boolean init(final Context ctx) {
        boolean isSupport = DexposedBridge.canDexposed(ctx);
        if (isSupport) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    check(ctx);
                }
            }).start();
        }
        return isSupport;
    }

    private  void check(final Context ctx) {
        RequestManager manager = RequestManager.getInstance();
        manager.setIPatchInfoRequest(RequestManager.getInstance().getIPatchInfoRequest());
        manager.reqeust(new RequestManager.OnRequestCallBackListener() {
            @Override
            public void onRequest(final PatchInfo info) {
                if (null != info) {
                    String apkPath = Utils.getCacheApkFilePath(ctx, info.apkFileUrl);
                    File file = new File(apkPath);
                    if (file.exists()) {
                        loadPath(info, ctx, apkPath);
                    } else {
                        DownLoadManager.getInstance().downloadFile(ctx, info.apkFileUrl, new DownLoadManager.OnFileDownload() {
                            @Override
                            public void fileDownload(String apkFilePath) {
                                loadPath(info, ctx, apkFilePath);
                            }
                        });
                    }
                }
            }
        });
    }

    private  void loadPath(PatchInfo info, Context ctx, String apkFilePath) {
        if (Utils.isSignEqual(ctx, apkFilePath) && TextUtils.equals(info.apkMd5, Utils.getMd5ByFile(new File(apkFilePath)))) {
            PatchMain.load(ctx, apkFilePath, null);
        }
    }

}

  

    已經提供了實現好的客戶端和服務器例子。網址分別是:spa

    客戶端例子實現:https://github.com/fengcunhan/Hotpatch-Sample

   服務器簡易實現:https://github.com/fengcunhan/Hotpatch-SimpleServer

    運行例子步驟:

    1.修改 DefaultPatch類中的info.patchApkUrl  的url中的IP替換成你的服務器的IP,將代碼部署到tomcat中。

    2.導入Hotpatch-Sample中的工程到Android Studio中。

    3.打開網址 http://服務器IP:服務器端口/PathServer,將patchsample下build/outputs/apk/app-debug.apk上傳到服務器上面,必定不要更名字。

    4.修改DefaultPatchInfoRequest 中的hostUrl的IP和端口爲你的服務器端IP和端口。  

    5.運行dexposedexamples項目,點擊 Check Hotpatch,若是出現 「The dialog is shown from patch apk」,恭喜你,成功運行了Demo。

     Demo中的Patch只是很簡單的一個例子,後續會碰到混淆的類怎麼怎麼寫Patch之類的問題,這些都將在之後一一敘述。請你們關注這個Hotpatch系列。     

     Demo中服務器實現很渣渣。請服務器端大神不要噴,能夠fork,不要fuck。

相關文章
相關標籤/搜索