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

上一篇文章,[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重命名。就是这么简单。看代码

 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);
        }
    }" data-snippet-id="ext.945172ad702cdd77e6eb82dfb50ae0a9" data-snippet-saved="false" data-csrftoken="gQzBFra4-c08xDIozpowxnhcjsfTrj0sxZZg" data-codota-status="done">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数组第二个参数指定的内容。

置于如何解析,这里不做展开了,代码太长,其实在android中会xml解析的都会解析。以pull方式解析的。倒是可以看看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)

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-08-02 03:44:56

Android插件化开发之Atlas生成插件信息列表的相关文章

Android插件化开发之Atlas插件适配

前三篇文章,介绍了OpenAtlas的一些基本用法以及patch的aapt的编译方法. - Android插件化开发之Atlas初体验 - Android插件化开发之Atlas生成插件信息列表 - Android插件化开发之Atlas资源打包工具补丁aapt的编译 OpenAtlas的原则就是避免引入冗余的库.也就是宿主中提供了第三方库后,插件中就不要再引入该库,编译的时候以provided形式提供即可.最简单的例子就是v4,v7兼容库,应该避免引入.为了让我妈的插件脱离OpenAtlas也能独

Android插件化开发之Atlas初体验

OpenAtlas一款强大的Android非代理动态部署框架,目前已经处于稳定定状态. 与传统的代理方式插件不同,OpenAtlas需要对注册动态部署的组件到manifest文件. 初体验,只不过就是把程序跑起来,跑通,后面的路还很长.这个过程中也是遇到了不少问题,刚开始拿到这个项目真是无处下手(没有看到有wiki),后来百度搜索了下找到四篇博文,大概就是OpenAtlas的作者写的吧 Android OpenAtlas初识 Android OpenAtlas之二 基本结构 OpenAtlas之

Androd插件化开发之Atlas资源打包工具补丁aapt的编译

我们先来看看Android Studio自动生成的R文件里的内容,你会发现,R文件里有很多内部类,而内部类里有很多int类型的值,他们都是以0x7f开头. 我们在编译一个Android应用程序的资源的时候,至少会涉及到两个包,其中一个是被引用的系统资源包,另外一个就是当前正在编译的应用程序资源包.每一个包都可以定义自己的资源,同时它也可以引用其它包的资源.那么,一个包是通过什么方式来引用其它包的资源的呢?这就是我们熟悉的资源ID了.资源ID是一个4字节的无符号整数,其中,最高字节表示Packag

Android插件化开发之OpenAtlas插件启动方式与插件启动广播

到现在为止已经写了6篇文章了 Android插件化开发之OpenAtlas初体验 Android插件化开发之OpenAtlas生成插件信息列表 Android插件化开发之OpenAtlas资源打包工具补丁aapt的编译 Android插件化开发之OpenAtlas插件适配 Android插件化开发之解决OpenAtlas组件在宿主的注册问题 Android插件化开发之OpenAtlas中四大组件与Application功能的验证 这篇文章主要介绍一下OpenAtlas插件的几种启动方式,在Atl

Android插件化开发之Hook StartActivity方法

第一步.先爆项目demo照片,代码不多,不要怕 第二步.应该知道Java反射相关知识 如果不知道或者忘记的小伙伴请猛搓这里,Android插件化开发基础之Java反射机制研究 http://blog.csdn.net/u011068702/article/details/49863931 第三步.应该知道Java静态代理知识 如果不知道或者忘记的小伙伴请猛搓这里,Android插件化开发基础之静态代理模式 http://blog.csdn.net/u011068702/article/detai

Android插件化开发之DexClassLoader动态加载dex、jar小Demo

一.温故动态加载ClassLoader机制 如果对Android的ClassLoader加载机制不熟悉,猛戳Android插件化开发动态加载基础之ClassLoader工作机制 http://blog.csdn.net/u011068702/article/details/53248960 二.介绍 我们知道在Android中可以跟java一样实现动态加载jar,但是Android使用德海Dalvik VM,不能直接加载java打包jar的byte code,需要通过dx工具来优化Dalvik

android插件化-apkplug从宿主启动插件Activity-06

插件是一个apk文件它存在自己的Activity界面和UI显示,本节将讲解如何配置插件的启动Activity以及怎样从宿主启动它. 一 配置插件apk的对外启动Activity (内部activity不需要配置) 与普通app不同,插件AndroidManifest.xml配置在apkplug框架中是无效的,我们需要在plugin.xml里面配置才能被apkplug所识别 具体设置属性为 Bundle-Activity="xxx.xxx.xxx.Activity" 只有设置为Bundl

Android Studio快速开发之道

概述 现如今开发越来越追求效率和节奏,节省出时间做更多的事情,除了开发技术上的封装等,开发工具的使用技巧也是很重要的,今天就根据自己的经验来给大家介绍一下Android Studio快速开发之道. Postfix completion 介绍 Postfix completion 是IntelliJ IDEA很早就有的功能,该功能基于已经输入的表达式和你添加的后缀来实现另一个你想要的表达式.例如在布尔表达式之后加上后缀if就是if语句 . 常用后缀介绍 下面介绍一下个人工作中觉得比较常用的几个后缀

android控件开发之ListView

android控件开发之ListView 本文主要讲述安卓开发中的ListView控件的使用方法 java代码: package com.example.listview; import java.util.ArrayList; import java.util.HashMap; import android.app.ListActivity; import android.os.Bundle; import android.view.Menu; import android.view.View