上一篇文章。[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)