动态加载和调用程序的方法及装置\n技术领域\n[0001] 本发明涉及插件处理技术领域,具体涉及一种动态加载和调用程序的方法及装置。\n背景技术\n[0002] 类加载器(class loader)是JavaTM中的一个很重要的概念。类加载器负责加载Java类的字节代码到Java虚拟机(Virtual Machine)中。同时,类加载器是Java语言的一个创新,也是Java语言流行的重要原因之一。它使得Java类可以被动态加载到Java虚拟机中并执行。类加载器从JDK1.0就出现了,最初是为了满足在Web容器和OSGI中得到了广泛的使用。\n[0003] Java虚拟机使用Java类的方式如下:Java源程序(.java文件)在经过Java编译器编译之后被转换成Java字节代码(.class文件)。类加载器负责读取Java字节代码,并转换成java.lang.Class类的一个实例。每个这样的实例用来表示一个Java类。通过此实例的newInstance()方法就可以创建出该类的一个对象。\n[0004] Java中的类加载器大致分为两类,一类是系统提供的,另一类是由Java应用开发人员编写的。系统提供的类加载器主要有下面三个:\n[0005] 引导加载器(Bootstrap class loader):用来加载Java核心库,它是由原生代码来实现的,并不继承于Java.lang.ClassLoader。\n[0006] 扩展加载器(Extensions class loader):用来加载Java扩展库。Java VM的实现会提供一个扩展库目录。该类加载器在此目录中查找并加载相关的Java类。\n[0007] 系统加载器(System class loader):根据设定的环境变量来加载Java类。Java应用的类都是由它完成加载的。\n[0008] 除了系统提供的类加载器以外,开发人员可以通过继承java.lang.ClassLoader类的方式实现自己的类加载器,以满足特殊的需求。\n[0009] 以在智能手机的安卓(Android)平台上加载APK(Android Package)格式的程序包为例。在加载APK之前,系统必须先安装APK,具体安装过程包括:首先要把该APK下载到本地,然后调用系统安装程序,用户逐步确认后系统复制该APK安装包到data/app目录下,解压并扫描安装包,把dex文件(Dalvik字节码)保存到dalvik-cache目录下,并在data/data目录下创建对应的应用数据目录。上述安装APK的步骤繁琐复杂,用户需要反复点击和确认后才能实现APK的加载,不利于APK的推广。\n发明内容\n[0010] 鉴于上述问题,提出了本发明以便提供一种克服上述问题或者至少部分地解决上述问题的动态加载和调用程序的方法和相应的动态加载和调用程序的装置。\n[0011] 根据本发明的一个方面,提供了一种动态加载和调用程序的方法,其包括:由主系统发起对调用程序的调用请求;所述调用程序加载被调用程序生成相关句柄及文件,并得到所述调用程序的实例;所述调用程序将所述调用程序的实例赋值给所述被调用程序的实例;由所述调用程序发起对所述被调用程序的调用请求;由所述主系统根据程序的生命周期调用所述调用程序对应的方法,由所述调用程序根据程序的生命周期调用所述被调用程序对应的方法。\n[0012] 根据本发明的另一方面,提供了一种动态加载和调用程序的装置,其包括:主系统、调用程序运行模块以及被调用程序运行模块;其中,所述主系统包括:第一调用请求发起单元和第一调用单元;所述调用程序运行模块包括:加载单元、赋值单元、第二调用请求发起单元以及第二调用单元;\n[0013] 所述第一调用请求发起单元适于发起对调用程序的调用请求;所述加载单元适于加载被调用程序生成相关句柄及文件,并得到所述调用程序的实例;所述赋值单元适于将所述调用程序的实例赋值给所述被调用程序的实例;所述第二调用请求发起单元适于发起对所述被调用程序的调用请求;所述第一调用单元适于根据程序的生命周期调用所述调用程序对应的方法;所述第二调用单元适于根据程序的生命周期调用所述被调用程序对应的方法。\n[0014] 根据本发明提供的动态加载和调用程序的方法及装置,主系统利用调用程序作为媒介实现对被调用程序的加载和调用,具体地,在主系统发起对调用程序的调用请求之后,调用程序加载被调用程序;在加载过程中,将调用程序的实例赋值给被调用程序的实例;之后调用程序能够发起对被调用程序的调用请求;进而通过主系统调用调用程序对应的方法,调用程序调用被调用程序对应的方法,实现了被调用程序的加载和调用。利用本发明提供的方案,跳过上述繁琐复杂的安装步骤,只需下载程序包即可加载和调用。\n[0015] 上述说明仅是本发明技术方案的概述,为了能够更清楚了解本发明的技术手段,而可依照说明书的内容予以实施,并且为了让本发明的上述和其它目的、特征和优点能够更明显易懂,以下特举本发明的具体实施方式。\n附图说明\n[0016] 通过阅读下文优选实施方式的详细描述,各种其他的优点和益处对于本领域普通技术人员将变得清楚明了。附图仅用于示出优选实施方式的目的,而并不认为是对本发明的限制。而且在整个附图中,用相同的参考符号表示相同的部件。在附图中:\n[0017] 图1示出了根据本发明一个实施例的动态加载和调用程序的方法的流程图;\n[0018] 图2示出了本发明实施例一个应用场景的方法流程图;\n[0019] 图3示出了本发明实施例的调用程序的抽象父类的定义示意图;\n[0020] 图4示出了本发明实施例的APK包(插件)的抽象父类的定义示意图;\n[0021] 图5示出了本发明实施例中调用程序以插件形式调用APK包的生命周期时序图;\n[0022] 图6示出了本发明实施例中调用程序以插件形式调用APK资源加载时序图;\n[0023] 图7示出了根据本发明一个实施例的动态加载和调用程序的装置的结构框图。\n具体实施方式\n[0024] 下面将参照附图更详细地描述本公开的示例性实施例。虽然附图中显示了本公开的示例性实施例,然而应当理解,可以以各种形式实现本公开而不应被这里阐述的实施例所限制。相反,提供这些实施例是为了能够更透彻地理解本公开,并且能够将本公开的范围完整的传达给本领域的技术人员。\n[0025] 为了解决现有技术中在加载和调用程序包之前必须先安装程序包的技术问题,本发明提供了一种动态加载和调用程序的方法,跳过上述繁琐复杂的安装步骤,通过相应的机制只需下载程序包即可加载和调用。图1示出了根据本发明一个实施例的动态加载和调用程序的方法的流程图。如图1所示,本实施例包括如下步骤:\n[0026] 步骤S101,由主系统发起对调用程序的调用请求。\n[0027] 其中,主系统指的是系统平台,例如手机平台;调用程序可以为已安装的用于调用插件的应用,例如手机卫士等软件都可以作为调用程序。由于调用程序为已安装的应用,所以在主系统的Manifest.xml中已经注册过,因此主系统可以先发起对调用程序的调用请求。\n[0028] 步骤S102,调用程序加载被调用程序生成相关句柄及文件,并得到调用程序的实例。\n[0029] 调用程序使用Java中的类加载器加载被调用程序,在加载过程中会在相应的目录下生成句柄及文件,并得到加载后的对象以及调用程序的实例。\n[0030] 步骤S103,调用程序将调用程序的实例赋值给被调用程序的实例。\n[0031] 调用程序将上述调用程序的实例赋值给被调用程序的实例,以调用者的实例作为被调用者的实例。\n[0032] 步骤S104,由调用程序发起对被调用程序的调用请求。\n[0033] 在将调用程序的实例赋值给被调用程序的实例之后,调用程序通过invoke方法发起对被调用程序的调用请求。\n[0034] 步骤S105,由主系统根据程序的生命周期调用调用程序对应的方法,由调用程序根据程序的生命周期调用被调用程序对应的方法。\n[0035] 根据本实施例提供的动态加载和调用程序的方法,主系统利用调用程序作为媒介实现对被调用程序的加载和调用,具体地,在主系统发起对调用程序的调用请求之后,调用程序加载被调用程序;在加载过程中,将调用程序的实例赋值给被调用程序的实例;之后调用程序能够发起对被调用程序的调用请求;进而通过主系统调用调用程序对应的方法,调用程序调用被调用程序对应的方法,实现了被调用程序的加载和调用。利用本实施例提供的方法,跳过上述繁琐复杂的安装步骤,只需下载程序包即可加载和调用。\n[0036] 下面以本发明提供的方法应用于智能手机的安卓平台上加载和调用APK程序包的场景为例,进一步的详述本发明的技术方案。在以下实施例中,被调用程序为未安装的APK包,也可称为APK插件。\n[0037] 图2示出了本发明实施例一个应用场景的方法流程图。该应用场景是在Android平台上通过对系统运行过程的模拟和优化,实现动态加载APK包及其所有逻辑和资源,动态调用该APK包中的组件(Activity)和服务(Services)等,如此便可实现Android平台的插件化编程。\n[0038] 如图2所示,该方法包括步骤:\n[0039] 步骤S201,启动软件,该软件为用于调用插件的调用程序,例如手机卫士等软件。\n[0040] 步骤S202,收集Android系统平台的信息,包括Android的版本、终端厂商信息、终端型号等。\n[0041] 由于Android系统的开放性,各家终端厂商所使用的系统基本都经过了二次开发,使得市场上的Android终端比较繁杂,收集这些信息的意义在于能够准确地获取与其适配的APK包。\n[0042] 步骤S203,在收集完相关信息后,将这些信息传至云端服务器,由云端服务器返回适配结果。\n[0043] 这样做的目的是为了使适配规则更加准确、灵活。在云端服务器返回的适配结果集里面会包含APK包的URL地址。\n[0044] 步骤S204,根据APK包的URL地址下载APK包。\n[0045] 步骤S205,对下载得到的APK包进行合法性鉴权。\n[0046] 为了避免APK包被非法篡改,或者在网络传输过程中数据出错,需要对APK包进行合法性鉴权。具体步骤包括:提取APK包的包信息(PackageInfo);根据PackageInfo获取签名(Signature)对象;取得Signature的MD5值;比较其MD5值与合法签名是否一致,如一致,则鉴权通过,继续下面步骤;如不一致,则鉴权错误,返回错误信息,停止加载。\n[0047] 步骤S206,动态加载和调用APK包。\n[0048] 为了方便调用APK包提供的功能,规避过多的使用反射机制,本发明将调用APK包提供的功能抽象为两个抽象父类。其中调用程序的抽象父类为CallPluginActivity,APK包的抽象父类为PluginActivity。CallPluginActivity和PluginActivity均为抽象类,需要子类实现其相应的方法,因此本文后续描述的CallPluginActivity均也代表CallPluginActivity的实现类,PluginActivity均也代表PluginActivity的实现类,后面将不再赘述。\n[0049] 本实施例中,调用程序为已经安装的用于调用插件的应用。APK包(插件)为已经下载,可以作为插件调用,也可以和普通APK一样正常安装的Android应用。\n[0050] 调用程序的抽象父类CallPluginActivity主要是为了向APK包(插件)中的PluginActivity提供实例,即上下文Context,并完成APK包的合法性鉴权和通过反射机制加载APK包(插件)。在本发明实施例的一个例子中,调用程序的抽象父类的定义如图3所示。\n其中,onCreate()方法由Android系统调用,用于发起对调用程序的调用请求。checkApk()方法用于对APK包进行合法性鉴权。LoadAPK()方法用于判断是否需要加载APK并生成DexClassLoader和PackageInfo等句柄及文件,并通过反射方法得到对应的PluginActivity实例(变量名为:pluginActivity)。getOtherResources()方法用于通过反射方法加载APK包的资源并生成Resources句柄(变量名为:pluginRes)。为了实现对应的功能,需要在子类中重写父类定义的如下方法:\n[0051] 重写以下方法替换当前CallPluginActivity的资源、样式为APK包中的资源、样式:\n[0052]\n[0053]\n[0054] //判断pluginActivity及pluginRes是否成功加载,若成功加载返回APK包的Resources资源;否则以系统默认方式加载Resources资源;\n[0055] ●+getResources():Resources//返回一个资源句柄(android.content.res.Resources)\n[0056] ●+getTheme():Theme//返回一个样式句柄(android.content.res.Resources.Theme)\n[0057] ●+getAssets():AssetManager//返回一个样式句柄(android.content.res.AssetManager)\n[0058] 本文中代码后“//…”的内容是代码的注释内容。\n[0059] 重写以下方法便于反射调用APK包(插件)中的PluginActivity、PluginService等组件:\n[0060] ●+startActivity(Intent):void//启动一个Activity,当Activity关闭时,不返回任何信息\n[0061] ●+startActivityForResult(Intent,int):void//启动一个Activity,当Activity关闭时,会有一个返回值\n[0062] ●+onActivityResult(int,int,Intent):void//当以startActivityForResult函数启动的Activity完成时,会有一个Intent作为返回值\n[0063] ●+startService(Intent):void//启动一个服务(android.app.Service)[0064] 重写以下方法使APK包(插件)中的PluginActivity的生命周期与调用程序CallPluginActivity的生命周期一致,如onStart、onResume方法,其他方法以此类推。\n[0065] 重写父类onResume方法,调用invoke方法。\n[0066]\n[0067] //invokeMethod方法:根据方法名称参数(String methodName)通过反射方式调用pluginActivity中对应的名称的方法\n[0068] z+onRestoreInstanceState(Bundle):void//当Activity之前被销毁再被重建时,可以从Bundle参数中恢复保存的状态\n[0069] z+onStart():void\n[0070] z+onRestart():void//当Activity从停止状态返回到前台时,收到一个onRestart()的调用,系统还会调用onStart()方法,该方法在Activity变得可见时都会发生(不管是被重启还是第一次被创建)\n[0071] z+onResume():void//每次Activity进入前台时,系统都会调用该方法,包括第一次创建时\n[0072] z+onSaveInstanceState(Bundle):void//当Activity要停止时,系统调用该方法,Activity可以用一个键-值对集合保存状态信息\n[0073] z+onPause():void//当系统调用onPause()时,在技术上意味着Activity仍是部分可见的,而其他情况下意味着用户正在离开Activity,并且将到达关闭(Stopped)状态[0074] z+onStop():void//当Activity收到onStop()方法的调用时,该Activity将不再可见,并且释放不需要的资源\n[0075] z+onDestroy():void//Activity的第一个生命周期回调函数是onCreate(),而它的最后一个回调函数是onDestroy();系统调用该方法作为一个最终信号,表明Activity实例将要被完全从系统内存中清除\n[0076] APK包(插件)的抽象父类的主要功能是完成APK包(插件)的构建和提供符合Android标准的Activity和Service等。在本发明实施例的一个例子中,APK包(插件)的抽象父类的定义如图4所示。其中,onCreate()方法由调用程序调用,用于发起对APK包(插件)的调用请求。setCallActivity()由调用程序反射调用并设置自身的实例(pluginActivity)为APK包(插件)的实例(baseActivity)。具体实现方法如下:\n[0077]\n[0078] }//由调用程序反射调用并设置自身实例为被调用程序的baseActivity变量[0079] 为了实现APK包(插件)子类对应的功能,需要在子类中重写父类定义的如下方法。\n[0080] 重写以下方法使APK包(插件)中的PluginActivity的生命周期受调用程序CallPluginActivity的生命周期控制,如:onStart、onResume方法,其他方法以此类推;以baseActivity变量是否为空来判断PluginActivity是由调用程序以插件形式启动,还是以Android正常启动(非插件调用的方式):\n[0081]\n[0082] //判断baseActivity是否为空,若不为空则是插件形式调用;否则为调用系统默认方法\n[0083] +onCreate(Bundle):void\n[0084] +onRestoreInstanceState(Bundle):void\n[0085] +onStart():void\n[0086] +onRestart():void\n[0087] +onResume():void\n[0088] +onSaveInstanceState(Bundle):void\n[0089] +onPause():void\n[0090] +onStop():void\n[0091] +onDestroy():void\n[0092] 关于以上方法的注释参见前文的描述。其中,在onCreate()方法里,可以执行基本的应用程序启动逻辑(这些逻辑只在Activity的整个生命活动中发生一次)。\n[0093] 以baseActivity变量是否为空来判断PluginActivity是否由调用程序以插件形式调用,如果是插件形式,则调用baseActivity对应方法,正常启动的话调用其父类对应方法,其他方法以此类推:\n[0094]\n[0095]\n[0096] //判断baseActivity是否为空,若不为空则加载调用程序资源,否则调用加载资源\n[0097] +getResources():Resources\n[0098] +getTheme():Theme\n[0099] +getAssets():AssetManager\n[0100] +startActivity(Intent):void\n[0101] +startActivityForResult(Intent, int):void\n[0102] +startService(Intent):void\n[0103] +onActivityResult(int, int, Intent):void\n[0104] 关于以上方法的注释参见前文的描述。\n[0105] 总而言之,调用程序与APK包(插件)之间调用的总策略为:\n[0106] CallPluginActivity通过判断pluginActivity是否为空来确定是否成功加载APK包(插件)及其资源;如果判断出pluginActivity不为空,则确定成功加载APK包(插件)及其资源,并实例化对应的Activity。\n[0107] PluginActivity通过判断baseActivity是否为空来确定本Activity是否由调用程序以插件的形式调用;如果判断出baseActivity不为空,则确定本Activity是由调用程序以插件的形式调用。\n[0108] 图5示出了本发明实施例中调用程序以插件形式调用APK包的生命周期时序图。如图5所示,主要包括如下步骤:\n[0109] 步骤S501,由Android系统调用CallPluginActivity的onCreate()方法,即Android系统发起对CallPluginActivity的调用请求。\n[0110] 步骤S502,CallPluginActivity执行checkApk()方法,对APK包(插件)进行合法性鉴权。有关合法性鉴权的具体步骤可参见上述实施例的描述。\n[0111] 步骤S503,CallPluginActivity执行LoadAPK()方法判断是否需要加载APK包(插件)并生成DexClassLoader和PackageInfo等句柄及文件,并通过反射方法得到对应的PluginActivity实例(变量名为:pluginActivity)。\n[0112] 步骤S504,CallPluginActivity反射调用PluginActivity的setCallActivity方法,设置自身实例到PluginActivity中(变量名为:baseActivity),利用CallPluginActivity自身的上下文Context充当PluginActivity的上下文Context。\n[0113] 步骤S505,CallPluginActivity通过invoke方法反射调用PluginActivity的onCreate()方法,即CallPluginActivity发起对PluginActivity的调用请求。\n[0114] 步骤S506,由Android系统根据Activity生命周期调用CallPluginActivity对应的方法,方法如下:\n[0115] +onRestoreInstanceState(Bundle):void\n[0116] +onStart():void\n[0117] +onRestart():void\n[0118] +onResume():void\n[0119] +onSaveInstanceState(Bundle):void\n[0120] +onPause():void\n[0121] +onStop():void\n[0122] +onDestroy():void\n[0123] 关于以上方法的注释参见前文的描述。\n[0124] 步骤S507,由CallPluginActivity根据Activity生命周期通过invoke方法反射调用PluginActivity对应的方法,方法同步骤S506。\n[0125] 图6示出了本发明实施例中调用程序以插件形式调用APK资源加载时序图。如图6所示,主要包括如下步骤:\n[0126] 步骤S601,由主系统根据程序的生命周期或者调用程序自身调用调用程序中的资源加载方法,加载调用程序或被调用程序的资源。具体地,由Android系统根据Activity生命周期或者CallPluginActivity自身调用getResources、getTheme、getAssets等资源加载方法,加载调用程序或APK包(插件)资源。\n[0127] 步骤S602,由调用程序根据程序的生命周期调用被调用程序中的资源加载方法,加载被调用程序的资源。具体地,由CallPluginActivity根据Activity生命周期通过invoke方法反射调用PluginActivity的getResources、getTheme、getAssets等资源加载方法,加载APK包(插件)资源。\n[0128] 另外,调用程序还可以以插件形式调用APK包(插件)内部PluginActivity,其时序主要包括:\n[0129] 首先,由主系统通过调用程序反射调用被调用程序中的组件和服务对应的方法。\n具体地,由Android系统通过CallPluginActivity反射调用APK包(插件)中的Activity和Service对应的方法,常用方法有:startActivity、startActivityForResult、startService、onActivityResult等。\n[0130] 然后,由主系统调用调用程序中的除了上述组件和服务以外的其他组件和服务对应的方法。具体地,由Android系统直接调用CallPluginActivity中的除了APK包(插件)中的Activity和Service以外的其他Activity和Service对应的方法,常用方法与上个步骤相同。\n[0131] 最后,由调用程序调用调用程序和被调用程序中均不存在的组件和服务对应的方法。具体地,由CallPluginActivity调用调用程序和APK包(插件)中均不存在的Activity和Service对应的方法,常用方法与上个步骤相同。\n[0132] 另外,本发明实施例还提供了如下常用事件监听接口,该接口主要用于Android的系统事件的传递,例如电量、信号、网络监听等。\n[0133]
[0134] //监听网络连接状态变化的接口\n[0135]
[0136] //监听充电状态或者电池电量变化的接口\n[0137]
[0138] //监听屏幕被关闭的接口\n[0139]
[0140] //监听屏幕被打开的接口\n[0141]
\n[0142] //监听电话的信号强度变化的接口\n[0143]
[0144] //监听电话服务的状态变化的接口\n[0145] 根据上述实施例提供的方法,实现了在Android平台上动态加载和调用APK包(插件)及其所有逻辑和资源,动态调用该APK中的Activity和Service,进而实现了Android平台的插件化编程。与现有的动态加载jar包的方案相比,本发明至少具有优点:\n[0146] 1.将jar文件改为APK文件,简化了签名流程;\n[0147] 2.Activity的生命周期由调用程序负责;\n[0148] 3.通过本发明提供的方法可以调用APK中的Activity的所有布局、图片、样式等资源文件,以及该Activity的自身的所有逻辑;\n[0149] 4.本发明跳过了繁琐复杂的安装步骤,无需安装只需下载APK即可完成加载和调用;\n[0150] 5.本发明中,APK即是插件又是独立的APK,可以单独安装使用,提升了便利性;\n[0151] 6.通常情况下,Android程序为了兼容大多数系统版本,如:Android2.2、Android4.0.3、Android4.1、Android4.2等,一般都会使用较低版本的SDK,如:SDK Api Level8即Android2.2,这样的程序在Android4.XX系统中不能充分发挥高版本Android系统的特性,而本发明提供的动态加载APK包(插件)的方法可以根据Android系统版本加载相应的插件,充分发挥系统特性。\n[0152] 图7示出了根据本发明一个实施例的动态加载和调用程序的装置的结构框图。如图7所示,该装置包括:主系统700、调用程序运行模块710以及被调用程序运行模块720。其中,主系统700包括第一调用请求发起单元701和第一调用单元702;调用程序运行模块710包括:加载单元711、赋值单元712、第二调用请求发起单元713以及第二调用单元714。主系统700指的是系统平台,例如手机平台;调用程序运行模块710可以为已安装的用于调用插件的应用,例如手机卫士等软件;被调用程序运行模块720可以为未安装的APK插件。\n[0153] 第一调用请求发起单元701适于发起对调用程序的调用请求。由于调用程序在主系统的Manifest.xml中已经注册过,因此主系统可以先发起对调用程序的调用请求。\n[0154] 加载单元711适于加载被调用程序生成相关句柄及文件,并得到调用程序的实例。\n[0155] 赋值单元712适于将调用程序的实例赋值给被调用程序的实例。\n[0156] 第二调用请求发起单元713适于发起对被调用程序的调用请求。\n[0157] 第一调用单元702适于根据程序的生命周期调用调用程序对应的方法[0158] 第二调用单元714适于根据程序的生命周期调用被调用程序对应的方法。\n[0159] 可选地,调用程序运行模块710还包括:鉴权单元715,适于对被调用程序进行合法性鉴权。\n[0160] 在上述Android系统平台上动态加载和调用APK包(插件)的应用场景中,主系统\n700为Android系统,第一调用请求发起单元701通过调用CallPluginActivity的onCreate()方法发起对CallPluginActivity的调用请求。鉴权单元715执行checkApk()方法,对APK包(插件)进行合法性鉴权。加载单元711执行LoadAPK()方法判断是否需要加载APK包(插件)并生成DexClassLoader和PackageInfo等句柄及文件,并通过反射方法得到对应的PluginActivity实例(变量名为:pluginActivity)。赋值单元712反射调用PluginActivity的setCallActivity方法,设置自身实例到PluginActivity中(变量名为:baseActivity),利用CallPluginActivity自身的上下文Context充当PluginActivity的上下文Context。第二调用请求发起单元713通过反射调用PluginActivity的onCreate()方法发起对被调用程序的调用请求。第一调用单元702根据Activity生命周期调用CallPluginActivity对应的方法;第二调用单元714根据Activity生命周期通过invoke方法反射调用PluginActivity对应的方法。\n[0161] 其中,调用程序运行模块710适于通过判断调用程序的实例不为空来确定成功加载被调用程序。被调用程序运行模块720适于通过判断被调用程序的实例不为空来确定被调用程序以插件的形式被调用。\n[0162] 为了能够使调用程序以插件形式调用APK资源,第一调用单元702进一步适于根据程序的生命周期调用调用程序中的资源加载方法,加载调用程序或被调用程序的资源。具体地,第一调用单元702根据Activity生命周期调用getResources、getTheme、getAssets等资源加载方法,加载调用程序或APK包(插件)资源。第二调用单元714进一步适于根据程序的生命周期调用被调用程序中的资源加载方法,加载被调用程序的资源。具体地,第二调用单元714根据Activity生命周期通过invoke方法反射调用PluginActivity的getResources、getTheme、getAssets等资源加载方法,加载APK包(插件)资源。\n[0163] 为了能够使调用程序以插件形式调用APK包(插件)内部PluginActivity,第一调用单元702进一步适于:通过第二调用单元714反射调用被调用程序中的组件和服务对应的方法;以及调用调用程序中的除了上述组件和服务以外的其他组件和服务对应的方法。具体地,第一调用单元702通过第二调用单元714反射调用APK包(插件)中的Activity和Service对应的方法,常用方法有:startActivity、startActivityForResult、startService、onActivityResult等。第一调用单元702直接调用CallPluginActivity中的除了APK包(插件)中的Activity和Service以外的其他Activity和Service对应的方法,常用方法与上述相同。第二调用单元714进一步适于调用调用程序和被调用程序中均不存在的组件和服务对应的方法。具体地,第二调用单元714调用调用程序和APK包(插件)中均不存在的Activity和Service对应的方法,常用方法与上述相同。\n[0164] 根据本实施例提供的动态加载和调用程序的装置,主系统利用调用程序作为媒介实现对被调用程序的加载和调用,具体地,在第一调用请求发起单元发起对调用程序的调用请求之后,加载单元加载被调用程序;在加载过程中,赋值单元将调用程序的实例赋值给被调用程序的实例;之后第二调用请求发起单元发起对被调用程序的调用请求;通过第一调用单元调用调用程序对应的方法,第二调用单元调用被调用程序对应的方法,实现了被调用程序的加载和调用。利用本实施例提供的装置,在加载和调用程序时跳过上述繁琐复杂的安装步骤,只需下载程序包即可实现加载和调用。\n[0165] 在Android系统平台上动态加载和调用APK包(插件)的应用场景中,通过本发明提供的装置可以调用APK中的Activity的所有布局、图片、样式等资源文件,以及该Activity的自身的所有逻辑;APK即是插件又是独立的APK,可以单独安装使用,提升了便利性;本发明提供的动态加载APK包(插件)的装置可以根据Android系统版本加载相应的插件,充分发挥系统特性。\n[0166] 在此提供的算法和显示不与任何特定计算机、虚拟系统或者其它设备固有相关。\n各种通用系统也可以与基于在此的示教一起使用。根据上面的描述,构造这类系统所要求的结构是显而易见的。此外,本发明也不针对任何特定编程语言。应当明白,可以利用各种编程语言实现在此描述的本发明的内容,并且上面对特定语言所做的描述是为了披露本发明的最佳实施方式。\n[0167] 在此处所提供的说明书中,说明了大量具体细节。然而,能够理解,本发明的实施例可以在没有这些具体细节的情况下实践。在一些实例中,并未详细示出公知的方法、结构和技术,以便不模糊对本说明书的理解。\n[0168] 类似地,应当理解,为了精简本公开并帮助理解各个发明方面中的一个或多个,在上面对本发明的示例性实施例的描述中,本发明的各个特征有时被一起分组到单个实施例、图、或者对其的描述中。然而,并不应将该公开的方法解释成反映如下意图:即所要求保护的本发明要求比在每个权利要求中所明确记载的特征更多的特征。更确切地说,如下面的权利要求书所反映的那样,发明方面在于少于前面公开的单个实施例的所有特征。因此,遵循具体实施方式的权利要求书由此明确地并入该具体实施方式,其中每个权利要求本身都作为本发明的单独实施例。\n[0169] 本领域那些技术人员可以理解,可以对实施例中的设备中的模块进行自适应性地改变并且把它们设置在与该实施例不同的一个或多个设备中。可以把实施例中的模块或单元或组件组合成一个模块或单元或组件,以及此外可以把它们分成多个子模块或子单元或子组件。除了这样的特征和/或过程或者单元中的至少一些是相互排斥之外,可以采用任何组合对本说明书(包括伴随的权利要求、摘要和附图)中公开的所有特征以及如此公开的任何方法或者设备的所有过程或单元进行组合。除非另外明确陈述,本说明书(包括伴随的权利要求、摘要和附图)中公开的每个特征可以由提供相同、等同或相似目的的替代特征来代替。\n[0170] 此外,本领域的技术人员能够理解,尽管在此所述的一些实施例包括其它实施例中所包括的某些特征而不是其它特征,但是不同实施例的特征的组合意味着处于本发明的范围之内并且形成不同的实施例。例如,在下面的权利要求书中,所要求保护的实施例的任意之一都可以以任意的组合方式来使用。\n[0171] 本发明的各个部件实施例可以以硬件实现,或者以在一个或者多个处理器上运行的软件模块实现,或者以它们的组合实现。本领域的技术人员应当理解,可以在实践中使用微处理器或者数字信号处理器(DSP)来实现根据本发明实施例的动态加载和调用程序的装置中的一些或者全部部件的一些或者全部功能。本发明还可以实现为用于执行这里所描述的方法的一部分或者全部的设备或者装置程序(例如,计算机程序和计算机程序产品)。这样的实现本发明的程序可以存储在计算机可读介质上,或者可以具有一个或者多个信号的形式。这样的信号可以从因特网网站上下载得到,或者在载体信号上提供,或者以任何其他形式提供。\n[0172] 应该注意的是上述实施例对本发明进行说明而不是对本发明进行限制,并且本领域技术人员在不脱离所附权利要求的范围的情况下可设计出替换实施例。在权利要求中,不应将位于括号之间的任何参考符号构造成对权利要求的限制。单词“包含”不排除存在未列在权利要求中的元件或步骤。位于元件之前的单词“一”或“一个”不排除存在多个这样的元件。本发明可以借助于包括有若干不同元件的硬件以及借助于适当编程的计算机来实现。在列举了若干装置的单元权利要求中,这些装置中的若干个可以是通过同一个硬件项来具体体现。单词第一、第二、以及第三等的使用不表示任何顺序。可将这些单词解释为名称。\n[0173] 本发明公开:A1、一种动态加载和调用程序的方法,其包括:由主系统发起对调用程序的调用请求;所述调用程序加载被调用程序生成相关句柄及文件,并得到所述调用程序的实例;所述调用程序将所述调用程序的实例赋值给所述被调用程序的实例;由所述调用程序发起对所述被调用程序的调用请求;由所述主系统根据程序的生命周期调用所述调用程序对应的方法,由所述调用程序根据程序的生命周期调用所述被调用程序对应的方法。A2、根据A1所述的方法,其中,所述调用程序为已安装的用于调用插件的应用,所述被调用程序为未安装的APK插件。A3、根据A1或A2所述的方法,其中,所述调用程序通过判断所述调用程序的实例不为空来确定成功加载所述被调用程序。A4、根据A3所述的方法,其中,所述被调用程序通过判断所述被调用程序的实例不为空来确定所述被调用程序以插件的形式被调用。A5、根据A1-A4任一项所述的方法,其中,所述由所述主系统根据程序的生命周期调用所述调用程序对应的方法,由所述调用程序根据程序的生命周期调用所述被调用程序对应的方法进一步包括:由主系统根据程序的生命周期或者调用程序自身调用所述调用程序中的资源加载方法,加载所述调用程序或所述被调用程序的资源;由所述调用程序根据程序的生命周期调用所述被调用程序中的资源加载方法,加载所述被调用程序的资源。A6、根据A1-A4任一项所述的方法,其中,所述由所述主系统根据程序的生命周期调用所述调用程序对应的方法,由所述调用程序根据程序的生命周期调用所述被调用程序对应的方法进一步包括:由主系统通过所述调用程序反射调用所述被调用程序中的组件和服务对应的方法;由主系统调用所述调用程序中的除了上述组件和服务以外的其他组件和服务对应的方法;由所述调用程序调用所述调用程序和所述被调用程序中均不存在的组件和服务对应的方法。A7、根据A1-A6任一项所述的方法,其中,在所述调用程序加载被调用程序生成相关句柄及文件之前进一步包括:对所述被调用程序进行合法性鉴权。\n[0174] 本发明还公开了:B8、一种动态加载和调用程序的装置,其包括:主系统、调用程序运行模块以及被调用程序运行模块;其中,所述主系统包括:第一调用请求发起单元和第一调用单元;所述调用程序运行模块包括:加载单元、赋值单元、第二调用请求发起单元以及第二调用单元;所述第一调用请求发起单元适于发起对调用程序的调用请求;所述加载单元适于加载被调用程序生成相关句柄及文件,并得到所述调用程序的实例;所述赋值单元适于将所述调用程序的实例赋值给所述被调用程序的实例;所述第二调用请求发起单元适于发起对所述被调用程序的调用请求;所述第一调用单元适于根据程序的生命周期调用所述调用程序对应的方法;所述第二调用单元适于根据程序的生命周期调用所述被调用程序对应的方法。B9、根据B8所述的装置,其中,所述调用程序运行模块为已安装的用于调用插件的应用,所述被调用程序运行模块为未安装的APK插件。B10、根据B8或B9所述的装置,其中,所述调用程序运行模块适于通过判断所述调用程序的实例不为空来确定成功加载所述被调用程序。B11、根据B10所述的装置,其中,所述被调用程序运行模块适于通过判断所述被调用程序的实例不为空来确定所述被调用程序以插件的形式被调用。B12、根据B8-B11任一项所述的装置,其中,所述第一调用单元进一步适于:根据程序的生命周期调用所述调用程序中的资源加载方法,加载所述调用程序或所述被调用程序的资源;所述第二调用单元进一步适于根据程序的生命周期调用所述被调用程序中的资源加载方法,加载所述被调用程序的资源。B13、根据B8-B11任一项所述的装置,其中,所述第一调用单元进一步适于:通过所述第二调用单元反射调用所述被调用程序中的组件和服务对应的方法;以及调用所述调用程序中的除了上述组件和服务以外的其他组件和服务对应的方法;所述第二调用单元进一步适于:调用所述调用程序和所述被调用程序中均不存在的组件和服务对应的方法。\nB14、根据B8-B13任一项所述的装置,其中,所述调用程序运行模块还包括:鉴权单元,适于对所述被调用程序进行合法性鉴权。