Android插件化开发之OpenAtlas生成插件信息列表

上一篇文章,[Android插件化开发之Atlas初体验](
http://blog.csdn.net/sbsujjbcy/article/details/47446733),简单的介绍了使用Atlas的整个流程,但是如果你没有实践过的话估计还是一头雾水,从这篇文章开始,慢慢的切入细节。这篇文章的主题是生成插件信息列表。

细心的你或许发现了上篇文章中我们使用了一个叫openatlasbundler的项目生成了so以及一个json文件,说白了这个so只不过就是apk重命名的,而这个json文件中包含了插件的信息,比如上篇文章中的两个插件,其信息如下。

[
  {
    "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等。按照作者原话说是这样的。

BundleList的生成。这部分用的Java写的,BundleListInfo一个存储json的文本文件,我们所做的这一切无非是提高效率,举个例子,你安装插件的时候如果有动态库的话要解压,不能安装的时候每个文件检测一下apk存在so不,打开文件本来就慢,程序优化一点是一点

我们可以试试,如果不将该so文件打包进去,程序运行会出现什么。

这里写图片描述

这里写图片描述

这里写图片描述
我们发现,打印了一个日志说找不到插件信息列表。至于插件信息列表的读取,这里姑且不去理会,本篇的重点是如何生成该列表。

打开BundleMakeBooter类,里面就一个main函数,也就是说这个只不过是普通的java项目,其实我们可以从命令行将参数传入,但是还记得上篇文章我们将前三行代码注释掉,加入了三行写死的代码。

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都复制到该目录进行处理。

main函数中开始调用了ApkPreProcess.preProcess(path);将第一个参数传入,该函数所做的事其实很简单,就是将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,很简单有木有。

注意生成的json文件的文件名要为bundle-info.json,当然你也可以通过修改代码使用别的文件名,然后该文件要放在assets目录下。

解析该json文件的代码在openatlascore项目中的BundleParser类中的parser函数中,有兴趣可以先去看看。

接下来要做的事就是将该json打包进apk,把so放到对应目录,即armeabi目录下,按照作者的原话就是加快启动速度,可以见这个issue插件可以不放在主工程的libs/armeabi目錄下麼

还有,赶紧亲自试一试吧,只要亲自试过了之后,才会觉得,哦,原来是这么一回事啊。

什么,源代码,木有源代码,代码见上一篇文章末尾[Android插件化开发之Atlas初体验](
http://blog.csdn.net/sbsujjbcy/article/details/47446733)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值