一、现实需求描述
一般,一个应用开发到一定阶段,功能模块会越来越多,apk安装包也会越来越大,用户在使用过程中也没有办法选择性的加载自己需要的功能模块,此时就需要考虑如何分拆整个应用。
或者说,每个应用一开始不可能把所有的功能点都考虑到,都做得特别完善,而是根据用户反馈和需求来逐步完善,当有新的功能增加或更新时,不能让用户完全重新安装整个应用,这样很费用户的流量,用户体验不好,此时只需要把新增或更新的功能点添加到已装的原始应用中即可。
 
二、解决方案提出
1、将应用按功能模块分成不同的apk,当用户需要哪些功能,就去下载相应的apk,但是这样对于用户来说比较繁琐,用户体验很差。
2、应用发布之后,后面有扩展功能更新,可以通过插件来实现,使应用的功能得到扩展。但是插件没有自己的主窗体,而是依附在原应用的窗体上。
一般是用第二种方式。
 
三、实现方法描述
android插件的实现,一般是以apk形式来加载。需要考虑的方面:
1、主应用中需要开发的框架:
a、识别插件是否已经安装(可根据插件的package名)
b、如果已经安装插件需要判断是否需要升级(从服务器获取最新的版本号与本地版本号比较)
c、下载安装或升级插件              
d、卸载插件                                              
                                                                        
2、插件apk开发中需要注意的事项:               
插件apk的manifest文件中不要提供插件apk启动的入口
                                                                           
3、主应用和插件之间的交互:
一般使用android:sharedUserId属性,插件可以方便的获取主应用的资源、数据库等。主应用可以用Intent方式启动具体插件,同时带有map类型参数或Json串参数,在插件apk中解析具体参数,实现相关逻辑。
 
每个插件以单独的apk形式发布,这样可以在主程序中灵活知道是否有新的插件,提示用户下载。因为插件apk没有启动的入口launcher,所以插件apk清单描述Action为非Launcher,Category为Default。
 
四、一般开发流程
1、插件程序清单
同主程序的清单文件一样,sharedUserId必须有而且要和主程序的一样。
插件的activity意图过滤描述必须是这样的,如下:
<intent-filter>
         <category android:name=”android.intent.category.DEFAULT”/>
</intent-filter>
 
2、插件程序的功能
插件可以包含任意类,和一个普通的apk工程一样。
插件向主程序提供调用的类,也必须是个activity,其方法没有返回值,有且仅有一个Context参数,框架会反射这个方法,并将主程序的context句柄传入。
                                                                                                                           
3、插件程序的plugin.xml配置
plugin.xml不能改名,并且要放在工程的assets目录下。
plugin.xml的格式一般如下:
<?xml version=”1.0” encoding=”UTF-8”>
<plugin-features>
         <description name=”com.package.name.and.description.name”/>
 
         <feature name=”com.package.name.and.activity.name1”>
                   <method need-context=”true” name=”methodName1”>描述信息</method>
                   <method need-context=”true” name=”methodName2”>描述信息</method>
         </feature>
 
         <feature name=”com.package.name.and.activity.name2”>
                   <method need-context=”true” name=”methodName1”>描述信息</method>
         </feature>
</plugin-features>
 
4、查找插件
在主程序中,根据自身apk的sharedUserId属性值来查找系统中具有相同属性的包并加载。
相应的实现一般如下:
PluginSearch psearch = new PluginSearch();
List<Plugin> plugins = psearch.getPlugins(this);
PluginBuilder pbuilder = new PluginBuilder(this);
plugins = pbuilder.builderPluginDescrition(plugins);
 
5、调用插件           
一般主程序可以通过 插件调用类 来调用,如:
Plugin plug;
PluginFeature pf;
PluginFeatureMethod fm;
……                       
PluginInvoke pi = new PluginInvoke(MainActivityName.this);
pi.invoke(plug, pf, fm);
 

    总之,通过插件来扩展原始应用的功能,需要在开发应用的时候,尽量将应用的框架设计得完善一些,后续进行功能扩展,通过下载安装更新相应的插件的工作就会更顺利。