CN104699537A - 程序控制方法与活动组件调度方法及其相应的装置 - Google Patents

程序控制方法与活动组件调度方法及其相应的装置 Download PDF

Info

Publication number
CN104699537A
CN104699537A CN201510119622.0A CN201510119622A CN104699537A CN 104699537 A CN104699537 A CN 104699537A CN 201510119622 A CN201510119622 A CN 201510119622A CN 104699537 A CN104699537 A CN 104699537A
Authority
CN
China
Prior art keywords
movable component
hole
loaded
activity
host
Prior art date
Legal status (The legal status is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the status listed.)
Granted
Application number
CN201510119622.0A
Other languages
English (en)
Other versions
CN104699537B (zh
Inventor
宋照春
张炅轩
姚彤
Current Assignee (The listed assignees may be inaccurate. Google has not performed a legal analysis and makes no representation or warranty as to the accuracy of the list.)
Beijing Qihoo Technology Co Ltd
Original Assignee
Beijing Qihoo Technology Co Ltd
Qizhi Software Beijing Co Ltd
Priority date (The priority date is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the date listed.)
Filing date
Publication date
Application filed by Beijing Qihoo Technology Co Ltd, Qizhi Software Beijing Co Ltd filed Critical Beijing Qihoo Technology Co Ltd
Priority to CN201510119622.0A priority Critical patent/CN104699537B/zh
Publication of CN104699537A publication Critical patent/CN104699537A/zh
Application granted granted Critical
Publication of CN104699537B publication Critical patent/CN104699537B/zh
Active legal-status Critical Current
Anticipated expiration legal-status Critical

Links

Abstract

本发明提供一种程序控制方法以及其所采用的活动组件调度方法,该调度方法包括如下步骤:提供给系统预注册多个活动组件坑位;构建包含所述多个活动组件坑位的特征信息的坑位列表;利用坑位列表为待加载活动组件分配相适配的目标活动组件坑位;将该待加载活动组件加载到目标坑位所对应的进程空间中运行。除了上述的各种方法,本发明还基于模块化编程思维为这些方法提供了相应的装置。本发明的应用,便于应用程序的活动组件的灵活扩展加载,可以简化应用程序的升级,也能简化云端服务系统的资源负荷。

Description

程序控制方法与活动组件调度方法及其相应的装置
技术领域
本发明涉及计算机应用程序的编程控制技术,尤其涉及以Android原理为基础的一种活动组件调度方法与装置,以及一种程序控制方法与装置。
背景技术
Android操作系统有其不同于其他操作系统的原理,Android为开发者提供四大组件,具体指Activity、Service、Receiver以及Content Provider等组件,其中Activity便是本发明所称的活动组件,通过对各组件的灵活运用,可以由开发者定制出应用程序。Android应用程序以APK安装包的形式提供给用户进行安装,APK安装包中,具有用于封装实现各个组件的程序代码的classes.dex代码文件以及用于表达应用程序所用的各个组件的注册信息以及权限申请信息等内容的Androidmanifest.xml配置文件。Activity组件通常用于实现用户界面以便应用程序能与用户进行人机交互,其代码可以被封装在classes.dex文件中,且需要在该配置文件中实现注册。配置文件中,各个activity的注册信息可以视为独立注册信息模块,视为“坑位”。Android系统在对应用程序进行安装时,由PackageManageService(PMS)对APK安装包的各个组件进行校验,而ActivityManagerSevice(AMS)则可以根据注册信息为活动组件建立进程入口(ActivityThread),以确保活动组件的正常运行。
通常,Activity活动组件应当预先在Androidmanafest.xml配置文件中进行坑位注册,并且坑位与组件名称以及活动组件的其他属性之间应保持一一对应性和确定性,这样才能够确保这些活动组件的正常注册。这种情况下,整个应用程序应当在开发时便确定了这些活动组件,由这些活动组件有机组合而成的应用程序继而作为一个整体提供给终端进行安装。终端每一次安装均是基于一个完整的应用程序的基础上进行,其中的每一个活动组件都在配置文件中进行了一一对应的注册表达,不存在任何不确定性。换言之,任何未经在Androidmanifest.xml注册的Activity活动组件,常规情况下均不能够被调度为进程进行运行。由此可知,每一次为应用程序扩展功能而提供新的活动组件,均需要将应用程序重新进行打包,并以打包后的安装文件提供给客户端进行安装,每次安装均是全量的。对于远程下载的情况而言,既浪费流量,又降低了效率,更不利于应用程序的功能模块的灵活扩展。
为了克服应用程序版本更迭所导致的流量浪费的问题,现有技术常以提供增量包的形式来降低安装流量,这种方式则需要架设繁重的云端服务架构,并且对终端的计算量也提出了更高的要求。更关键的,这种方式并不能满足应用程序功能模块灵活扩展这一需求。
现有技术也尝试在Activity提供的界面中进一步提供网页访问接口,甚至结合HTML5等新型技术,以期实现应用程序的功能扩充,但是,网页提供的交互功能毕竟有限,未必能充分开发终端的最大性能,用户体验上也将有所下降。
发明内容
本发明的首要目的旨在解决上述至少一个问题,提供一种活动组件动态调试方法以及与其相应的装置。
本发明的另一目的在于基于上述目的,进而提供一种程序控制方法以及与其相应的装置。
为了实现上述目的,本发明采取如下技术方案:
本发明提供的一种活动组件调度方法,包括如下步骤:
提供给系统预注册多个活动组件坑位;
构建包含所述多个活动组件坑位的特征信息的坑位列表;
利用坑位列表为待加载活动组件分配相适配的目标活动组件坑位;
将该待加载活动组件加载到目标坑位所对应的进程空间中运行。
上述注册活动组件坑位的步骤中,以实施本方法的宿主功能模块的配置文件中声明的用于表达预留的活动组件的注册信息向系统进行注册,以构造所述活动组件坑位。
较佳的,所述配置文件中活动组件的注册信息中的包名属性包含有用于识别不同进程空间的特征字符。
较佳的,所述配置文件为Androidmanifest.xml文件。
上述构建坑位列表的步骤中,在实施本方法的宿主功能模块启动时运行用于添加所述活动组件坑位的特征信息的代码指令以实现所述坑位列表的构建。
具体的,实施本方法的宿主功能模块的Application.onCreate方法中重构有所述的代码指令用于构建所述坑位列表。
进一步,所述的待加载活动组件为独立于实施本方法的宿主功能模块的插件功能模块,该插件功能模块包含实现该待加载活动组件的代码文件和用于声明该活动组件的注册信息的配置文件。
进一步,分配目标坑位时,利用预设的优选策略从坑位列表中选定与待加载活动组件相适配的唯一一个活动组件坑位以完成分配。
较佳的,所述加载待加载活动组件的步骤中,包括如下具体步骤:
中获得已被分配的目标活动组件坑位;
运行重构的类加载器为分配了坑位的待加载活动组件确定类对象;
运行指令打开目标坑位以令待加载活动组件加载于进程空间中运行。
其中,所述重构的类加载器继承自DexClassLoader,其findClass方法被重构,以用于为分配了坑位的待加载活动组件确定类对象。
进一步,打开目标坑位时,先通过ComponentName对象传递目标坑位的进程空间,利用该对象构造Intent,然后以context.startActivity方法调用该Intent以便打开目标坑位。
较佳的,本方法还包括在分配目标坑位之前为目标坑位优选进程空间的步骤。
本发明提供的一种活动组件调度装置,包括:
注册单元,其提供给系统预注册多个活动组件坑位;
构建单元,用于构建包含所述多个活动组件坑位的坑位列表;
分配单元,用于利用坑位列表为待加载活动组件分配相适配的目标活动组件坑位;
加载单元,用于将该待加载活动组件加载到目标坑位所对应的进程空间中运行。
所述注册单元,被配置为利用包含了本装置的宿主功能模块的配置文件中声明的用于表达预留的活动组件的注册信息进行注册,以构造所述活动组件坑位。
所述配置文件中活动组件的注册信息中的包名属性包含有用于识别不同进程空间的特征字符。
较佳的,所述配置文件为Androidmanifest.xml文件。
所述构建单元,被配置为在包含了本装置的宿主功能模块启动时运行用于添加所述活动组件坑位的特征信息的代码指令以实现所述坑位列表的构建。
较佳的,包含了本装置的宿主功能模块的Application.onCreate方法中重构有所述的代码指令用于构建所述坑位列表。
进一步,所述的待加载活动组件为独立于包含了本装置的宿主功能模块的插件功能模块,该插件功能模块包含实现该待加载活动组件的代码文件和用于声明该活动组件的注册信息的配置文件。
所述的分配单元,被配置为在分配目标坑位时,利用预设的优选策略从坑位列表中选定与待加载活动组件相适配的唯一一个活动组件坑位以完成分配。
进一步,所述加载单元包括:
获取模块,用于获得已被分配的目标活动组件坑位;
创建模块,用于运行重构的类加载器为分配了坑位的待加载活动组件确定类对象;
运行模块,用于运行指令打开目标坑位以令待加载活动组件加载于进程空间中运行。
较佳的,所述重构的类加载器继承自DexClassLoader,其findClass方法被重构,以用于为分配了坑位的待加载活动组件确定类对象。
具体的,所述运行模块,被配置为先通过ComponentName对象传递目标坑位的进程空间,利用该对象构造Intent,然后以context.startActivity方法调用该Intent以便打开目标坑位。
较佳的,本装置还包括用于在分配目标坑位之前为目标坑位优选进程空间的优选装置。
本发明提供的一种程序控制方法,该方法利用宿主功能模块实现了如本发明首要目的所述的所述的活动组件调度方法的任何一种实施方式,并以该方法对所述插件功能模块所包含的活动组件实施调度,使该活动组件运行于由宿主功能模块所创建的进程空间中。
本发明提供的一种程序控制装置,其包括宿主功能模块和插件功能模块,所述宿主功能模块包含有如本发明首要目的所述的活动组件调度装置的任何一种实施方式,所述宿主功能模块被配置为利用该活动组件调度装置实现对所述插件功能模块所包含的活动组件的调度,使该活动组件运行于由宿主功能模块所创建的进程空间中。
与现有技术相比较,本发明的方案具有以下优点:
1、本发明实现了活动组件(Activity)的完全自定义,加载活动组件无需修改主程序,由此可以使得作为主程序的宿主功能模块永远不需升级,只需要以宿主功能模块实施的本发明的技术手段,即可实现按需加载相应的活动组件,理论上可以无限扩展主程序的功能。
2、由于主程序无需升级,而所扩展的活动组件又便于被打包处理成插件功能模块,因此,每次进行升级时,只需下载相应的插件功能模块即可。这就真正做到了最小化安装,大大节省流量,又不需大量消耗终端的资源,既省流量又能能高效运行。
3、插件功能模块可以标准化实现,由此便可以简化应用分发系统的云端实现,有利于不同应用程序之间的资源共享。不同应用程序之间只要构建了实施本发明的架构,即可通过下载一些共通的插件功能模块来实现同一的功能,显然大大减轻了开发者的劳动,也简化了服务器的程序资源的复杂度。
综上所述,本发明的应用,便于应用程序的活动组件的灵活扩展加载,可以简化应用程序的升级,也能简化云端服务系统的资源负荷。
本发明附加的方面和优点将在下面的描述中部分给出,这些将从下面的描述中变得明显,或通过本发明的实践了解到。
附图说明
本发明上述的和/或附加的方面和优点从下面结合附图对实施例的描述中将变得明显和容易理解,其中:
图1为本发明的活动组件调度方法的流程示意图;
图2为本发明的活动组件进程空间分配方法的流程示意图;
图3为本发明的活动组件调度装置的原理框图;
图4为本发明的活动组件进程空间分配装置的原理框图。
具体实施方式
下面详细描述本发明的实施例,所述实施例的示例在附图中示出,其中自始至终相同或类似的标号表示相同或类似的元件或具有相同或类似功能的元件。下面通过参考附图描述的实施例是示例性的,仅用于解释本发明,而不能解释为对本发明的限制。
本技术领域技术人员可以理解,除非特意声明,这里使用的单数形式“一”、“一个”、“所述”和“该”也可包括复数形式。应该进一步理解的是,本发明的说明书中使用的措辞“包括”是指存在所述特征、整数、步骤、操作、元件和/或组件,但是并不排除存在或添加一个或多个其他特征、整数、步骤、操作、元件、组件和/或它们的组。应该理解,当我们称元件被“连接”或“耦接”到另一元件时,它可以直接连接或耦接到其他元件,或者也可以存在中间元件。此外,这里使用的“连接”或“耦接”可以包括无线连接或无线耦接。这里使用的措辞“和/或”包括一个或更多个相关联的列出项的全部或任一单元和全部组合。
本技术领域技术人员可以理解,除非另外定义,这里使用的所有术语(包括技术术语和科学术语),具有与本发明所属领域中的普通技术人员的一般理解相同的意义。还应该理解的是,诸如通用字典中定义的那些术语,应该被理解为具有与现有技术的上下文中的意义一致的意义,并且除非像这里一样被特定定义,否则不会用理想化或过于正式的含义来解释。
本技术领域技术人员可以理解,这里所使用的“终端”、“终端设备”既包括无线信号接收器的设备,其仅具备无发射能力的无线信号接收器的设备,又包括接收和发射硬件的设备,其具有能够在双向通信链路上,执行双向通信的接收和发射硬件的设备。这种设备可以包括:蜂窝或其他通信设备,其具有单线路显示器或多线路显示器或没有多线路显示器的蜂窝或其他通信设备;PCS(Personal Communications Service,个人通信系统),其可以组合语音、数据处理、传真和/或数据通信能力;PDA(PersonalDigital Assistant,个人数字助理),其可以包括射频接收器、寻呼机、互联网/内联网访问、网络浏览器、记事本、日历和/或GPS(Global PositioningSystem,全球定位系统)接收器;常规膝上型和/或掌上型计算机或其他设备,其具有和/或包括射频接收器的常规膝上型和/或掌上型计算机或其他设备。这里所使用的“终端”、“终端设备”可以是便携式、可运输、安装在交通工具(航空、海运和/或陆地)中的,或者适合于和/或配置为在本地运行,和/或以分布形式,运行在地球和/或空间的任何其他位置运行。这里所使用的“终端”、“终端设备”还可以是通信终端、上网终端、音乐/视频播放终端,例如可以是PDA、MID(Mobile Internet Device,移动互联网设备)和/或具有音乐/视频播放功能的移动电话,也可以是智能电视、机顶盒等设备。
本技术领域技术人员可以理解,这里所使用的远端网络设备,其包括但不限于计算机、网络主机、单个网络服务器、多个网络服务器集或多个服务器构成的云。在此,云由基于云计算(Cloud Computing)的大量计算机或网络服务器构成,其中,云计算是分布式计算的一种,由一群松散耦合的计算机集组成的一个超级虚拟计算机。本发明的实施例中,远端网络设备、终端设备与WNS服务器之间可通过任何通信方式实现通信,包括但不限于,基于3GPP、LTE、WIMAX的移动通信、基于TCP/IP、UDP协议的计算机网络通信以及基于蓝牙、红外传输标准的近距无线传输方式。
本发明所做出的改进,主要是以Android的Dalvik虚拟机为基础而提出的,当然,如果其它操作系统中架构了类似于Dalvik的机制,理论上也可以将本发明推广之。为了理解本发明,请先了解如下揭示的Android系统的安装文件结构:
Android系统中,每一个应用程序安装包都为APK文件,即AndroidApplication Package File的缩写,其实质是zip格式的文件,对其进行解压缩可以得到以下文件结构:
表1 APK文件结构
通常,开发Android应用程序时,是以Android提供的四大组件为单元进行开发的,这四大组件分别是Activity、Service、Receiver、Provider,四大组件相关的代码会被整合到classes.dex文件中,但这四大组件所需的注册信息和权限请求信息则会被声明到Androidmanifest.xml文件中。每个apk文件中都包含有一个AndroidManifest.xml文件,它记录着安装包的全局配置信息,是典型的配置文件。该配置文件中,除了包名package name、版本编号versionCode、版本号versionName等信息,还包括应用程序注册的activity、service、receiver、Provider等系统组件,各大组件的注册信息在该配置文件中予以声明,在安装时,提供给应用程序向系统注册,具体是由系统的PackageManagerService读取该配置文件以完成注册。众所周知的,通常情况下,只有在Androidmanifest.xml中声明了的活动组件(Activity)才能够被程序调用,才能打开,从而显示活动界面,以便于在终端上实现人机交互。而本发明提供的活动组件调度方法则可以克服此一先天不足。
如图1所揭示的本发明的活动组件调度方法,可以实现于作为主程序使用的宿主功能模块中,其具体包括如下步骤:
S11、提供给系统预注册多个活动组件坑位。
如前所述,常规情况下,活动组件需要在作为主程序的宿主功能模块中的Androidmanifest.xml文件中进行声明,以便在系统进行安装时,以该声明中的注册信息对相关的活动组件进行注册。而本发明是出于预留的目的而在宿主功能模块的Androidmanifest.xml配置文件中设置多个活动组件注册信息,但这些注册信息所指向的活动组件的真实内容并未确定,因此,本发明中,形象地将这些配置文件预留了注册信息的活动组件,并在该配置文件提供给系统进行安装之后形成的活动组件虚拟单位称之为活动组件坑位。具体而言,预先在主程序的Androidmanifest.xml文件中声明了多个活动组件的注册信息,以便在主程序安装时,由PMS依据这些注册信息进行注册,由AMS为其建立进程入口,从而形成所述的活动组件坑位。
考虑到本发明中,将依据活动组件的不同属性,诸如launchMode、taskAffinity、theme等属性对活动组件进行分类管理,因此,在所述的注册信息中所使用到的包名,可以在包名的后缀中使用不同的特征字符用于表征不同类型的坑位,也是指代不同的进程空间,以利于识别。例如以下引用的一个实例:
其中活动组件的包名中的形如ActivityX中的X便特征字符,特征字符X代表活动组件应跑在哪一个进程空间里,上例所给出的“N1”较为特殊,是为保留的特征字符,表示主进程(UI进程),“N1”之后则可以是指代依据前述各种活动组件属性而给出的不同类型的活动组件。上例所给出的包名的后缀ActivityN1ST0可以表征本坑位跑在系统默认(UI)进程,且使用后续揭示的SingleTask表,而Activity0ST0则表示跑在loader0进程,且使用SingleTask表。关于这些不同特征字符以及与之相对应的不同类型的表之间的关系,将在后续进行揭示。
需要优先提及的是,本发明的调度对象,也即待加载的活动组件通常是以插件功能模块的形式给出,例如以一个压缩包的形式提供给用户进行下载并由本发明的技术手段加以装载。这一插件功能模块除了包含活动组件的功能代码之外,还可以通过一个内置的配置文件名如Androidmanifest.xml加以表达其固有的注册信息,这里所称的插件的配置文件的注册信息则可以灵活甚至无约束地进行编写,例如,可以按照以下形式进行编写:
也就是说,插件功能模块自身的注册信息并不能确定其跑在哪个进程,而是通过本发明的方法来决定上述的AntitheftEntryActivity最终会落在ActivityN1ST0、ActivityN1ST1(单进程)Activity0ST0、Activity1ST0中的哪一个坑位中。
S12、构建包含所述多个活动组件坑位的特征信息的坑位列表。
构建坑位列表的过程,将涉及到对Application类的运用,因此先行介绍Application类。
Application和Activity、Service一样是Android框架的一个系统组件,当Android程序启动时系统会创建一个Application对象,用来存储系统的一些信息。Android系统自动会为每个程序运行时创建一个Application类的对象且只创建一个,所以Application可以说是单例(singleton)模式的一个类。通常使用时并不需要指定一个Application,系统会自动为之创建该类,如果需要创建自有的Application,只需创建一个类继承Application并在AndroidManifest.xml文件中的application标签中进行注册(只需要给application标签增加name属性,并添加自己的Application的名字即可)。
启动Application时,系统会创建一个PID,即进程ID,所有的Activity都会在此进程上运行。那么如果在Application创建的时候初始化全局变量,同一个应用的所有Activity都可以取到这些全局变量的值,换句话说,如果在某一个Activity中改变了这些全局变量的值,那么在同一个应用的其他Activity中值就会改变。Application对象的生命周期是整个程序中最长的,它的生命周期就等于这个程序的生命周期。因为它是全局的单例的,所以在不同的Activity、Service中获得的对象都是同一个对象。所以可以通过Application来进行一些,如:数据传递、数据共享和数据缓存等操作。通过继承Application类来实现应用程序级的全局变量,这种全局变量方法相对静态类更有保障,直到应用的所有Activity全部被destory掉之后才会被释放掉。
同理,请进一步了解Android的Activity提供的launchMode属性。
launchMode在多个Activity跳转的过程中扮演着重要的角色,它可以决定是否生成新的Activity实例,是否重用已存在的Activity实例,是否和其他Activity实例公用一个task栈。这里简单介绍一下task的概念,task是一个具有栈结构的对象,一个task可以管理多个Activity,启动一个应用,也就创建一个与之对应的task。
Activity一共有以下四种launchMode,几种模式及其介绍如下:
1.standard
standard模式是默认的启动模式,不用为<activity>配置android:launchMode属性即可,当然也可以指定值为standard。standard启动模式,不管有没有已存在的实例,都生成新的实例。
2.singleTop
singleTop启动模式,如果发现有对应的Activity实例正位于栈顶,则重复利用,不再生成新的实例。
3.singleTask
singleTask模式,如果发现有对应的Activity实例,则使此Activity实例之上的其他Activity实例统统出栈,使此Activity实例成为栈顶对象,显示到幕前
4.singleInstance
这种启动模式比较特殊,因为它会启用一个新的栈结构,将Acitvity放置于这个新的栈结构中,并保证不再有其他Activity实例进入。
可以在AndroidManifest.xml配置<activity>的android:launchMode属性为以上四种之一即可。
鉴于Application和launchMode的以上特性,本发明通过重构Application.onCreate方法,在其中写入用于添加每个活动组件坑位特征信息的代码指令,来实现所述坑位列表的构建。
下列给出的表,即坑位列表,该坑位列表实质上是实现了对具体列表的索引,形如:
上面的代码中,String字段是字符串,表示Activity坑位的坑位名,而ActivityState则为状态信息。从这个坑位列表可以看出,该坑位列表虽然可以是直接包含每个活动组件坑位的建立了映射关系的特征信息,但在该表给出的实施例中,则是通过包含一个总表和多个类型表来建立对活动组件坑位特征信息的管理。上述的代码所给出的各表,从上至下,依次为:
mStates:总表,顾名思义,所有的Activity都要存储在这张表中,以作为汇总之用。
mStatesST:表示launchMode为SingleTask的表,其注册信息可以按照如下方式进行表达:
mStatesTA:表示taskAffinity为指定值的表,taskAffinity属性表示Activity的归属,也就是Activity应该在哪个Task中,Activity与Task的吸附关系。一般情况下在同一个应用中,启动的Activity都在同一个Task中,它们在该Task中度过自己的生命周期。如果一个Activity没有显式的指明该Activity的taskAffinity,那么它的这个属性就等于Application指明的taskAffinity,如果Application也没有指明,那么该taskAffinity的值就等于包名。而Task也有自己的affinity属性,它的值等于它的根Activity的taskAffinity的值。一开始,创建的Activity都会在创建它的Task中,并且大部分都在这里度过了它的整个生命。然而有一些情况,创建的Activity会被分配其它的Task中去,有的甚至,本来在一个Task中,之后出现了转移。因此,有必要以taskAffinity为依据形成类型表。此表的注册信息可以按照如下方式进行表达:
mStatesNR:表示launchMode为Standard(默认值)的表,其注册信息可以按照如下方式进行表达:
mStatesSI:表示launchMode为SingleInstance的表,其注册信息可以按照如下方式进行表达:
mStatesF:表示theme属性为FullScreen(全屏幕)的表,其注册信息可以按照如下方式进行表达:
mStatesT:表示theme属性为Translucent(透明背景)的表,其注册信息可以按照如下方式进行表达:
mStatesTF:表示theme属性为Translucent.FullScreen(全屏且透明)的表,其注册信息可以按照如下方式进行表达:
mStatesD:表示theme为Dialog的表,其注册信息可以按照如下方式进行表达:
mStatesSID:表示launchMode为SingleInstance、且Theme为Dialog的表,其注册信息可以按照如下方式进行表达:
以上逐一介绍了坑位列表中的总表和类型表,主要用于向读者说明坑位列表的一个实施方式,本领域技术人员应当理解,坑位列表的实现,只要建立了对所述活动组件坑位的特征信息的管理,不管其具体实现形式如何,也不管其直接还是间接包含了所述的特征信息,均能够为本领域技术人员依据本发明的精神实质而灵活运用。
如前所述,在熟知上述实现方式的基础上,通过重构Application.onCreate方法的代码,即可实现对所述坑位列表的建立。以下给出代码示例形如:
通过形如上述的代码示例的实施,最终,每一个活动组件坑位都分别创建到mStates总表以及其它类型表中,其中Containers表示Activity的“mContainerActivity”对象。
通过上述的方式,便建立起坑位列表所包括的各个子表的索引关系,由此形成一个数据架构。继而,对于每个坑位而言,需要了解其记载到坑位列表,具体是存储到各个相应表格中的特征信息的结构。每个坑位的特征信息,主要是由存在映射关系的坑位名、使用状态、待加载活动组件名称(即插件功能模块的名称)、修改使用状态时的时间戳、对活动组件的弱引用等数据项组成,必要时,也可对这些关键项进行修饰性的增减。这些特征信息项,概述如下:
(1)container:活动组件坑位对应的坑位名;
(2)state:活动组件坑位使用状态,具有以下几种标识:
Private static final int STATE_NONE=0//表示非使用状态
Private static final int STATE_REGISTERED=1//表示已分配状态
Private static final int STATE_LOADED=2//表示已加载状态
Private static final int STATE_CREATED=3//表示已创建状态
Private static final int STATE_RECYCLED=4//表示已回收状态
(3)mCN:对应的目标插件功能模块及其名称;
(4)timestamp:修改使用状态时的时间戳;
(5)ref:保留对活动组件的弱引用。
以上特征信息在可以在多种情况下按需赋值。例如mCN字段会在分配阶段进行赋值,而state情况特殊,下面分别举例说明:
1、进入主程序时,会在Application.attachBaseContext中,初始化进程的上述信息,将各个活动组件坑位的state置为STATE_NONE;
2、当插件功能模块中的待加载活动组件被分配坑位,会将state状态置为STATE_REGISTERED;
3、当待加载活动组件被类加载器classLoader加载后,活动组件坑位被返回并被加载后,会将state状态置为STATE_LOADED;
4、当待加载活动组件的onCreate方法被调用,会将相应的目标坑位的state状态置为STATE_CREATED;
5、当待加载活动组件被释放(调用Activity.onDestroy,或坑位已满,分配时),则会将state状态置为STATE_RECYCLED。
以上,详细地揭示了实现所述坑位列表的一个示例,本领域技术人员根据上述对于本步骤的示例性说明,足以知晓本步骤的具体实现及其变例。经过本步骤的处理,将构建出本发明所需的包含有多个活动组件坑位特征信息的坑位列表。该坑位列表也是实现本发明的活动组件进程空间分配方法和装置所必须的准备。
步骤S13、利用坑位列表为待加载活动组件分配相适配的目标活动组件坑位。
为了实施本步骤,本发明进而揭示一种活动组件进程空间分配方法,运用这一方法来对所述的坑位列表加以利用,最终为插件功能模块中的待加载活动组件分配坑位。该方法主要由以下的步骤S21、S22、S23实现,以下结合图2对各个步骤进行详细说明:
步骤S21、接收为待加载活动组件分配活动组件坑位的请求。
同理,由于本发明的活动组件进程空间分配方法作为本发明的活动组件调度方法的一部分,被编程实现于作为主程序的宿主功能模块中,因而,其主要利用过程思维编程成功能模块,对外接收参数以接收请求,并向请求方反馈相应的结果。基于这一原理,通过本步骤,当主程序需要加载插件功能模块的待加载活动组件时,将由主程序或其构成部分传递待加载活动组件的相关信息给本分配方法所构造的功能模块,以便由本分配方法对其进行后续的处理。
需要指出的是,本分配方法待要进行分配的活动组件坑位,也就是本发明的调度方法所构建的活动组件坑位,因此,这些活动组件坑位即是作为主程序的宿主功能模块的Androidmanifest.xml文件中声明了注册信息并向系统注册而形成的进程空间。本分配方法更优之处在于,可以在某一个进程中,管理多个插件功能模块的待加载活动组件。
步骤S22、利用预设的优选策略,从坑位列表中为待加载活动组件优选相适配的目标活动组件坑位。
所述的坑位列表,也即前述步骤S12所构建的坑位列表,用于存储多个预注册的活动组件坑位的特征信息。由于如前所述的示例中,坑位列表包含有总表和各种类型表,其中的总表包含有所有活动组件坑位的特征信息,其中的类型表只存储属于具有相同类型特征的活动组件坑位的特征信息,因此,在实施预设的优选策略时,可以先对类型表进行检索,在类型表未找到甜酸的活动组件时才在总表中进一步检索。而在实施检索时,依照前述揭示的坑位列表设计原理,相应地,也应依据活动组件的launchMode、taskAffinity和/或theme属性进行判别以确定具体相对应的类型表。
本步骤对所述目标活动组件坑位的优选,主要是依据其中的使用状态为依据进行。
以下揭示运用所述优选策略的流程:
本调度方法预先在PackageInfo中存储了所有ActivityInfo对象,所以可以在这里直接使用这些信息。在本子步骤中,通过launchMode、taskAffinity、theme等属性判别与请求分配的待加载活动组件所属的类型表,开始对类型表进行检索。示例代码如下:
继而,从相应的类型表中确定相适配的目标活动组件坑位,上面的代码中,alloc方法的签名为:
其中,ai表示ActivityInfo,map就是指定的坑位列表,plugin和activity分别代表插件功能模块名称及其待加载活动组件名称。
采用如下的策略进行优选,按序进行,只要以下任何一条规则得到满足,即可直接返回结果,不必进行后续步骤:
(1)对于SingleTask和SingleInstance类型的优选,是优选查找上一个用过的实例。参阅如下代码:
如前所述,SingleTask和SingleInstance比较特殊,这两种模式系统要求Activity实例只能有一份,故必须找上一个已经打开的实例。而其它LaunchMode没有这个限制,可以使用多个实例。
比如说,二维码插件的BarcodeActivity之前已经打开过,那么若仍要打开,则在这里会做判断:首先其使用状态必须得是STATE_CREATED,并且目标插件必须是二维码,且Activity必须是对应的名称如BarcodeActivity,且还有Activity对象,如此才能直接返回该结果。否则任一条件不符合,都将进行下一步。
(2)采用未用过的坑位,参阅如下代码:
如果通过检测,该坑位未使用,则直接使用,返回结果,不进行后续步骤。
(3)采用已经用过但已经停止的,注意这里不区分launchMode,其中SI和ST这两种情况已经在之前的步骤处理过。参阅代码:
同理,如果找到,返回结果,不进行后续步骤。
(4)寻找最早的一个已经被翻译的坑位。参阅代码如下:
同理,如果找到,返回结果,不进行后续步骤。
(5)与第(4)条策略不同的是,这里即使是已被分配状态,但没有用过的坑位(这种情况比较少,通常是Activity一创建就释放或者创建失败等),这里要回收其中最早的那一个。参阅如下代码:
同理,如果找到,返回结果,不进行后续步骤。
(6)在穷举上述各种策略而未找到相适配的坑位的情况下,只能回收最早加载的那一个。参阅如下代码:
如果找到,返回结果,不进行后续步骤。
(7)同理,在以上各种策略查找均失败的情况下,只能才用最后一个策略,回收正在运行的最早的一个Activity。参阅如下代码:
经过上述的优选策略的作用,最终将获得唯一一个目标活动组件坑位,完成坑位分配。
步骤23、通过前一步骤获取该目标坑位之后,即可将该坑位的特征信息中的使用状态state置为STATE_REGISTERED,同时获得该坑位的坑位名Activity.mContainer,作为结果返回给请求方即可。
通过上述本发明提供的活动组件进程空间分配方法,可以优选出一个与待加载活动组件相适配的目标活动组件坑位。获得这个目标坑位后,便可以在相关返回的信息的基础上,由本发明的调度方法做后续处理。
步骤S14、将该待加载活动组件加载到目标坑位所对应的进程空间中运行。
基于前述步骤的实施结果,本发明继而按照如下具体步骤将待加载活动组件加载到相应的进程空间中运行:
步骤141、从所述坑位列表中获得已被分配的目标活动组件坑位。
如前所述,在步骤13中,通过本发明提供的分配方法可最终确定唯一一个目标坑位,并且返回该目标坑位的信息。这些信息主要包含坑位名称,确定坑位名称之后,即可通过类加载器加载待加载活动组件。
由于在步骤13中,已经将目标坑位的使用状态state标记为STATE_REGISTERED并返回了坑位名,因此,在本子步骤中,只需要以该标记对坑位列表(具体到某个类型表)进行查找即可。参考如下代码:
步骤142、运行重构的类加载器为分配了坑位的待加载活动组件确定类对象。
本发明所称的类加载器,是通过重构系统的ClassLoader实现的。重构类加载器的目的,是希望在主程序启动时改变系统生成新类的方法,从而确保正确加载待加载活动组件,使其运行于目标坑位所指代的进程空间。
一种现有技术中,常通过自己生成DexClassLoader,在插件启动时调用来实现,其缺点显而易见,就是调用起来非常不直观,必须得先调用DexClassLoader的指定方法来实现。如下所示:
现有:XXX my=mDexClassLoader.findClass(XXX).newInstance();
本作:XXX my=new XXX();
另一种现有技术中,通过替换Thread的contextClassLoader方式来实现。这一方式最大的问题是不支持Activity、Service、AIDL等场景,这些地方系统默认会使用PackageInfo的ClassLoader,而非Thread的,使用场景受到严重的限制。
本发明的重构的ClassLoader将实现对系统的类加载器的完全替换,具体是通过替换PackageInfo的ClassLoader,来确保替换无死角,不仅Thread可以使用,连Activity、Service等组件都能使用自定义的ClassLoader来实现加载,其应用场景更为广泛,并且调用过程非常直观,调用者无需考虑任何替换关系,直接使用即可。
实现自定义类加载器的方法,可以参照如下步骤进行:
首先,每一个进程启动时,都会调用Application对象,该对象也可以通过继承的方式自定义。系统会最先调用Application.attachBaseContext方法,因此,适宜在此处导入重构的ClassLoader。
然后,获取PackageInfo。在这一过程中,按照如下子步骤实现:
(1)首先需要获取ContextWrapper对象。也即:反射获取Application对象中的mBase字段即可。所获取的对象存好备用。
(2)获取mPackageInfo。
获取的mBase对象,在不同的Android系统上会代表着不同的类型,如Android 2.1为ApplicationContext,而Android 2.2则为ContextImpl,在Android 2.3及以上则为AppContextImpl。但不管是哪一个,都有共同的特点,即都有一个名叫“mPackageInfo”字段,直接反射获取mBase对象中的mPackageInfo字段,即可获得PackageInfo对象。
以上两条可用代码来说明:
继而,生成自定义的ClassLoader对象。
只要自定义的类继承了ClassLoader或其子类对象,就意味着完成了自定义操作。在这个基础上,本领域技术人员可以理解,可以做大量和插件功能模块有关的工作。
除了自定义,还必须覆写ClassLoader中的所有方法,每一个方法最终都应该指向之前的ClassLoader,由此即可确保ClassLoader的成功重构和正常使用。以不添加任何自定义功能的代码示例如下:
如上所述,mBase就是之前的ClassLoader。在处理完自定义事件后,如有必要,则需要调用mBase的对应方法。
最后,替换PackageInfo的mClassLoader
将之前存留好的mPackageInfo对象取出,通过反射来设置mClassLoader字段为上述生成的自定义ClassLoader对象即可。
以代码为例,在获取mPackageInfo的代码示例的“……”省略部分可以插入如下的示例代码:
由此,替换系统的ClassLoader的过程结束,完成了ClassLoader的自定义重构。由于系统的ClassLoader被替换成了自定义的ClassLoader,根据它的使用场景和性质,一般而言,只要有获取类信息、生成新类、调用Native方法等情况,就一定会通过该自定义ClassLoader来加载。
因此,通过上述实现的自定义ClassLoader,继承之DexClassLoader,其findClass方法也被重构,在findClass中实现为所述的待加载活动组件查找对象。一旦找到了目标坑位对象的名称,接下来只需要将当前插件功能模块的ClassLoader获取到,然后执行invoke方法,即可获取该插件的Class对象。
步骤S143、运行指令打开目标坑位以令待加载活动组件加载于进程空间中运行。
具体而言,由于进程空间既定,且待加载活动组件的类对象也已经找到,接下只需要对两者进行拼接即可。首先通过ComponentName(系统Intent的固有功能)对象传递目标坑位的进程空间,利用该对象构造Intent,然后以context.startActivity方法调用该Intent,即可打开目标坑位,从而使待加载活动组件加载于既定进程空间中运行。
在本发明的其他实施例中,用于所述待加载活动组件进行运行的进程空间,可以经过一个优选的步骤,以便在前述分配目标坑位之前提供一个既定且优选的进程空间。
可见,本发明提供的活动组件调度方法,可以实现对待加载活动组件的灵活调度,使得待加载活动组件可以以插件功能模块的方式独立于作为主程序的宿主功能模块之外灵活添加。
进一步,可以将本发明的活动组件调度方法实例化成程序,附加到作为主程序使用的宿主功能模块中,而提供一种程序控制方法,在主程序运行时,实施本调度方法,对所述插件功能模块所包含的活动组件实施调度,使该活动组件运行于由宿主功能模块所创建的进程空间中。这种主程序的升级将变得更为简易和省流量,理论上只要不涉及主程序的框架修改,主程序便可以永不升级。
而本发明提供的活动组件进程空间分配方法,则实现了基于单进程情况下加载待加载活动组件的高效管理,使得对这种待加载活动组件的灵活添加、升级成为可能。
基于计算机程序的模块化思维,可以以本发明的精神实质进行编程,形成由执行独立功能的若干模块,基于这一思维,下面继续揭示本发明提供的一种活动组件调度装置。
如图3所示,本发明的活动组件调度装置包括注册单元11、构建单元12、分配单元13以及加载单元14。
所述的注册单元11,用于提供给系统预注册多个活动组件坑位。
如前所述,常规情况下,活动组件需要在作为主程序的宿主功能模块中的Androidmanifest.xml文件中进行声明,以便在系统进行安装时,以该声明中的注册信息对相关的活动组件进行注册。而本发明是出于预留的目的而在宿主功能模块的Androidmanifest.xml配置文件中设置多个活动组件注册信息,但这些注册信息所指向的活动组件的真实内容并未确定,因此,本发明中,形象地将这些配置文件预留了注册信息的活动组件,并在该配置文件提供给系统进行安装之后形成的活动组件虚拟单位称之为活动组件坑位。具体而言,预先在主程序的Androidmanifest.xml文件中声明了多个活动组件的注册信息,以便在主程序安装时,由PMS依据这些注册信息进行注册,由AMS为其建立进程入口,从而形成所述的活动组件坑位。
考虑到本发明中,将依据活动组件的不同属性,诸如launchMode、taskAffinity、theme等属性对活动组件进行分类管理,因此,在所述的注册信息中所使用到的包名,可以在包名的后缀中使用不同的特征字符用于表征不同类型的坑位,也是指代不同的进程空间,以利于识别。例如以下引用的一个实例:
其中活动组件的包名中的形如ActivityX中的X便特征字符,特征字符X代表活动组件应跑在哪一个进程空间里,上例所给出的“N1”较为特殊,是为保留的特征字符,表示主进程(UI进程),“N1”之后则可以是指代依据前述各种活动组件属性而给出的不同类型的活动组件。上例所给出的包名的后缀ActivityN1ST0可以表征本坑位跑在系统默认(UI)进程,且使用后续揭示的SingleTask表,而Activity0ST0则表示跑在loader0进程,且使用SingleTask表。关于这些不同特征字符以及与之相对应的不同类型的表之间的关系,将在后续进行揭示。
需要优先提及的是,本发明的调度对象,也即待加载的活动组件通常是以插件功能模块的形式给出,例如以一个压缩包的形式提供给用户进行下载并由本发明的技术手段加以装载。这一插件功能模块除了包含活动组件的功能代码之外,还可以通过一个内置的配置文件名如Androidmanifest.xml加以表达其固有的注册信息,这里所称的插件的配置文件的注册信息则可以灵活甚至无约束地进行编写,例如,可以按照以下形式进行编写:
也就是说,插件功能模块自身的注册信息并不能确定其跑在哪个进程,而是通过本发明来决定上述的AntitheftEntryActivity最终会落在ActivityN1ST0、ActivityN1ST1(单进程)Activity0ST0、Activity1ST0中的哪一个坑位中。
所述的构建单元12,用于构建包含所述多个活动组件坑位的特征信息的坑位列表。
构建单元12构建坑位列表的过程,将涉及到对Application类的运用,因此先行介绍Application类。
Application和Activity、Service一样是Android框架的一个系统组件,当Android程序启动时系统会创建一个Application对象,用来存储系统的一些信息。Android系统自动会为每个程序运行时创建一个Application类的对象且只创建一个,所以Application可以说是单例(singleton)模式的一个类。通常使用时并不需要指定一个Application,系统会自动为之创建该类,如果需要创建自有的Application,只需创建一个类继承Application并在AndroidManifest.xml文件中的application标签中进行注册(只需要给application标签增加name属性,并添加自己的Application的名字即可)。
启动Application时,系统会创建一个PID,即进程ID,所有的Activity都会在此进程上运行。那么如果在Application创建的时候初始化全局变量,同一个应用的所有Activity都可以取到这些全局变量的值,换句话说,如果在某一个Activity中改变了这些全局变量的值,那么在同一个应用的其他Activity中值就会改变。Application对象的生命周期是整个程序中最长的,它的生命周期就等于这个程序的生命周期。因为它是全局的单例的,所以在不同的Activity、Service中获得的对象都是同一个对象。所以可以通过Application来进行一些,如:数据传递、数据共享和数据缓存等操作。通过继承Application类来实现应用程序级的全局变量,这种全局变量方法相对静态类更有保障,直到应用的所有Activity全部被destory掉之后才会被释放掉。
同理,请进一步了解Android的Activity提供的launchMode属性。
launchMode在多个Activity跳转的过程中扮演着重要的角色,它可以决定是否生成新的Activity实例,是否重用已存在的Activity实例,是否和其他Activity实例公用一个task栈。这里简单介绍一下task的概念,task是一个具有栈结构的对象,一个task可以管理多个Activity,启动一个应用,也就创建一个与之对应的task。
Activity一共有以下四种launchMode,几种模式及其介绍如下:
1.standard
standard模式是默认的启动模式,不用为<activity>配置android:launchMode属性即可,当然也可以指定值为standard。standard启动模式,不管有没有已存在的实例,都生成新的实例。
2.singleTop
singleTop启动模式,如果发现有对应的Activity实例正位于栈顶,则重复利用,不再生成新的实例。
3.singleTask
singleTask模式,如果发现有对应的Activity实例,则使此Activity实例之上的其他Activity实例统统出栈,使此Activity实例成为栈顶对象,显示到幕前
4.singleInstance
这种启动模式比较特殊,因为它会启用一个新的栈结构,将Acitvity放置于这个新的栈结构中,并保证不再有其他Activity实例进入。
可以在AndroidManifest.xml配置<activity>的android:launchMode属性为以上四种之一即可。
鉴于Application和launchMode的以上特性,本发明通过重构Application.onCreate方法,在其中写入用于添加每个活动组件坑位特征信息的代码指令,来实现所述坑位列表的构建。
下列给出的表,即坑位列表,该坑位列表实质上是实现了对具体列表的索引,形如:
上面的代码中,String字段是字符串,表示Activity坑位的坑位名,而ActivityState则为状态信息。从这个坑位列表可以看出,该坑位列表虽然可以是直接包含每个活动组件坑位的建立了映射关系的特征信息,但在该表给出的实施例中,则是通过包含一个总表和多个类型表来建立对活动组件坑位特征信息的管理。上述的代码所给出的各表,从上至下,依次为:
mStates:总表,顾名思义,所有的Activity都要存储在这张表中,以作为汇总之用。
mStatesST:表示launchMode为SingleTask的表,其注册信息可以按照如下方式进行表达:
mStatesTA:表示taskAffinity为指定值的表,taskAffinity属性表示Activity的归属,也就是Activity应该在哪个Task中,Activity与Task的吸附关系。一般情况下在同一个应用中,启动的Activity都在同一个Task中,它们在该Task中度过自己的生命周期。如果一个Activity没有显式的指明该Activity的taskAffinity,那么它的这个属性就等于Application指明的taskAffinity,如果Application也没有指明,那么该taskAffinity的值就等于包名。而Task也有自己的Affinity属性,它的值等于它的根Activity的taskAffinity的值。一开始,创建的Activity都会在创建它的Task中,并且大部分都在这里度过了它的整个生命。然而有一些情况,创建的Activity会被分配其它的Task中去,有的甚至,本来在一个Task中,之后出现了转移。因此,有必要以taskAffinity为依据形成类型表。此表的注册信息可以按照如下方式进行表达:
mStatesNR:表示launchMode为Standard(默认值)的表,其注册信息可以按照如下方式进行表达:
mStatesSI:表示launchMode为SingleInstance的表,其注册信息可以按照如下方式进行表达:
mStatesF:表示theme属性为FullScreen(全屏幕)的表,其注册信息可以按照如下方式进行表达:
mStatesT:表示theme属性为Translucent(透明背景)的表,其注册信息可以按照如下方式进行表达:
mStatesTF:表示theme属性为Translucent.FullScreen(全屏且透明)的表,其注册信息可以按照如下方式进行表达:
mStatesD:表示theme为Dialog的表,其注册信息可以按照如下方式进行表达:
mStatesSID:表示launchMode为SingleInstance、且Theme为Dialog的表,其注册信息可以按照如下方式进行表达:
以上逐一介绍了坑位列表中的总表和类型表,主要用于向读者说明坑位列表的一个实施方式,本领域技术人员应当理解,坑位列表的实现,只要建立了对所述活动组件坑位的特征信息的管理,不管其具体实现形式如何,也不管其直接还是间接包含了所述的特征信息,均能够为本领域技术人员依据本发明的精神实质而灵活运用。
如前所述,在熟知上述实现方式的基础上,通过重构Application.onCreate方法的代码,即可实现对所述坑位列表的建立。以下给出代码示例形如:
通过形如上述的代码示例的实施,最终,每一个活动组件坑位都分别创建到mStates总表以及其它类型表中,其中Containers表示Activity的“mContainerActivity”对象。
通过上述的方式,便建立起坑位列表所包括的各个子表的索引关系,由此形成一个数据架构。继而,对于每个坑位而言,需要了解其记载到坑位列表,具体是存储到各个相应表格中的特征信息的结构。每个坑位的特征信息,主要是由存在映射关系的坑位名、使用状态、待加载活动组件名称(即插件功能模块的名称)、修改使用状态时的时间戳、对活动组件的弱引用等数据项组成,必要时,也可对这些关键项进行修饰性的增减。这些特征信息项,概述如下:
(1)container:活动组件坑位对应的坑位名;
(2)state:活动组件坑位使用状态,具有以下几种标识:
Private static final int STATE_NONE=0//表示非使用状态
Private static final int STATE_REGISTERED=1//表示已分配状态
Private static final int STATE_LOADED=2//表示已加载状态
Private static final int STATE_CREATED=3//表示已创建状态
Private static final int STATE_RECYCLED=4//表示已回收状态
(3)mCN:对应的目标插件功能模块及其名称;
(4)timestamp:修改使用状态时的时间戳;
(5)ref:保留对活动组件的弱引用。
以上特征信息在可以在多种情况下按需赋值。例如mCN字段会在分配阶段进行赋值,而state情况特殊,下面分别举例说明:
1、进入主程序时,会在Application.attachBaseContext中,初始化进程的上述信息,将各个活动组件坑位的state置为STATE_NONE;
2、当插件功能模块中的待加载活动组件被分配坑位,会将state状态置为STATE_REGISTERED;
3、当待加载活动组件被类加载器classLoader加载后,活动组件坑位被返回并被加载后,会将state状态置为STATE_LOADED;
4、当待加载活动组件的onCreate方法被调用,会将相应的目标坑位的state状态置为STATE_CREATED;
5、当待加载活动组件被释放(调用Activity.onDestroy,或坑位已满,分配时),则会将state状态置为STATE_RECYCLED。
以上,详细地揭示了实现所述坑位列表的一个示例,本领域技术人员根据上述对于本构建单元12的示例性说明,足以知晓本构建单元12的具体实现及其变例。经过本构建单元12的处理,将构建出本发明所需的包含有多个活动组件坑位特征信息的坑位列表。该坑位列表也是实现本发明的活动组件进程空间分配方法和装置所必须的准备。
所述的分配单元13,用于利用坑位列表为待加载活动组件分配相适配的目标活动组件坑位。
为了构造本分配单元13,本发明进而揭示该分配单元13配备的一种活动组件进程空间分配装置,运用这一装置来对所述的坑位列表加以利用,最终为插件功能模块中的待加载活动组件分配坑位。该装置主要包括接收模块21、优选模块22以及响应模块23,以下结合图4对各个模块所实现的功能进行详细说明:
所述的接收模块21,用于接收为待加载活动组件分配活动组件坑位的请求。
同理,由于本发明的活动组件进程空间分配装置被配备给所述的分配单元13,因而,其主要利用过程思维编程成功能模块,对外接收参数以接收请求,并向请求方反馈相应的结果。基于这一原理,通过本分配装置,当主程序需要加载插件功能模块的待加载活动组件时,将由主程序或其构成部分传递待加载活动组件的相关信息给本分配装置所构造的功能模块,以便由本分配装置对其进行后续的处理。
需要指出的是,本分配装置待要进行分配的活动组件坑位,也就是本发明的调度装置所构建的活动组件坑位,因此,这些活动组件坑位即是作为主程序的宿主功能模块的Androidmanifest.xml文件中声明了注册信息并向系统注册而形成的进程空间。本分配装置更优之处在于,可以在某一个进程中,管理多个插件功能模块的待加载活动组件。
所述的优选模块22,用于利用预设的优选策略,从坑位列表中为待加载活动组件优选相适配的目标活动组件坑位。
所述的坑位列表,也即前述构建单元12所构建的坑位列表,用于存储多个预注册的活动组件坑位的特征信息。由于如前所述的示例中,坑位列表包含有总表和各种类型表,其中的总表包含有所有活动组件坑位的特征信息,其中的类型表只存储属于具有相同类型特征的活动组件坑位的特征信息,因此,在实施预设的优选策略时,可以先对类型表进行检索,在类型表未找到适配的活动组件时才在总表中进一步检索。而在实施检索时,依照前述揭示的坑位列表设计原理,相应地,也应依据活动组件的launchMode、taskAffinity和/或theme属性进行判别以确定具体相对应的类型表。
本优选模块22对所述目标活动组件坑位的优选,主要是依据其中的使用状态为依据进行。
以下揭示运用所述优选策略的流程:
本调度装置预先在PackageInfo中存储了所有ActivityInfo对象,所以可以在这里直接使用这些信息。在本优选模块22中,通过launchMode、taskAffinity、theme等属性判别与请求分配的待加载活动组件所属的类型表,开始对类型表进行检索。示例代码如下:
继而,从相应的类型表中确定相适配的目标活动组件坑位,上面的代码中,alloc方法的签名为:
其中,ai表示ActivityInfo,map就是指定的坑位列表,plugin和activity分别代表插件功能模块名称及其待加载活动组件名称。
采用如下的策略进行优选,按序进行,只要以下任何一条规则得到满足,即可直接返回结果,不必进行后续步骤:
(1)对于SingleTask和SingleInstance类型的优选,是优选查找上一个用过的实例。参阅如下代码:
如前所述,SingleTask和SingleInstance比较特殊,这两种模式系统要求Activity实例只能有一份,故必须找上一个已经打开的实例。而其它LaunchMode没有这个限制,可以使用多个实例。
比如说,二维码插件的BarcodeActivity之前已经打开过,那么若仍要打开,则在这里会做判断:首先其使用状态必须得是STATE_CREATED,并且目标插件必须是二维码,且Activity必须是对应的名称如BarcodeActivity,且还有Activity对象,如此才能直接返回该结果。否则任一条件不符合,都将进行下一步。
(2)采用未用过的坑位,参阅如下代码:
如果通过检测,该坑位未使用,则直接使用,返回结果,不进行后续步骤。
(3)采用已经用过但已经停止的,注意这里不区分launchMode,其中SI和ST这两种情况已经在之前的步骤处理过。参阅代码:
同理,如果找到,返回结果,不进行后续步骤。
(4)寻找最早的一个已经被翻译的坑位。参阅代码如下:
同理,如果找到,返回结果,不进行后续步骤。
(5)与第(4)条策略不同的是,这里即使是已被分配状态,但没有用过的坑位(这种情况比较少,通常是Activity一创建就释放或者创建失败等),这里要回收其中最早的那一个。参阅如下代码:
同理,如果找到,返回结果,不进行后续步骤。
(6)在穷举上述各种策略而未找到相适配的坑位的情况下,只能回收最早加载的那一个。参阅如下代码:
如果找到,返回结果,不进行后续步骤。
(7)同理,在以上各种策略查找均失败的情况下,只能才用最后一个策略,回收正在运行的最早的一个Activity。参阅如下代码:
经过上述的优选策略的作用,最终将获得唯一一个目标活动组件坑位,完成坑位分配。
所述的响应模块23,用于在坑位列表中标记该目标坑位的使用状态表征其已被分配,响应于该请求而提供该目标坑位。
通过前一单元获取该目标坑位之后,即可将该坑位的特征信息中的使用状态state置为STATE_REGISTERED,同时获得该坑位的坑位名Activity.mContainer,作为结果返回给请求方即可。
通过上述本发明提供的活动组件进程空间分配装置的执行,可以优选出一个与待加载活动组件相适配的目标活动组件坑位。获得这个目标坑位后,便可以在相关返回的信息的基础上,由本发明的调度装置做后续处理。
所述的加载单元14,用于将该待加载活动组件加载到目标坑位所对应的进程空间中运行。
基于前述各单元的实施结果,本发明继而借助加载单元14所具有的如下具体构造将待加载活动组件加载到相应的进程空间中运行:
获取模块,用于从所述坑位列表中获得已被分配的目标活动组件坑位。
如前所述,在所述分配单元13中,通过本发明提供的分配装置可最终确定唯一一个目标坑位,并且返回该目标坑位的信息。这些信息主要包含坑位名称,确定坑位名称之后,即可通过类加载器加载待加载活动组件。
由于在所述分配单元13中,已经将目标坑位的使用状态state标记为STATE_REGISTERED并返回了坑位名,因此,在本获取模块中,只需要以该标记对坑位列表(具体到某个类型表)进行查找即可。参考如下代码:
创建模块,用于运行重构的类加载器为分配了坑位的待加载活动组件确定类对象。
本发明所称的类加载器,是通过重构系统的ClassLoader实现的。重构类加载器的目的,是希望在主程序启动时改变系统生成新类的方法,从而确保正确加载待加载活动组件,使其运行于目标坑位所指代的进程空间。
一种现有技术中,常通过自己生成DexClassLoader,在插件启动时调用来实现,其缺点显而易见,就是调用起来非常不直观,必须得先调用DexClassLoader的指定方法来实现。如下所示:
现有:XXX my=mDexClassLoader.findClass(XXX).newInstance();
本作:XXX my=new XXX();
另一种现有技术中,通过替换Thread的contextClassLoader方式来实现。这一方式最大的问题是不支持Activity、Service、AIDL等场景,这些地方系统默认会使用PackageInfo的ClassLoader,而非Thread的,使用场景受到严重的限制。
本发明的重构的ClassLoader将实现对系统的类加载器的完全替换,具体是通过替换PackageInfo的ClassLoader,来确保替换无死角,不仅Thread可以使用,连Activity、Service等组件都能使用自定义的ClassLoader来实现加载,其应用场景更为广泛,并且调用过程非常直观,调用者无需考虑任何替换关系,直接使用即可。
实现自定义类加载器的方法,可以参照如下步骤进行:
首先,每一个进程启动时,都会调用Application对象,该对象也可以通过继承的方式自定义。系统会最先调用Application.attachBaseContext方法,因此,适宜在此处导入重构的ClassLoader。
然后,获取PackageInfo。在这一过程中,按照如下子步骤实现:
(1)首先需要获取ContextWrapper对象。也即:反射获取Application对象中的mBase字段即可。所获取的对象存好备用。
(2)获取mPackageInfo。
获取的mBase对象,在不同的Android系统上会代表着不同的类型,如Android 2.1为ApplicationContext,而Android 2.2则为ContextImpl,在Android 2.3及以上则为AppContextImpl。但不管是哪一个,都有共同的特点,即都有一个名叫“mPackageInfo”字段,直接反射获取mBase对象中的mPackageInfo字段,即可获得PackageInfo对象。
以上两条可用代码来说明:
继而,生成自定义的ClassLoader对象。
只要自定义的类继承了ClassLoader或其子类对象,就意味着完成了自定义操作。在这个基础上,本领域技术人员可以理解,可以做大量和插件功能模块有关的工作。
除了自定义,还必须覆写ClassLoader中的所有方法,每一个方法最终都应该指向之前的ClassLoader,由此即可确保ClassLoader的成功重构和正常使用。以不添加任何自定义功能的代码示例如下:
如上所述,mBase就是之前的ClassLoader。在处理完自定义事件后,如有必要,则需要调用mBase的对应方法。
最后,替换PackageInfo的mClassLoader
将之前存留好的mPackageInfo对象取出,通过反射来设置mClassLoader字段为上述生成的自定义ClassLoader对象即可。
以代码为例,在获取mPackageInfo的代码示例的“……”省略部分可以插入如下的示例代码:
由此,替换系统的ClassLoader的过程结束,完成了ClassLoader的自定义重构。由于系统的ClassLoader被替换成了自定义的ClassLoader,根据它的使用场景和性质,一般而言,只要有获取类信息、生成新类、调用Native方法等情况,就一定会通过该自定义ClassLoader来加载。
因此,通过上述实现的自定义ClassLoader,继承之DexClassLoader,其findClass方法也被重构,在findClass中实现为所述的待加载活动组件查找对象。一旦找到了目标坑位对象的名称,接下来只需要将当前插件功能模块的ClassLoader获取到,然后执行invoke方法,即可获取该插件的Class对象。
运行模块,用于运行指令打开目标坑位以令待加载活动组件加载于进程空间中运行。
具体而言,由于进程空间既定,且待加载活动组件的类对象也已经找到,接下只需要对两者进行拼接即可。首先通过ComponentName(系统Intent的固有功能)对象传递目标坑位的进程空间,利用该对象构造Intent,然后以context.startActivity方法调用该Intent,即可打开目标坑位,从而使待加载活动组件加载于既定进程空间中运行。
在本发明的其他实施例中,用于所述待加载活动组件进行运行的进程空间,可以经过一个优选的步骤,以便在前述分配目标坑位之前提供一个既定且优选的进程空间。
可见,本发明提供的活动组件调度装置,可以实现对待加载活动组件的灵活调度,使得待加载活动组件可以以插件功能模块的方式独立于作为主程序的宿主功能模块之外灵活添加。
进一步,可以将本发明的活动组件调度装置实例化成程序,附加到作为主程序使用的宿主功能模块中,在主程序运行时,运行本调度装置,对所述插件功能模块所包含的活动组件实施调度,使该活动组件运行于由宿主功能模块所创建的进程空间中。这种主程序的升级将变得更为简易和省流量,理论上只要不涉及主程序的框架修改,主程序便可以永不升级。
而本发明提供的活动组件进程空间分配装置,则实现了基于单进程情况下加载待加载活动组件的高效管理,使得对这种待加载活动组件的灵活添加、升级成为可能。
以上所述仅是本发明的部分实施方式,应当指出,对于本技术领域的普通技术人员来说,在不脱离本发明原理的前提下,还可以做出若干改进和润饰,这些改进和润饰也应视为本发明的保护范围。

Claims (10)

1.一种活动组件调度方法,其特征在于,包括如下步骤:
提供给系统预注册多个活动组件坑位;
构建包含所述多个活动组件坑位的特征信息的坑位列表;
利用坑位列表为待加载活动组件分配相适配的目标活动组件坑位;
将该待加载活动组件加载到目标坑位所对应的进程空间中运行。
2.根据权利要求1所述的活动组件调度方法,其特征在于:注册活动组件坑位的步骤中,以实施本方法的宿主功能模块的配置文件中声明的用于表达预留的活动组件的注册信息向系统进行注册,以构造所述活动组件坑位。
3.根据权利要求2所述的活动组件调度方法,其特征在于:所述配置文件中活动组件的注册信息中的包名属性包含有用于识别不同进程空间的特征字符。
4.根据权利要求1所述的活动组件调度方法,其特征在于:构建坑位列表的步骤中,在实施本方法的宿主功能模块启动时运行用于添加所述活动组件坑位的特征信息的代码指令以实现所述坑位列表的构建。
5.根据权利要求1所述的活动组件调度方法,其特征在于:所述的待加载活动组件为独立于实施本方法的宿主功能模块的插件功能模块,该插件功能模块包含实现该待加载活动组件的代码文件和用于声明该活动组件的注册信息的配置文件。
6.根据权利要求1所述的活动组件调度方法,其特征在于,分配目标坑位时,利用预设的优选策略从坑位列表中选定与待加载活动组件相适配的唯一一个活动组件坑位以完成分配。
7.根据权利要求1所述的活动组件调度方法,其特征在于,所述加载待加载活动组件的步骤中,包括如下具体步骤:
获得已被分配的目标活动组件坑位;
运行重构的类加载器为分配了坑位的待加载活动组件确定类对象;
运行指令打开目标坑位以令待加载活动组件加载于进程空间中运行。
8.一种活动组件调度装置,其特征在于,包括:
注册单元,其提供给系统预注册多个活动组件坑位;
构建单元,用于构建包含所述多个活动组件坑位的坑位列表;
分配单元,用于利用坑位列表为待加载活动组件分配相适配的目标活动组件坑位;
加载单元,用于将该待加载活动组件加载到目标坑位所对应的进程空间中运行。
9.一种程序控制方法,其特征在于,该方法利用宿主功能模块实现了如权利要求1至7中任意一项所述的活动组件调度方法,并以该方法对所述插件功能模块所包含的活动组件实施调度,使该活动组件运行于由宿主功能模块所创建的进程空间中。
10.一种程序控制装置,其特征在于,其包括宿主功能模块和插件功能模块,所述宿主功能模块包含有如权利要求8所述的活动组件调度装置,所述宿主功能模块被配置为利用该活动组件调度装置实现对所述插件功能模块所包含的活动组件的调度,使该活动组件运行于由宿主功能模块所创建的进程空间中。
CN201510119622.0A 2015-03-18 2015-03-18 程序控制方法与活动组件调度方法及其相应的装置 Active CN104699537B (zh)

Priority Applications (1)

Application Number Priority Date Filing Date Title
CN201510119622.0A CN104699537B (zh) 2015-03-18 2015-03-18 程序控制方法与活动组件调度方法及其相应的装置

Applications Claiming Priority (1)

Application Number Priority Date Filing Date Title
CN201510119622.0A CN104699537B (zh) 2015-03-18 2015-03-18 程序控制方法与活动组件调度方法及其相应的装置

Publications (2)

Publication Number Publication Date
CN104699537A true CN104699537A (zh) 2015-06-10
CN104699537B CN104699537B (zh) 2017-05-31

Family

ID=53346700

Family Applications (1)

Application Number Title Priority Date Filing Date
CN201510119622.0A Active CN104699537B (zh) 2015-03-18 2015-03-18 程序控制方法与活动组件调度方法及其相应的装置

Country Status (1)

Country Link
CN (1) CN104699537B (zh)

Cited By (10)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
CN105824623A (zh) * 2016-03-14 2016-08-03 广州趣丸网络科技有限公司 一种Android应用热修复的方法和装置
CN107193587A (zh) * 2017-04-21 2017-09-22 北京奇虎科技有限公司 一种实现插件的多任务栈的方法和装置
CN107239297A (zh) * 2017-04-21 2017-10-10 北京奇虎科技有限公司 一种插件的多进程管理方法和装置
CN107944266A (zh) * 2017-12-15 2018-04-20 北京奇虎科技有限公司 组件管理方法、装置及移动终端
CN108038370A (zh) * 2017-12-28 2018-05-15 北京奇虎科技有限公司 沙箱活动组件进程空间分配方法、分配装置和分配终端
CN108595205A (zh) * 2018-05-09 2018-09-28 四川华创世纪科技有限公司 一种通过流程引擎配置快速开发新业务型软件程序的方法
CN110688171A (zh) * 2019-09-26 2020-01-14 深圳市奋源科技有限公司 应用程序的插件化配置方法、装置、设备以及存储介质
CN111443959A (zh) * 2020-03-27 2020-07-24 北京金山云网络技术有限公司 任务的执行方法、装置和服务器
CN113326035A (zh) * 2020-06-29 2021-08-31 阿里巴巴集团控股有限公司 数据处理方法、装置、电子设备及计算机存储介质
CN114153513A (zh) * 2020-09-04 2022-03-08 华为技术有限公司 组件启动方法及装置

Families Citing this family (1)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
CN109144692A (zh) * 2018-07-16 2019-01-04 北京奇虎科技有限公司 一种用于分配进程的方法、装置及终端

Citations (3)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
CN102722370A (zh) * 2012-05-24 2012-10-10 南京华设科技股份有限公司 Android模块化开发方法
CN103617078A (zh) * 2013-11-22 2014-03-05 北京奇虎科技有限公司 活动组件的管理方法及装置
CN104391649A (zh) * 2014-12-05 2015-03-04 上海斐讯数据通信技术有限公司 一种多活动触屏消息控制方法及系统

Patent Citations (3)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
CN102722370A (zh) * 2012-05-24 2012-10-10 南京华设科技股份有限公司 Android模块化开发方法
CN103617078A (zh) * 2013-11-22 2014-03-05 北京奇虎科技有限公司 活动组件的管理方法及装置
CN104391649A (zh) * 2014-12-05 2015-03-04 上海斐讯数据通信技术有限公司 一种多活动触屏消息控制方法及系统

Cited By (16)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
CN105824623B (zh) * 2016-03-14 2019-03-26 广州趣丸网络科技有限公司 一种Android应用热修复的方法和装置
CN105824623A (zh) * 2016-03-14 2016-08-03 广州趣丸网络科技有限公司 一种Android应用热修复的方法和装置
CN107193587A (zh) * 2017-04-21 2017-09-22 北京奇虎科技有限公司 一种实现插件的多任务栈的方法和装置
CN107239297A (zh) * 2017-04-21 2017-10-10 北京奇虎科技有限公司 一种插件的多进程管理方法和装置
CN107239297B (zh) * 2017-04-21 2020-10-20 北京奇虎科技有限公司 一种插件的多进程管理方法和装置
CN107193587B (zh) * 2017-04-21 2020-10-27 北京奇虎科技有限公司 一种实现插件的多任务栈的方法和装置
CN107944266A (zh) * 2017-12-15 2018-04-20 北京奇虎科技有限公司 组件管理方法、装置及移动终端
CN108038370A (zh) * 2017-12-28 2018-05-15 北京奇虎科技有限公司 沙箱活动组件进程空间分配方法、分配装置和分配终端
CN108595205A (zh) * 2018-05-09 2018-09-28 四川华创世纪科技有限公司 一种通过流程引擎配置快速开发新业务型软件程序的方法
CN110688171B (zh) * 2019-09-26 2023-11-10 深圳市奋源科技有限公司 应用程序的插件化配置方法、装置、设备以及存储介质
CN110688171A (zh) * 2019-09-26 2020-01-14 深圳市奋源科技有限公司 应用程序的插件化配置方法、装置、设备以及存储介质
CN111443959A (zh) * 2020-03-27 2020-07-24 北京金山云网络技术有限公司 任务的执行方法、装置和服务器
CN111443959B (zh) * 2020-03-27 2023-04-25 北京金山云网络技术有限公司 任务的执行方法、装置和服务器
CN113326035A (zh) * 2020-06-29 2021-08-31 阿里巴巴集团控股有限公司 数据处理方法、装置、电子设备及计算机存储介质
CN114153513A (zh) * 2020-09-04 2022-03-08 华为技术有限公司 组件启动方法及装置
WO2022048462A1 (zh) * 2020-09-04 2022-03-10 华为技术有限公司 组件启动方法及装置

Also Published As

Publication number Publication date
CN104699537B (zh) 2017-05-31

Similar Documents

Publication Publication Date Title
CN104699537A (zh) 程序控制方法与活动组件调度方法及其相应的装置
CN105094922A (zh) 应用程序免安装运行控制方法及其装置
CN104699536A (zh) 活动组件进程空间分配方法及其相应的装置
CN101833465B (zh) 一种支持应用程序动态加载运行的嵌入式系统
CN111324571B (zh) 一种容器集群管理方法、装置及系统
US20080270617A1 (en) Method, System and Article of Manufacture for Providing Connections and Connection Aliases Descriptors by Services and Libraries Archives
CN104714828A (zh) 应用安装、运行方法及装置
CN102855152B (zh) 升级应用程序中资源文件的方法及系统
US8176114B2 (en) Distributed cross-application server deployment
US20100313197A1 (en) System and method for operating domain profile using database in core framework for sdr mobile terminals
CN113296792B (zh) 存储方法、装置、设备、存储介质和系统
CN102682014A (zh) 在浏览器上实现的开放式插件管理平台及插件管理方法
CN102323879A (zh) 完整网络中间件运行支撑平台及异构中间件的集成方法
CN103473696A (zh) 一种收集、分析和分发网络商业信息的方法和系统
CN104750528A (zh) 一种Android程序中的组件管理方法和装置
CN100549957C (zh) 一种类装载隔离的方法及一种类装载隔离的装置
CN106569880B (zh) 一种Android应用间动态共享资源的方法及系统
CN104219078A (zh) 一种多运行时环境数据的处理方法和装置
CN105516154A (zh) 应用于SEAndroid系统的安全策略配置方法及装置
CN110134428A (zh) 一种安全防护方法及装置
CN108363612A (zh) 基于类装载器实现的j2ee模块热部署及调用信息统计方法
CN101490645A (zh) 用以设备虚拟化的方法及设备
CN103176809A (zh) 应用升级方法及系统
CN107977572B (zh) 一种应用程序运行方法和装置、智能终端
CN103647811A (zh) 一种实现应用访问后台服务的方法和装置

Legal Events

Date Code Title Description
C06 Publication
PB01 Publication
C10 Entry into substantive examination
SE01 Entry into force of request for substantive examination
GR01 Patent grant
GR01 Patent grant
TR01 Transfer of patent right

Effective date of registration: 20220714

Address after: Room 801, 8th floor, No. 104, floors 1-19, building 2, yard 6, Jiuxianqiao Road, Chaoyang District, Beijing 100015

Patentee after: BEIJING QIHOO TECHNOLOGY Co.,Ltd.

Address before: 100088 room 112, block D, 28 new street, new street, Xicheng District, Beijing (Desheng Park)

Patentee before: BEIJING QIHOO TECHNOLOGY Co.,Ltd.

Patentee before: Qizhi software (Beijing) Co.,Ltd.

TR01 Transfer of patent right