您的位置:首页 > 移动开发 > Android开发

Android插件化方案调研与实践

2016-06-13 10:31 183 查看
也是年代久远了,这个调研已经没什么实际意义了 :)Time:2014.6.20Author:Yeshen基本概念定义:通过和应用程序的互动,用来替应用程序增加一些所需要的特定的功能。主要原因是: 使得第三方的开发者可以对应用程序进行扩充、精简,或者将源代码从应用程序中分离出来,去除因软件使用权限而产生的不兼容。机制和原理:应用软件提供使插件能够应用的各项服务,其中包括提供加载方式,使插件可以加载到应用程序和网络传输协议中,从而和插件进行数据交换。插件必须依赖于应用程序才能发挥自身功能,仅靠插件是无法正常运行的。相反地,应用程序并不需要依赖插件就可以运行,这样一来,插件就可以加载到应用程序上并且动态更新而不会对应用程序造成任何改变。公开应用程序接口提供一个标准的界面,允许其他人编写插件和应用程序互动。一个稳定的应用程序接口会允许其他插件正常运行即使其最初的版本有所变动,也会支持插件延长老旧的应用程序的使用寿命。Adobe Photoshop和After Effects的插件应用程序接口逐渐成为标准,并且被一些和它们竞争的应用程序部分采纳。就好比一个网络转换器也许会运载一个未被占用但不标准的端口来容纳各种任选的物理层连接器。而游戏和某些应用程序经常使用插件的体系结构来允许最初的发行者和第三方发行者增加功能性。使用场景[align=justify]解耦,用户需要功能以插件方式给出,灵活定制[/align]开源方案调研:1、AAPhttp://code.google.com/p/android-application-plug-ins-frame-work/实现方式:主要通过Apk清单文件中的sharedUserId属性来把多个Apk融合为单一虚拟机,变相逾越了android不同Apk权限不同无法互通的鸿沟。插件向主程序提供调用的类必须是个activity,方法无返回值,有且只有一个Context参数,框架会反射这个方法,并将主程序的Context句柄传入。实现步骤:1、安装主程序、相应插件都要提前安装2、查找插件根据sharedUserId来查找系统中具有相同属性的包,并加载3、调用通过
PluginInvoke pi=
new
PluginInvoke(AndroidPluginFrameworkActivity.
this
);
//三个参数,第一个是Plugin类型,第二个是PluginFeature,第三个
PluginFeatureMethod
pi.invoke(plug, pf, fm);
2、动态加载https://github.com/singwhatiwanna/dynamic-load-apkhttps://github.com/mmin18/AndroidDynamicLoader ) 类加载机制:Dalvik虚拟机和其他java虚拟机一样,在运行程序时首先需要将对应的类加载到内存中。Android提供了几种加载方法:DexClassLoader: 可以加载文件系统上的jar、dex、apkPathClassLoader: 可以加载/data/app目录下的apk,这也意味着,它只能加载已经安装的apkURLClassLoader: 可以加载java中的jar,但是由于dalvik不能直接识别jar,所以此方法在android中无法使用,尽管还有这个类资源管理:Android中的资源在R文件中有定义了它的路径,使用DexClassLoader加载后,因为不能获取原Apk包中的R文件,所以如果不经过处理,只能使用代码写页面逻辑,或者把插件的资源在主程序下也存放一份。我们知道,activity的工作主要是由ContextImpl来完成的, 它在activity中是一个叫做mBase的成员变量。注意到Context中有如下两个抽象方法,看起来是和资源有关的,实际上context就是通 过它们来获取资源的,这两个抽象方法的真正实现在ContextImpl中。也即是说,只要我们自己实现这两个方法,就可以解决资源问题了。    /** Return an AssetManager instance for your application's package. */    public abstract AssetManager getAssets();    /** Return a Resources instance for your application's package. */    public abstract Resources getResources(); 加载的方法是通过反射,通过调用AssetManager中的addAssetPath方法,我们可以将一个apk中的资源加载到Resources中, 由于addAssetPath是隐藏api我们无法直接调用,所以只能通过反射,传递的路径可以是zip文件也可 以是一个资源目录,而apk就是一个zip,所以直接将apk的路径传给它,资源就加载到AssetManager中了,然后再通过 AssetManager来创建一个新的Resources对象,这个对象就是我们可以使用的apk中的资源了,这样我们的问题就解决了。Activity生命周期管理系统在启动activity之前做了很多初始化工作,而我们在应用层通过反射去启动activity是很难完成系统所做的初始化工作的,所以activity的大部分特性都无法使用包括activity的生 命周期管理,这就需要我们自己去管理。谈到activity生命周期,其实就是那几个常见的方法:onCreate、onStart、onResume、 onPause等,由于apk中的activity不是真正意义上的activity(没有在宿主程序中注册且没有完全初始化),所以这几个生命周期的方 法系统就不会去自动调用了。针对此类问题,采用Fragment是一个不错的方法,Fragment从3.0引入,通过support-v4包,可以兼容3.0以下的android版本。Fragment既有类似于Activity的生命周期,又有类似于View的界面,将Fragment加入到 Activity中,activity会自动管理Fragment的生命周期。FragmentFragment在是一个模块化和可重用的组件,因为fragment定义了自己的布局,以及通过使用它的生命周期回调方法定义它自己的行为,Fragment类和Activity类很像它包涵了activity类似的回调方法,例如 onCreate()、 onStart()、onPause()以及 onStop()。事实上, 如果你准备将一个现成的Android应用转换到使用fragment,可能只需简单的将代码从你的activity的回调方法分别移动到你的 fragment的回调方法即可。具体实现方法: 首先宿主程序会到文件系统比如sd卡去加载apk,然后通过一个叫做proxy的activity去执行插件中的activity,插件中的Activity继承自BaseActivity,通过BaseActivity做生命周期管理。3、OSGI方案https://github.com/zstorok/android-osgi-demo)该规范和核心部分是一个框架 ,其中定义了应用程序的生命周期模式和服务注册。基于这个框架定义了大量的OSGi服务:日志、配置管理、偏好,HTTP(运行servlet)、XML分析、设备访问、软件包管理、许可管理、星级、用户管理、IO连接、连线管理、JiniUPnP。这个框架实现了一个优雅、完整和动态的组件模型。应用程序(称为bundle)无需重新引导可以被远程安装、启动、升级和卸载(其中Java包/类的管理被详细定义)。API中还定义了运行远程下载管理政策的生命周期管理服务注册允许bundles去检测新服务和取消的服务,然后相应配合。这个方案主要的工作就是将OSGI现有框架从java中移植到Android中。目前有公司把这个框架提取出来,做成项目。4、分析AAP方案是我最先找的,也是最新放弃的,原因是:1、用户需要提前安装插件,把这个问题复杂化了 2、主程序卸载了,插件不会自动卸载,会遗留垃圾 3、activity采用反射的方法需要考虑很多问题,例如activity的生命周期问题、垃圾回收问题,而在demo代码中,这方面的处理不够动态加载给出的两个链接是两个开源项目,放在一起必然是因为很类似。第一个项目(后称A)的原理介绍很充足,代码简洁高效,基本上实现了插件化需要完成的工作,但是很有一些问题要优化处理;第二个方案(后称B)高度封装,重写了 DexClassLoader等文件,选用了Fragment作为插件页面显示,自定义了intent,但插件代码和主程序代码耦合程度很高,在改项目中直接把主程序提取出jar包,作为插件程序的库文件。我是边理解代码边调试,理解了A项目,通过调试了确定A项目满足我们的基本需求,所以我在A项目上做了补充完善,提取了框架,修改了apk文件存放目录。但是还有不少优化项,这部分的工作留在下一节进行分析。OSGI方案这个方案是三个方案里面最复杂的,我读了一部分代码,下了demo来看,看了两天还是云里雾里的。网上去找博客关于OSGI android的,发现有些基础的方法和动态加载有点像,例如用了类加载机制。也下了一个PPT专门介绍OSGI移植到android的,涉及到很底层的东西,不过啃完还是感觉不好实现。总的来说,这几种方案都涉及到插件化的东西,从满足我们的需求,以及实施的容易程度而言,我推荐动态加载方案。目前已经初步做了一个demo
                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android