VirtualAPK 插件化项目实践

项目VirtualApkProgram中采用要实行插件化首先考虑的是采用哪种方式,怎么实现等等,经过一番调研发现目前比较火的插件化的优缺点大概有如下几种,如图:

各大插件化方案比较

        考虑到自己项目中可能需要进行宿主与插件之间进行通信,宿主与插件之间有些功能无法解藕,所以最终选择使用virtualAPK来实现插件化功能需求(如果加载独立插件,宿主和插件没有频繁业务逻辑推荐采用DroidPlugin),virtualapk对编译环境有很大的限制,我宿主项目和插件项目中使用的编译环境是:'com.android.tools.build:gradle:2.3.3'(刚更新了,支持3.1.0)。

        在项目开始时,在主项目中进行了一些基本组件的编写依赖,插件中开发功能需求时同时添加所需的基本组件,然后都独立开发自己的功能模块需求,在项目中添加了NativePlugin和RemotePlugin的插件工程,其中NativePlugin存放在本地assets文件中,RemotePlugin存放在服务器中,这两个插件分别在宿主工程中进行从本地拷贝到指定文件加载和从服务器下载到指定文件加载。

关于通信功能需求:

        本项目VirtualApkProgram中单个进程中(单个app内部)用的是EventBus消息传递机制,跨进程消息传递(多个app通信,eg:登录插件NativePlugin中登录后通知宿主和RemotePlugin插件修改登录状态) 采用的是广播机制进行的消息传递,跨进程存取操作数据采用ContentProvider方式 。

跨进程通信 可以采取Messenger,AIDL,ContentProvider,Socket的方式

 didi/VirtualAPK Demo中的宿主向插件中取数据采用ContentProvider方式

一、插件集成

1、项目的build.gradle添加依赖

buildscript { repositories { jcenter() } dependencies { classpath 'com.android.tools.build:gradle:2.3.3' classpath 'com.didi.virtualapk:gradle:0.9.4'

    // NOTE: Do not place your application dependencies here; they belong

    // in the individual module build.gradle files

}

}

2、宿主app中build.gradle添加依赖

头部添加:

apply plugin: 'com.didi.virtualapk.host'

在dependencies添加:

compile 'com.didi.virtualapk:core:0.9.5'

3、在在App的工程模块proguard-rules.pro文件添加混淆规则:

-keep class com.didi.virtualapk.internal.VAInstrumentation { *; }

-keep class com.didi.virtualapk.internal.PluginContentResolver { *; }

-dontwarn com.didi.virtualapk.**

-dontwarn android.**

-keep class android.** { *; }

4、初始化

在合适的地方添加: PluginManager.getInstance(context).init();

5、加载模块

//初始化插件管理器

PluginManager pluginManager = PluginManager.getInstance(context.getApplicationContext());

//获取插件APK的文件对象

File apk = getPluginFile(context, pluginId);

if (apk.exists()){ try { //加载插件 pluginManager.loadPlugin(apk); return true; } catch (Exception e) { e.printStackTrace(); } }

检测模块是否已经加载:

PluginManager pluginManager = PluginManager.getInstance(context.getApplicationContext());

//获取指定包名的插件对象

if (pluginManager.getLoadedPlugin(PackageName) != null){

return true; //已经加载

}

启动模块界面: if(isPluginLoaded(activity,pluginId)){ //模块是否加载,pluginId为model中设置的插件id

//代表模块加载成功 页面可赢正常跳转功能

try {

    Intent intent = new Intent();

    intent.setClassName(packageName, className);

    activity.startActivity(intent);

}catch (Exception e){

    e.printStackTrace();

    Log.e("sun", "startActivity: " +"启动插件失败");

}

return true;

}

二、插件工程接入

头部添加: apply plugin: 'com.didi.virtualapk.plugin' 添加依赖: //引入virtualAPK依赖 compile 'com.didi.virtualapk:core:0.9.5'

插件信息配置:

virtualApk {

//Attention:::packageId 范围 0x02 - 0x7E

packageId = 0x61            // 插件资源id,避免资源id冲突

targetHost ='app'            // 宿主工程的路径

applyHostMapping = true      // 插件编译时是否启用应用宿主的apply mapping

}

生成插件:

最后一步生成插件,需要使用Gradle命令(在Terminal中执行,或者在醒目目录中执行)

gradle clean assemblePlugin

三、运行插件

1、demo中的plugin是push到模拟器或者手机的指定目录中。(真实项目应该是从服务器下载)

2、运行宿主app,在指定位置启动model就可以了(参考:一、插件集成中的5步骤)

注意: 模块的文件名称和路径要和代码中保持一致

/**

通过插件id获取插件文件对象

@param context

@param pluginId

@return, 返回插件文件对象 */

public static File getPluginFile(Context context, int pluginId){

//定义插件apk的名称

String pluginApkName = getPluginName(pluginId);  //demo中做了简单封装,根据pluginId获model的包名

//定义插件文件对象

File file = new File(getExternalStorageDirectory(), pluginApkName);

Log.e("sun", "getPluginFile: " +  file.getAbsolutePath());

return file;

}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,045评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,114评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 147,120评论 0 332
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,902评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,828评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,132评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,590评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,258评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,408评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,335评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,385评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,068评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,660评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,747评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,967评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,406评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,970评论 2 341

推荐阅读更多精彩内容