Android插件化開發之OpenAtlas生成插件信息列表

上一篇文章。[Android插件化開發之Atlas初體驗](
http://blog.csdn.net/sbsujjbcy/article/details/47446733),簡單的介紹了使用Atlas的整個流程,但是假設你沒有實踐過的話預計仍是一頭霧水。從這篇文章開始,慢慢的切入細節。這篇文章的主題是生成插件信息列表。java

細心的你也許發現了上篇文章中咱們使用了一個叫openatlasbundler的項目生成了so以及一個json文件,說白了這個so僅僅只是就是apk重命名的。而這個json文件裏包括了插件的信息。比方上篇文章中的兩個插件,其信息例如如下。android

[
  {
    "pkgName": "com.lizhangqu.test",
    "version": "1.0",
    "activities": [ "com.lizhangqu.test.MainActivity" ],
    "services": [],
    "receivers": [],
    "contentProviders": [],
    "dependency": [],
    "md5": "882d50a3c2668360b96a3af8f72b3bd2",
    "size": 24780,
    "hasSO": false },
  {
    "pkgName": "com.lizhangqu.zxing",
    "version": "1.0",
    "activities": [ "com.lizhangqu.zxing.android.CaptureActivity" ],
    "services": [],
    "receivers": [],
    "contentProviders": [],
    "dependency": [],
    "md5": "e68270557ae9776d218bb034916c124a",
    "size": 312352,
    "hasSO": false }
]

可以看到裏面存了插件的一些組件信息。以及大寫和md5等。git

依照做者原話說是這種。github

BundleList的生成。這部分用的Java寫的,BundleListInfo一個存儲json的文本文件,咱們所作的這一切無非是提升效率,舉個樣例。你安裝插件的時候假設有動態庫的話要解壓。不能安裝的時候每一個文件檢測一下apk存在so不。打開文件原本就慢。程序優化一點是一點apache

咱們可以試試,假設不將該so文件打包進去,程序執行會出現什麼。json

這裏寫圖片描寫敘述

這裏寫圖片描寫敘述

這裏寫圖片描寫敘述
咱們發現,打印了一個日誌說找不到插件信息列表。數組

至於插件信息列表的讀取。這裏姑且不去理會,本篇的重點是怎樣生成該列表。markdown

打開BundleMakeBooter類,裏面就一個main函數,也就是說這個僅僅只是是普通的java項目,事實上咱們可以從命令行將參數傳入,但是還記得上篇文章咱們將前三行代碼凝視掉,增長了三行寫死的代碼。app

args=new String[2];
args[0]="C:\\Users\\kltz\\Desktop\\AtlasDemo\\plugin";
args[1]="C:\\Users\\kltz\\Desktop\\AtlasDemo\\plugin\\bundle-info.json";

數組第一個參數表明待處理的apk所在文件夾,數組第二個參數表明生成的插件信息存的文件。而咱們是在項目根文件夾創建一個文件夾叫plugin,後來將插件的apk都拷貝到該文件夾進行處理。ide

main函數中開始調用了ApkPreProcess.preProcess(path);將第一個參數傳入,該函數所作的事事實上很是easy,就是將apk重命名爲so,怎麼個重命名法呢。

首先遍歷該文件夾,獲得以apk後綴的文件,經過解析拿到該apk的包名,將該apk命名爲lib開頭。後面緊跟包名。包名中的.會被替換成_。最後文件後綴是so,假設該文件夾存在了該so,則將原so文件刪除。而後將apk重命名。就是這麼簡單。

看代碼

public static void preProcess(String mDir) {
        Collection<File> apkFiles = org.apache.commons.io.FileUtils.listFiles(new File(mDir), new String[]{"apk"}, true);

        for (File file : apkFiles) {
            String pkgName = PackageLite.parse(file.getAbsolutePath()).packageName;

            pkgName = "lib" + pkgName.replaceAll("\\.", "_") + ".so";
            File targetFile = new File(mDir + File.separator + pkgName);
            if (targetFile.exists())
                targetFile.delete();

            System.out.println("rename: " + file.getName() + " -> " + pkgName);
            while(!file.renameTo(targetFile)) {
                System.gc();
                Thread.yield();
            }
            System.out.println("ApkPreProcess.preProcess() processed " + pkgName);
        }
    }

重命名完畢後接下來就是遍歷該文件夾,查找以libcom_開頭的的文件,注意這裏是一個約定,就是包名以com開頭。

而後經過PackageLite.parse()函數解析每一個so。經過packageLit.getBundleInfo()函數得到解析結果並將其扔到一個json數組中去。最後將該json數組寫入文件。也就是args數組第二個參數指定的內容。

置於怎樣解析,這裏不作展開了,代碼太長。事實上這個已經涉及到反編譯的範疇了,事實上該項目的一大部分源代碼是AXMLPrinter的源代碼。一個android xml反編譯的東西,這裏提供源代碼下載AXMLPrinter。 卻是可以看看getBundleInfo()函數

public JSONObject getBundleInfo() throws JSONException {
        JSONObject jsonObject=new JSONObject();
        jsonObject.put("pkgName", packageName);
        jsonObject.put("version", versionName);
        JSONArray activityArray=new JSONArray();
        for (String name:activitys) {
            activityArray.put(name);
        }
        jsonObject.put("activities", activityArray);
        JSONArray servicesArray=new JSONArray();
        for (String name:services) {
            servicesArray.put(name);
        }
        jsonObject.put("services", servicesArray);
        JSONArray receiversArray=new JSONArray();
        for (String name:receivers) {
            receiversArray.put(name);
        }
        jsonObject.put("receivers", receiversArray);

        JSONArray providersArray=new JSONArray();
        for (String name:providers) {
            providersArray.put(name);
        }
        jsonObject.put("contentProviders", providersArray);
        JSONArray dependencyArray=new JSONArray();
        for (String name:dependency) {
            dependencyArray.put(name);
        }
        jsonObject.put("dependency", dependencyArray);
        jsonObject.put("md5", apkMD5);
        jsonObject.put("size", size);
        jsonObject.put("hasSO", hasSO);
 return jsonObject;

    }

事實上就是將解析結果轉化爲json。很是easy有木有。

注意生成的json文件的文件名稱要爲bundle-info.json,固然你也可以經過改動代碼使用別的文件名稱,而後該文件要放在assets文件夾下。

解析該json文件的代碼在openatlascore項目中的BundleParser類中的parser函數中,有興趣可以先去看看。

接下來要作的事就是將該json打包進apk,把so放到相應文件夾。即armeabi文件夾下,依照做者的原話就是加快啓動速度,可以見這個issue插件可以不放在主project的libs/armeabi目錄下麼

還有,趕忙親自試一試吧,僅僅要親自試過了以後,纔會認爲,哦。原來是這麼一回事啊。

什麼,源代碼。木有源代碼,代碼見上一篇文章末尾[Android插件化開發之Atlas初體驗](
http://blog.csdn.net/sbsujjbcy/article/details/47446733)

相關文章
相關標籤/搜索