本發(fā)明涉及計算機(jī)技術(shù)領(lǐng)域,特別是一種插件加載方法及裝置。
背景技術(shù):
IBinder是遠(yuǎn)程對象的基本接口,是為高性能而設(shè)計的輕量級遠(yuǎn)程調(diào)用機(jī)制的核心部分,Android的遠(yuǎn)程調(diào)用(即跨進(jìn)程調(diào)用)就是通過IBinder實現(xiàn)的。但它不僅用于遠(yuǎn)程調(diào)用,也可以用于進(jìn)程內(nèi)調(diào)用。這個接口定義了與遠(yuǎn)程對象交互的協(xié)議。
IBinder的主要API(Application Program Interface,應(yīng)用程序接口)是transact(),與它對應(yīng)另一方法是Binder.onTransact()。第一個方法用于本端向遠(yuǎn)端的IBinder對象發(fā)送發(fā)出調(diào)用,第二個方法用于本端的遠(yuǎn)程對象能夠響應(yīng)接收到的調(diào)用。IBinder的API都是同步執(zhí)行的,比如transact()直到對方的Binder.onTransact()方法調(diào)用完成后才返回。調(diào)用發(fā)生在進(jìn)程內(nèi)時無疑是這樣的,而在進(jìn)程間時,在IPC的幫助下,也是同樣的效果。
相關(guān)技術(shù)中,可以采用Service的方式來獲取IBinder對象,其優(yōu)點是可以充分利用Service和IBinder的特性,但缺點也顯而易見:
1)此方法是異步操作,每次bindService完成后,必須等待onServiceConnection回調(diào)后才能做下一步,這就需要在回調(diào)時記住上次操作的內(nèi)容等,開發(fā)起來十分繁瑣,且容易出錯;
2)Service坑有限,無論是原來手機(jī)衛(wèi)士的方案,還是DroidPlugin,要使用插件Service就需要申請多個“坑位”,一旦坑位不足,則會出現(xiàn)崩潰、找錯Service等嚴(yán)重問題;
3)手機(jī)衛(wèi)士的功能場景較多,這種插件間通信的方式是經(jīng)常用到的,顯然開發(fā)越輕量,效率越高,但單純只用Service方案的話,還無法滿足這一點。
在其它相關(guān)技術(shù)中,可以采用Socket通信(或類似形式)來“模擬”同步過程,具體做法是建立兩個Socket,一個負(fù)責(zé)發(fā)送消息,一個負(fù)責(zé)接收消息。其中在發(fā)送消息方,在發(fā)出消息后開始讀取緩存,以此進(jìn)入阻塞狀態(tài),接收方收到消息后再發(fā)送給發(fā)送方,此時阻塞態(tài)消失,讀取消息。此方案的優(yōu)點是可做到同步進(jìn)行,且傳輸媒介較為靈活(畢竟全是二進(jìn)制)。然而,其缺點比單純用Service還要明顯:
(1)需要建立兩個Socket進(jìn)行通信,操作極其繁瑣;
(2)一旦接收方進(jìn)程意外終止,作為發(fā)送方無法立即知道情況,只能等待超時結(jié)束后才能繼續(xù),但問題是,超時既有可能是進(jìn)程被退出,也有可能是出錯;
(3)信道采用二進(jìn)制,編寫起來非常不直觀;
(4)Socket通信在效率上不及IBinder;
(5)Socket通信存在一定的安全隱患。
綜上所述,發(fā)明人發(fā)現(xiàn)亟待提供一種快速、同步地獲取插件的IBinder對象的方案。
技術(shù)實現(xiàn)要素:
鑒于上述問題,提出了本發(fā)明以便提供一種克服上述問題或者至少部分地解決上述問題的插件加載方法及相應(yīng)的裝置。
依據(jù)本發(fā)明的一方面,提供了一種插件加載方法,包括:
當(dāng)宿主程序接收到加載插件的請求時,調(diào)用插件加載方法對目標(biāo)插件進(jìn)行加載;
在加載目標(biāo)插件的過程中,創(chuàng)建目標(biāo)插件的入口類的對象;
利用所述入口類的對象,調(diào)用所述入口類中的指定方法緩存目標(biāo)插件的接口的對象。
可選地,目標(biāo)插件的接口的對象用于獲取IBinder對象,所述方法還包括:
當(dāng)外部調(diào)用方需要獲取目標(biāo)插件的IBinder對象時,調(diào)用預(yù)先定義的預(yù)定義類中的指定方法;
利用所述預(yù)定義類中的指定方法,從所述入口類中的指定方法中獲取目標(biāo)插件的接口的對象;
調(diào)用目標(biāo)插件的接口的對象中的指定方法獲取IBinder對象。
可選地,在調(diào)用目標(biāo)插件的接口的對象中的指定方法獲取IBinder對象之后,所述方法還包括:
利用獲取的IBinder對象進(jìn)行與所述目標(biāo)插件進(jìn)行通信。
可選地,所述目標(biāo)插件的入口類為Entry類。
可選地,所述目標(biāo)插件的接口為IPlugin接口,所述IPlugin接口的對象為mPlugin對象。
可選地,所述方法還包括:
利用所述入口類的對象,反射獲取所述入口類中的指定方法。
可選地,當(dāng)外部調(diào)用方需要獲取目標(biāo)插件的IBinder對象時,調(diào)用預(yù)先定義的預(yù)定義類中的指定方法,包括:
當(dāng)外部調(diào)用方需要獲取目標(biāo)插件的IBinder對象時,判斷所述外部調(diào)用方所在當(dāng)前進(jìn)程與即將返回所述目標(biāo)插件的IBinder對象的接收方所在目標(biāo)進(jìn)程是否為同一進(jìn)程;
若是,則直接調(diào)用預(yù)先定義的預(yù)定義類中的指定方法。
可選地,所述方法還包括:
若所述外部調(diào)用方所在當(dāng)前進(jìn)程與即將返回所述目標(biāo)插件的IBinder對象的接收方所在目標(biāo)進(jìn)程不為同一進(jìn)程,則通過所述目標(biāo)進(jìn)程中的Provider獲取宿主程序的接口的對象;
由宿主程序的接口的對象中的指定方法,調(diào)用預(yù)先定義的預(yù)定義類中的指定方法。
可選地,所述目標(biāo)進(jìn)程為常駐進(jìn)程。
可選地,所述宿主程序的接口為IpluginHost接口。
可選地,調(diào)用目標(biāo)插件的接口的對象中的指定方法獲取IBinder對象,包括:
調(diào)用目標(biāo)插件的接口的對象中的指定方法;
根據(jù)module名字返回對應(yīng)的IBinder對象。
可選地,當(dāng)宿主程序接收到加載插件的指令時,調(diào)用插件加載方法對目標(biāo)插件進(jìn)行加載,包括:
將插件加載事件拆分為獨立的至少一個加載階段,其中,各個加載階段對應(yīng)不同的插件內(nèi)容;
當(dāng)宿主程序接收到加載插件的指令時,確定所述請求對應(yīng)的目標(biāo)加載階段;
加載所述目標(biāo)加載階段對應(yīng)的插件內(nèi)容。
可選地,所述至少一個加載階段包括下列至少之一:
插件信息的獲取、插件資源的加載、插件代碼的加載。
依據(jù)本發(fā)明的另一方面,還提供了一種插件加載裝置,包括:
加載模塊,適于當(dāng)宿主程序接收到加載插件的指令時,調(diào)用插件加載方法對目標(biāo)插件進(jìn)行加載;
創(chuàng)建模塊,適于在加載目標(biāo)插件的過程中,創(chuàng)建目標(biāo)插件的入口類的對象;
緩存模塊,適于利用所述入口類的對象,調(diào)用所述入口類中的指定方法緩存目標(biāo)插件的接口的對象。
可選地,目標(biāo)插件的接口的對象用于獲取IBinder對象,所述裝置還包括:
調(diào)用模塊,適于當(dāng)外部調(diào)用方需要獲取目標(biāo)插件的IBinder對象時,調(diào)用預(yù)先定義的預(yù)定義類中的指定方法;
第一獲取模塊,適于利用所述預(yù)定義類中的指定方法,從所述入口類中的指定方法中獲取目標(biāo)插件的接口的對象;
第二獲取模塊,適于調(diào)用目標(biāo)插件的接口的對象中的指定方法獲取IBinder對象。
可選地,所述裝置還包括:
通信模塊,適于在所述第二獲取模塊調(diào)用目標(biāo)插件的接口的對象中的指定方法獲取IBinder對象之后,利用獲取的IBinder對象進(jìn)行與所述目標(biāo)插件進(jìn)行通信。
可選地,所述目標(biāo)插件的入口類為Entry類。
可選地,所述目標(biāo)插件的接口為IPlugin接口,所述IPlugin接口的對象為mPlugin對象。
可選地,所述裝置還包括:
第三獲取模塊,適于利用所述入口類的對象,反射獲取所述入口類中的指定方法。
可選地,所述調(diào)用模塊還適于:
當(dāng)外部調(diào)用方需要獲取目標(biāo)插件的IBinder對象時,判斷所述外部調(diào)用方所在當(dāng)前進(jìn)程與即將返回所述目標(biāo)插件的IBinder對象的接收方所在目標(biāo)進(jìn)程是否為同一進(jìn)程;
若是,則直接調(diào)用預(yù)先定義的預(yù)定義類中的指定方法。
可選地,所述調(diào)用模塊還適于:
若所述外部調(diào)用方所在當(dāng)前進(jìn)程與即將返回所述目標(biāo)插件的IBinder對象的接收方所在目標(biāo)進(jìn)程不為同一進(jìn)程,則通過所述目標(biāo)進(jìn)程中的Provider獲取宿主程序的接口的對象;
由宿主程序的接口的對象中的指定方法,調(diào)用預(yù)先定義的預(yù)定義類中的指定方法。
可選地,所述目標(biāo)進(jìn)程為常駐進(jìn)程。
可選地,所述宿主程序的接口為IpluginHost接口。
可選地,所述第二獲取模塊還適于:
調(diào)用目標(biāo)插件的接口的對象中的指定方法;
根據(jù)module名字返回對應(yīng)的IBinder對象。
可選地,所述加載模塊還適于:
將插件加載事件拆分為獨立的至少一個加載階段,其中,各個加載階段對應(yīng)不同的插件內(nèi)容;
當(dāng)宿主程序接收到加載插件的指令時,確定所述請求對應(yīng)的目標(biāo)加載階段;
加載所述目標(biāo)加載階段對應(yīng)的插件內(nèi)容。
可選地,所述至少一個加載階段包括下列至少之一:
插件信息的獲取、插件資源的加載、插件代碼的加載。
本發(fā)明實施例提供的技術(shù)方案,當(dāng)宿主程序接收到加載插件的請求時,調(diào)用插件加載方法對目標(biāo)插件進(jìn)行加載,在加載目標(biāo)插件的過程中可以創(chuàng)建目標(biāo)插件的入口類的對象,并利用入口類的對象,調(diào)用入口類中的指定方法緩存目標(biāo)插件的接口的對象。由于該目標(biāo)插件的接口的對象能夠用于獲取IBinder對象,因而當(dāng)外部調(diào)用方需要獲取目標(biāo)插件的IBinder對象時,可以直接獲取緩存的目標(biāo)插件的接口的對象,并利用該目標(biāo)插件的接口的對象來獲取IBinder對象,進(jìn)而可以利用獲取的IBinder對象與目標(biāo)插件進(jìn)行通信。由此可見,本發(fā)明實施例能夠充分利用Android系統(tǒng)的邏輯來實現(xiàn)在插件中快速、同步地獲取IBinder對象,實現(xiàn)進(jìn)程內(nèi)或進(jìn)程間的通信。
上述說明僅是本發(fā)明技術(shù)方案的概述,為了能夠更清楚了解本發(fā)明的技術(shù)手段,而可依照說明書的內(nèi)容予以實施,并且為了讓本發(fā)明的上述和其它目的、特征和優(yōu)點能夠更明顯易懂,以下特舉本發(fā)明的具體實施方式。
根據(jù)下文結(jié)合附圖對本發(fā)明具體實施例的詳細(xì)描述,本領(lǐng)域技術(shù)人員將會更加明了本發(fā)明的上述以及其他目的、優(yōu)點和特征。
附圖說明
通過閱讀下文優(yōu)選實施方式的詳細(xì)描述,各種其他的優(yōu)點和益處對于本領(lǐng)域普通技術(shù)人員將變得清楚明了。附圖僅用于示出優(yōu)選實施方式的目的,而并不認(rèn)為是對本發(fā)明的限制。而且在整個附圖中,用相同的參考符號表示相同的部件。在附圖中:
圖1示出了根據(jù)本發(fā)明一實施例的插件加載方法的流程圖;
圖2示出了根據(jù)本發(fā)明一個實施例的插件加載裝置的結(jié)構(gòu)示意圖;以及
圖3示出了根據(jù)本發(fā)明另一個實施例的插件加載裝置的結(jié)構(gòu)示意圖。
具體實施方式
下面將參照附圖更詳細(xì)地描述本公開的示例性實施例。雖然附圖中顯示了本公開的示例性實施例,然而應(yīng)當(dāng)理解,可以以各種形式實現(xiàn)本公開而不應(yīng)被這里闡述的實施例所限制。相反,提供這些實施例是為了能夠更透徹地理解本公開,并且能夠?qū)⒈竟_的范圍完整的傳達(dá)給本領(lǐng)域的技術(shù)人員。
為解決上述技術(shù)問題,本發(fā)明實施例提供了一種插件加載方法。圖1示出了根據(jù)本發(fā)明一實施例的插件加載方法的流程圖。如圖1所示,該方法至少包括以下步驟S102至步驟S106。
步驟S102,當(dāng)宿主程序接收到加載插件的請求時,調(diào)用插件加載方法對目標(biāo)插件進(jìn)行加載。
步驟S104,在加載目標(biāo)插件的過程中,創(chuàng)建目標(biāo)插件的入口類的對象。
步驟S106,利用入口類的對象,調(diào)用入口類中的指定方法緩存目標(biāo)插件的接口的對象。
本發(fā)明實施例提供的技術(shù)方案,當(dāng)宿主程序接收到加載插件的請求時,調(diào)用插件加載方法對目標(biāo)插件進(jìn)行加載,在加載目標(biāo)插件的過程中可以創(chuàng)建目標(biāo)插件的入口類的對象,并利用入口類的對象,調(diào)用入口類中的指定方法緩存目標(biāo)插件的接口的對象。由于該目標(biāo)插件的接口的對象能夠用于獲取IBinder對象,因而當(dāng)外部調(diào)用方需要獲取目標(biāo)插件的IBinder對象時,可以直接獲取緩存的目標(biāo)插件的接口的對象,并利用該目標(biāo)插件的接口的對象來獲取IBinder對象,進(jìn)而可以利用獲取的IBinder對象與目標(biāo)插件進(jìn)行通信。由此可見,本發(fā)明實施例能夠充分利用Android系統(tǒng)的邏輯來實現(xiàn)在插件中快速、同步地獲取IBinder對象,實現(xiàn)進(jìn)程內(nèi)或進(jìn)程間的通信。
上文步驟S102中當(dāng)宿主程序接收到加載插件的請求時,調(diào)用插件加載方法對目標(biāo)插件進(jìn)行加載,本發(fā)明實施例提供了一種可選的方案,即,將插件加載事件拆分為獨立的至少一個加載階段,其中,各個加載階段對應(yīng)不同的插件內(nèi)容;當(dāng)宿主程序接收到加載插件的指令時,確定請求對應(yīng)的目標(biāo)加載階段;進(jìn)而加載目標(biāo)加載階段對應(yīng)的插件內(nèi)容。這里,至少一個加載階段可以包括插件信息的獲取(即Info)、插件資源的加載(即Res)、插件代碼的加載(即Dex)。在實際應(yīng)用中,Info是最小單元,若要加載Res,則必須先加載Info;若要加載Dex,則必須先依次加載Info和Res。舉例來說,外界調(diào)用load進(jìn)行插件加載,TYPE表示要加載到哪個階段(Info、Res和Dex)。同時調(diào)用loadInfo先進(jìn)行Info的加載。loadInfo成功且TYPE為Info,表示只為加載Info,返回;loadRes成功且TYPE為Res,表示只為加載Info和Res,返回;loadDex成功且TYPE為Dex,表示需全部加載,直接返回。
在本發(fā)明的可選實施例中,當(dāng)目標(biāo)插件的接口的對象用于獲取IBinder對象時,則當(dāng)外部調(diào)用方需要獲取目標(biāo)插件的IBinder對象時,調(diào)用預(yù)先定義的預(yù)定義類中的指定方法,進(jìn)而利用預(yù)定義類中的指定方法,從入口類中的指定方法中獲取目標(biāo)插件的接口的對象,從而可以調(diào)用目標(biāo)插件的接口的對象中的指定方法獲取IBinder對象。
進(jìn)一步地,在調(diào)用目標(biāo)插件的接口的對象中的指定方法獲取IBinder對象之后,可以利用獲取的IBinder對象進(jìn)行與目標(biāo)插件進(jìn)行通信,來實現(xiàn)相應(yīng)的功能或任務(wù)。
上文提及的插件的入口類可以為Entry類。插件的入口還可以如Activity、Service、Provider、Receiver和Application這五大入口。然而,Entry是插件里最早被調(diào)用的,它類似于Android的Dalvik.main,是整個插件最早入口的地方,適合在其中做初始化、緩存接口等操作。
進(jìn)一步地,調(diào)用Entry類中的指定方法create方法來緩存插件的接口的對象,該插件的接口最終交回宿主程序,由宿主程序進(jìn)行調(diào)度,實現(xiàn)宿主程序和插件之間的聯(lián)動。這里,插件的接口可以為IPlugin接口,IPlugin接口的對象可以為mPlugin對象。IPlugin接口中可以聲明插件的宿主、名字、描述、作者、版本等信息,以及UI工具欄、菜單等資源,并且可以根據(jù)需要進(jìn)行添加或者刪減。
在上文步驟S104利用入口類的對象,調(diào)用入口類中的指定方法緩存目標(biāo)插件的接口的對象之前,本發(fā)明實施例還可以利用入口類的對象,反射獲取入口類中的指定方法。
進(jìn)一步地,上文提及,當(dāng)外部調(diào)用方需要獲取目標(biāo)插件的IBinder對象時,調(diào)用預(yù)先定義的預(yù)定義類中的指定方法,本發(fā)明實施例提供了一種可選的方案,在該方案中,當(dāng)外部調(diào)用方需要獲取目標(biāo)插件的IBinder對象時,可以判斷外部調(diào)用方所在當(dāng)前進(jìn)程與即將返回目標(biāo)插件的IBinder對象的接收方所在目標(biāo)進(jìn)程是否為同一進(jìn)程;若是,則直接調(diào)用預(yù)先定義的預(yù)定義類中的指定方法;反之,若否,則通過目標(biāo)進(jìn)程中的Provider獲取宿主程序的接口的對象,進(jìn)而由宿主程序的接口的對象中的指定方法,調(diào)用預(yù)先定義的預(yù)定義類中的指定方法。
例如,預(yù)先定義的預(yù)定義類為PluginFactory類,該類是針對插件的對外入口類,該類的指定方法為query,定義該query方法用于快速獲取IBinder對象。在本發(fā)明的可選實施例中,目標(biāo)進(jìn)程可以為常駐進(jìn)程。此外,宿主程序的接口可以為IPluginHost接口,在這里向插件提供必要的宿主函數(shù)或資源,如文件對象、數(shù)據(jù)庫的連接對象等等。這樣,每一個插件都可以通過Host參數(shù)來訪問宿主程序的資源或者函數(shù)。
上文提及的調(diào)用目標(biāo)插件的接口的對象中的指定方法獲取IBinder對象,本發(fā)明實施例提供了一種可選的方案,即,調(diào)用目標(biāo)插件的接口的對象中的指定方法,進(jìn)而根據(jù)module名字返回對應(yīng)的IBinder對象。
在本發(fā)明的可選實施例中,在步驟S102創(chuàng)建插件的入口類的對象之后,還可以定義入口類中的指定方法返回表示加載失敗的指定值(如,null等)。從而,在利用預(yù)定義類中的指定方法,從入口類中的指定方法中獲取目標(biāo)插件的接口的對象時,若從入口類中的指定方法中未獲取到目標(biāo)插件的接口的對象,并返回該指定值,則確定插件加載失敗。
在一具體實施例中,Main Client為“宿主程序”部分,Plugin為“插件內(nèi)部”部分,而Android System則為“系統(tǒng)API”,這里API是操作系統(tǒng)留給應(yīng)用程序的一個調(diào)用接口,應(yīng)用程序通過調(diào)用操作系統(tǒng)的API而使操作系統(tǒng)去執(zhí)行應(yīng)用程序的命令或動作。在Main Client中定義PluginFactory、PluginLoader類,在Plugin中修改Entry類,下面將詳細(xì)介紹獲取插件的IBinder對象的過程。
首先是PluginFactory類。該類是唯一針對插件的對外入口類。這里因為只用到了query,故只列出此方法:
query:快速獲取IBinder。尋找目標(biāo)進(jìn)程、尋找對應(yīng)插件并加載等都在此方法中完成。具體用法和流程在后面有敘述。
其次是PluginLoader類。該類主要負(fù)責(zé)插件的加載部分:
load:加載一個插件。
query:被PluginFactory調(diào)用,一旦找到進(jìn)程和插件,則此方法將直接調(diào)用先前已緩存好的IPlugin.query方法來使用。
然后是Entry類。該類是所有插件的入口類,僅有一個方法:
create:插件的入口。其返回值恰是本發(fā)明所用到的IPlugin對象。若返回null,則表示插件加載失敗。
同時,一些插件初始化的流程也可在此方法中體現(xiàn)。
IPlugin接口是核心類之一,它是獲取IBinder對象的入口,存在于插件內(nèi)。
query:作為插件方,需實現(xiàn)此方法,并根據(jù)module名字返回對應(yīng)的IBinder對象,供外界使用。
下面將從安裝IBinder和使用IBinder兩方面來詳細(xì)介紹本發(fā)明的獲取插件的IBinder對象的方法的實現(xiàn)過程。
首先,安裝IBinder。每次加載插件時,本發(fā)明實施例都會嘗試去緩存IPlugin類,而此類正是作為IBinder的獲取類而存在的,下面將描述這種過程。
采用PluginLoader.load方法加載插件,在加載插件的過程中,需要創(chuàng)建插件的入口類(即Entry類)的對象,該對象和方法均需要通過反射來創(chuàng)建和調(diào)用,具體包括以下兩個步驟101和102:
101:反射獲取Entry.create方法的描述;
102:調(diào)用此方法描述,緩存mPlugin對象。
具體代碼如下:
在本發(fā)明實施例中,為了方便起見,規(guī)定所有的插件入口類的全名遵循如下的規(guī)則:“com.qihoo360.plugin.”+插件名+“.Entry”。如搖一搖插件的入口類全名為:com.qihoo360.plugin.shakeoff.Entry。當(dāng)然,也可以通過AndroidManifest.xml中的Meta-data來自定義Entry類的位置。
此外,在手機(jī)衛(wèi)士產(chǎn)品中,將IPlugin變成AIDL(Android Interface Definition Language,Android接口定義語言)類,這樣可以充分利用AIDL的一些特性。至此,IPlugin對象就緩存完成,并隨時備用了。
其次,使用IBinder。在介紹之前,先定義一些術(shù)語:
調(diào)用方:指需要使用IBinder的一端,主要是調(diào)用PluginFactory.query的一端;
接收方:指返回IBinder的一端,主要是IPlugin.query端處理的一端;
目標(biāo)進(jìn)程:指接收方所在進(jìn)程。接收方可以和調(diào)用方為一個進(jìn)程,也可以跨進(jìn)程去調(diào)用。
當(dāng)外部插件需要使用IBinder時,需要經(jīng)過幾個步驟201至205:
201:首先判斷目標(biāo)進(jìn)程是否為當(dāng)前進(jìn)程,換言之,調(diào)用方和接收方是否要求在一個進(jìn)程中,若是,則繼續(xù)執(zhí)行202;反之,若否,則繼續(xù)執(zhí)行203。
202:獲取IBinder對象。
203:判斷目標(biāo)進(jìn)程是否為常駐進(jìn)程。若是,則需要跨進(jìn)程去調(diào)用常駐進(jìn)程里的Query方法。
204:在常駐進(jìn)程里有一個Provider,獲取IPluginHost(也是IBinder)對象,然后再做下一步操作。
205:利用AIDL調(diào)用IPluginHost.queryPluginBinder方法,其仍調(diào)用的是PluginFactory,只不過這次傳遞的目標(biāo)進(jìn)程是“當(dāng)前的”。
具體代碼如下:
以下將重點說明步驟202、204和205。
實際上,本發(fā)明實施例提供了“單進(jìn)程”和“跨進(jìn)程”兩種方案。如果是“單進(jìn)程”方案的話,只需要202步驟即可,其它步驟均可省略。而“跨進(jìn)程”方案則需要考慮很多種情況,故仍需上述所有步驟。
在步驟202中,首先定義PluginFactory.query方法。該方法用來獲取或加載插件,并調(diào)用其IPlugin提供的接口,步驟如下301至307:
301-302:嘗試獲取或者加載插件Dex,返回符合條件的PluginLoader對象;
303-305:通過PluginLoader對象中的query()方法,來嘗試從Entry中拿到IPlugin的對象,來調(diào)用其query方法,以獲取IBinder對象。
306-307:到插件內(nèi)的IPlugin中調(diào)用其query方法,來獲取IBinder對象并返回給外界。
具體代碼如下:
其中mPlugins字段用來記錄所有的插件信息,不管插件是否被加載,這里不再贅述。
PluginLoader類的query方法就是從剛才在加載插件時,從Entry中拿到IPlugin中調(diào)用其query方法,具體代碼如下:
在步驟204和205中,可以實現(xiàn)跨進(jìn)程獲取IBinder對象??邕M(jìn)程獲取的要點是:
通過Provider來獲取IPluginHost這個AIDL對象;
借由IPluginHost.query()方法來調(diào)用PluginFactory.query()方法。
其中,IPluginHost的獲取可以通過SyncServiceManager.getService來獲取。一旦拿到IPluginHost對象后,可直接調(diào)用PluginFactory.query方法,進(jìn)而調(diào)用Entry.create方法中獲取插件的接口的對象(即,mPlugin對象),之后,調(diào)用插件的接口的對象中的query方法獲取IBinder對象。
此外,本發(fā)明實施例還可以定義IPlugin和插件初始化。作為插件接口定義方,定義供外界訪問的IPlugin對象只需要復(fù)寫IPlugin.query方法,并在Entry類中返回此對象即可。這里,還可以做插件初始化的一些操作,且一旦操作失敗,則可以返回null,這將會告訴外界,插件加載失敗。
具體代碼如下:
若外界想獲取IAccountManager的AIDL,只需這樣調(diào)用即可:
其中第一個參數(shù)為插件名,第二個為模塊名。拿到的IBinder對象需要再轉(zhuǎn)換成IAccountManager后即可。
綜上介紹,本發(fā)明實施例可以做到:
(1)只需要通過PluginFactory.query方法來獲取AIDL,沒有多余步驟;
(2)只需要定義IPlugin.query和設(shè)置返回值就可以定義AIDL,同樣沒有多余步驟;
(3)不僅支持當(dāng)前進(jìn)程,還可以跨進(jìn)程到常駐進(jìn)程里(當(dāng)然,不僅僅局限于常駐,還可在UI、單獨等)
(4)在Entry類的create方法內(nèi),還可以做些額外的初始化操作,方便插件做下一步操作。其所做的事情和Application可形成互補。
進(jìn)一步地,在上文調(diào)用目標(biāo)插件的接口的對象中的指定方法獲取IBinder對象之后,可以利用獲取的IBinder對象進(jìn)行與目標(biāo)插件進(jìn)行通信,來實現(xiàn)相應(yīng)的功能或任務(wù)。
Android的遠(yuǎn)程調(diào)用(即跨進(jìn)程調(diào)用)就是通過IBinder實現(xiàn)的,IBinder是遠(yuǎn)程對象的基本接口,是為高性能而設(shè)計的輕量級遠(yuǎn)程調(diào)用機(jī)制的核心部分。但它不僅用于遠(yuǎn)程調(diào)用,也用于進(jìn)程內(nèi)調(diào)用。這個接口定義了與遠(yuǎn)程對象交互的協(xié)議。不要直接實現(xiàn)這個接口,而應(yīng)該從Binder派生。IBinder的主要API是transact(),與它對應(yīng)另一方法是Binder.onTransact()。第一個方法使調(diào)用者向遠(yuǎn)端的IBinder對象發(fā)送發(fā)出調(diào)用,第二個方法使調(diào)用方的遠(yuǎn)程對象能夠響應(yīng)接收到的調(diào)用。IBinder的API都是同步執(zhí)行的,比如transact()直到對方的Binder.onTransact()方法調(diào)用完成后才返回。調(diào)用發(fā)生在進(jìn)程內(nèi)時無疑是這樣的,而在進(jìn)程間時,在IPC的幫助下,也是同樣的效果。
通過transact()發(fā)送的數(shù)據(jù)是Parcel,Parcel是一種一般的緩沖區(qū),除了有數(shù)據(jù)外還帶有一些描述它內(nèi)容的元數(shù)據(jù)。元數(shù)據(jù)用于管理IBinder對象的引用,這樣就能在緩沖區(qū)從一個進(jìn)程移動到另一個進(jìn)程時保存這些引用。這樣就保證了當(dāng)一個IBinder被寫入到Parcel并發(fā)送到另一個進(jìn)程中,如果另一個進(jìn)程把同一個IBinder的引用回發(fā)到原來的進(jìn)程,那么這個原來的進(jìn)程就能接收到發(fā)出的那個IBinder的引用。這種機(jī)制使IBinder和Binder像唯一標(biāo)志符那樣在進(jìn)程間管理。
系統(tǒng)為每個進(jìn)程維護(hù)一個存放交互線程的線程池。這些交互線程用于派送所有從另外進(jìn)程發(fā)來的IPC調(diào)用。例如,當(dāng)一個IPC從進(jìn)程A發(fā)到進(jìn)程B,A中那個發(fā)出調(diào)用的線程(這個應(yīng)該不在線程池中)就阻塞在transact()中了。進(jìn)程B中的交互線程池中的一個線程接收了這個調(diào)用,它調(diào)用Binder.onTransact(),完成后用一個Parcel來做為結(jié)果返回。然后進(jìn)程A中的那個等待的線程在收到返回的Parcel后得以繼續(xù)執(zhí)行。實際上,另一個進(jìn)程看起來就像是當(dāng)前進(jìn)程的一個線程,但不是當(dāng)前進(jìn)程創(chuàng)建的。
Binder機(jī)制還支持進(jìn)程間的遞歸調(diào)用。例如,進(jìn)程A執(zhí)行自己的IBinder的transact()調(diào)用進(jìn)程B的Binder,而進(jìn)程B在其Binder.onTransact()中又用transact()向進(jìn)程A發(fā)起調(diào)用,那么進(jìn)程A在等待它發(fā)出的調(diào)用返回的同時,還會用Binder.onTransact()響應(yīng)進(jìn)程B的transact()??傊瓸inder造成的結(jié)果使得跨進(jìn)程的調(diào)用與進(jìn)程內(nèi)的調(diào)用沒什么區(qū)別。
基于上文各個實施例提供的插件加載方法,基于同一發(fā)明構(gòu)思,本發(fā)明實施例還提供了一種插件加載裝置。
圖2示出了根據(jù)本發(fā)明一個實施例的插件加載裝置的結(jié)構(gòu)示意圖。如圖2所示,該裝置至少可以包括加載模塊210、創(chuàng)建模塊220以及緩存模塊230。
現(xiàn)介紹本發(fā)明實施例的插件加載裝置的各組成或器件的功能以及各部分間的連接關(guān)系:
加載模塊210,適于當(dāng)宿主程序接收到加載插件的指令時,調(diào)用插件加載方法對目標(biāo)插件進(jìn)行加載;
創(chuàng)建模塊220,與加載模塊210相耦合,適于在加載目標(biāo)插件的過程中,創(chuàng)建目標(biāo)插件的入口類的對象;
緩存模塊230,與創(chuàng)建模塊220相耦合,適于利用所述入口類的對象,調(diào)用所述入口類中的指定方法緩存目標(biāo)插件的接口的對象。
在本發(fā)明一實施例中,如圖3所示,上文圖2展示的裝置還可以包括:
調(diào)用模塊240,與緩存模塊230相耦合,適于目標(biāo)插件的接口的對象用于獲取IBinder對象,當(dāng)外部調(diào)用方需要獲取目標(biāo)插件的IBinder對象時,調(diào)用預(yù)先定義的預(yù)定義類中的指定方法;
第一獲取模塊250,與調(diào)用模塊240相耦合,適于利用所述預(yù)定義類中的指定方法,從所述入口類中的指定方法中獲取目標(biāo)插件的接口的對象;
第二獲取模塊260,與第一獲取模塊250相耦合,適于調(diào)用目標(biāo)插件的接口的對象中的指定方法獲取IBinder對象。
在本發(fā)明一實施例中,如圖3所示,上文圖2展示的裝置還可以包括:
通信模塊270,與第二獲取模塊260相耦合,適于在所述第二獲取模塊260調(diào)用目標(biāo)插件的接口的對象中的指定方法獲取IBinder對象之后,利用獲取的IBinder對象進(jìn)行與所述目標(biāo)插件進(jìn)行通信。
在本發(fā)明一實施例中,所述目標(biāo)插件的入口類為Entry類。
在本發(fā)明一實施例中,所述目標(biāo)插件的接口為IPlugin接口,所述IPlugin接口的對象為mPlugin對象。
在本發(fā)明一實施例中,如圖3所示,上文圖2展示的裝置還可以包括:
第三獲取模塊280,與創(chuàng)建模塊220、緩存模塊230相耦合,適于利用所述入口類的對象,反射獲取所述入口類中的指定方法。
在本發(fā)明一實施例中,上述調(diào)用模塊240還適于:
當(dāng)外部調(diào)用方需要獲取插件的IBinder對象時,判斷所述外部調(diào)用方所在當(dāng)前進(jìn)程與即將返回所述目標(biāo)插件的IBinder對象的接收方所在目標(biāo)進(jìn)程是否為同一進(jìn)程;
若是,則直接調(diào)用預(yù)先定義的預(yù)定義類中的指定方法。
在本發(fā)明一實施例中,上述調(diào)用模塊240還適于:
若所述外部調(diào)用方所在當(dāng)前進(jìn)程與即將返回所述目標(biāo)插件的IBinder對象的接收方所在目標(biāo)進(jìn)程不為同一進(jìn)程,則通過所述目標(biāo)進(jìn)程中的Provider獲取宿主程序的接口的對象;
由宿主程序的接口的對象中的指定方法,調(diào)用預(yù)先定義的預(yù)定義類中的指定方法。
在本發(fā)明一實施例中,所述目標(biāo)進(jìn)程為常駐進(jìn)程。
在本發(fā)明一實施例中,所述宿主程序的接口為IPluginHost接口。
在本發(fā)明一實施例中,上述第二獲取模塊260還適于:
調(diào)用目標(biāo)插件的接口的對象中的指定方法;
根據(jù)module名字返回對應(yīng)的IBinder對象。
在本發(fā)明一實施例中,上述加載模塊210還適于:
將插件加載事件拆分為獨立的至少一個加載階段,其中,各個加載階段對應(yīng)不同的插件內(nèi)容;
當(dāng)宿主程序接收到加載插件的指令時,確定所述請求對應(yīng)的目標(biāo)加載階段;
加載所述目標(biāo)加載階段對應(yīng)的插件內(nèi)容。
在本發(fā)明一實施例中,所述至少一個加載階段包括下列至少之一:
插件信息的獲取、插件資源的加載、插件代碼的加載。
根據(jù)上述任意一個優(yōu)選實施例或多個優(yōu)選實施例的組合,本發(fā)明實施例能夠達(dá)到如下有益效果:
本發(fā)明實施例提供的技術(shù)方案,當(dāng)宿主程序接收到加載插件的請求時,調(diào)用插件加載方法對目標(biāo)插件進(jìn)行加載,在加載目標(biāo)插件的過程中可以創(chuàng)建目標(biāo)插件的入口類的對象,并利用入口類的對象,調(diào)用入口類中的指定方法緩存目標(biāo)插件的接口的對象。由于該目標(biāo)插件的接口的對象能夠用于獲取IBinder對象,因而當(dāng)外部調(diào)用方需要獲取目標(biāo)插件的IBinder對象時,可以直接獲取緩存的目標(biāo)插件的接口的對象,并利用該目標(biāo)插件的接口的對象來獲取IBinder對象,進(jìn)而可以利用獲取的IBinder對象與目標(biāo)插件進(jìn)行通信。由此可見,本發(fā)明實施例能夠充分利用Android系統(tǒng)的邏輯來實現(xiàn)在插件中快速、同步地獲取IBinder對象,實現(xiàn)進(jìn)程內(nèi)或進(jìn)程間的通信。
在此處所提供的說明書中,說明了大量具體細(xì)節(jié)。然而,能夠理解,本發(fā)明的實施例可以在沒有這些具體細(xì)節(jié)的情況下實踐。在一些實例中,并未詳細(xì)示出公知的方法、結(jié)構(gòu)和技術(shù),以便不模糊對本說明書的理解。
類似地,應(yīng)當(dāng)理解,為了精簡本公開并幫助理解各個發(fā)明方面中的一個或多個,在上面對本發(fā)明的示例性實施例的描述中,本發(fā)明的各個特征有時被一起分組到單個實施例、圖、或者對其的描述中。然而,并不應(yīng)將該公開的方法解釋成反映如下意圖:即所要求保護(hù)的本發(fā)明要求比在每個權(quán)利要求中所明確記載的特征更多的特征。更確切地說,如下面的權(quán)利要求書所反映的那樣,發(fā)明方面在于少于前面公開的單個實施例的所有特征。因此,遵循具體實施方式的權(quán)利要求書由此明確地并入該具體實施方式,其中每個權(quán)利要求本身都作為本發(fā)明的單獨實施例。
本領(lǐng)域那些技術(shù)人員可以理解,可以對實施例中的設(shè)備中的模塊進(jìn)行自適應(yīng)性地改變并且把它們設(shè)置在與該實施例不同的一個或多個設(shè)備中??梢园褜嵤├械哪K或單元或組件組合成一個模塊或單元或組件,以及此外可以把它們分成多個子模塊或子單元或子組件。除了這樣的特征和/或過程或者單元中的至少一些是相互排斥之外,可以采用任何組合對本說明書(包括伴隨的權(quán)利要求、摘要和附圖)中公開的所有特征以及如此公開的任何方法或者設(shè)備的所有過程或單元進(jìn)行組合。除非另外明確陳述,本說明書(包括伴隨的權(quán)利要求、摘要和附圖)中公開的每個特征可以由提供相同、等同或相似目的的替代特征來代替。
此外,本領(lǐng)域的技術(shù)人員能夠理解,盡管在此所述的一些實施例包括其它實施例中所包括的某些特征而不是其它特征,但是不同實施例的特征的組合意味著處于本發(fā)明的范圍之內(nèi)并且形成不同的實施例。例如,在權(quán)利要求書中,所要求保護(hù)的實施例的任意之一都可以以任意的組合方式來使用。
本發(fā)明的各個部件實施例可以以硬件實現(xiàn),或者以在一個或者多個處理器上運行的軟件模塊實現(xiàn),或者以它們的組合實現(xiàn)。本領(lǐng)域的技術(shù)人員應(yīng)當(dāng)理解,可以在實踐中使用微處理器或者數(shù)字信號處理器(DSP)來實現(xiàn)根據(jù)本發(fā)明實施例的插件加載裝置中的一些或者全部部件的一些或者全部功能。本發(fā)明還可以實現(xiàn)為用于執(zhí)行這里所描述的方法的一部分或者全部的設(shè)備或者裝置程序(例如,計算機(jī)程序和計算機(jī)程序產(chǎn)品)。這樣的實現(xiàn)本發(fā)明的程序可以存儲在計算機(jī)可讀介質(zhì)上,或者可以具有一個或者多個信號的形式。這樣的信號可以從因特網(wǎng)網(wǎng)站上下載得到,或者在載體信號上提供,或者以任何其他形式提供。
應(yīng)該注意的是上述實施例對本發(fā)明進(jìn)行說明而不是對本發(fā)明進(jìn)行限制,并且本領(lǐng)域技術(shù)人員在不脫離所附權(quán)利要求的范圍的情況下可設(shè)計出替換實施例。在權(quán)利要求中,不應(yīng)將位于括號之間的任何參考符號構(gòu)造成對權(quán)利要求的限制。單詞“包含”不排除存在未列在權(quán)利要求中的元件或步驟。位于元件之前的單詞“一”或“一個”不排除存在多個這樣的元件。本發(fā)明可以借助于包括有若干不同元件的硬件以及借助于適當(dāng)編程的計算機(jī)來實現(xiàn)。在列舉了若干裝置的單元權(quán)利要求中,這些裝置中的若干個可以是通過同一個硬件項來具體體現(xiàn)。單詞第一、第二、以及第三等的使用不表示任何順序??蓪⑦@些單詞解釋為名稱。
至此,本領(lǐng)域技術(shù)人員應(yīng)認(rèn)識到,雖然本文已詳盡示出和描述了本發(fā)明的多個示例性實施例,但是,在不脫離本發(fā)明精神和范圍的情況下,仍可根據(jù)本發(fā)明公開的內(nèi)容直接確定或推導(dǎo)出符合本發(fā)明原理的許多其他變型或修改。因此,本發(fā)明的范圍應(yīng)被理解和認(rèn)定為覆蓋了所有這些其他變型或修改。
本發(fā)明實施例還提供了A1、一種插件加載方法,包括:
當(dāng)宿主程序接收到加載插件的請求時,調(diào)用插件加載方法對目標(biāo)插件進(jìn)行加載;
在加載目標(biāo)插件的過程中,創(chuàng)建目標(biāo)插件的入口類的對象;
利用所述入口類的對象,調(diào)用所述入口類中的指定方法緩存目標(biāo)插件的接口的對象。
A2、根據(jù)A1所述的方法,其中,目標(biāo)插件的接口的對象用于獲取IBinder對象,所述方法還包括:
當(dāng)外部調(diào)用方需要獲取目標(biāo)插件的IBinder對象時,調(diào)用預(yù)先定義的預(yù)定義類中的指定方法;
利用所述預(yù)定義類中的指定方法,從所述入口類中的指定方法中獲取目標(biāo)插件的接口的對象;
調(diào)用目標(biāo)插件的接口的對象中的指定方法獲取IBinder對象。
A3、根據(jù)A2所述的方法,其中,在調(diào)用目標(biāo)插件的接口的對象中的指定方法獲取IBinder對象之后,所述方法還包括:
利用獲取的IBinder對象進(jìn)行與所述目標(biāo)插件進(jìn)行通信。
A4、根據(jù)A1-A3中任一項所述的方法,其中,所述目標(biāo)插件的入口類為Entry類。
A5、根據(jù)A1-A4中任一項所述的方法,其中,所述目標(biāo)插件的接口為IPlugin接口,所述IPlugin接口的對象為mPlugin對象。
A6、根據(jù)A1-A5中任一項所述的方法,其中,還包括:
利用所述入口類的對象,反射獲取所述入口類中的指定方法。
A7、根據(jù)A2-A6中任一項所述的方法,其中,當(dāng)外部調(diào)用方需要獲取目標(biāo)插件的IBinder對象時,調(diào)用預(yù)先定義的預(yù)定義類中的指定方法,包括:
當(dāng)外部調(diào)用方需要獲取目標(biāo)插件的IBinder對象時,判斷所述外部調(diào)用方所在當(dāng)前進(jìn)程與即將返回所述目標(biāo)插件的IBinder對象的接收方所在目標(biāo)進(jìn)程是否為同一進(jìn)程;
若是,則直接調(diào)用預(yù)先定義的預(yù)定義類中的指定方法。
A8、根據(jù)A7所述的方法,其中,還包括:
若所述外部調(diào)用方所在當(dāng)前進(jìn)程與即將返回所述目標(biāo)插件的IBinder對象的接收方所在目標(biāo)進(jìn)程不為同一進(jìn)程,則通過所述目標(biāo)進(jìn)程中的Provider獲取宿主程序的接口的對象;
由宿主程序的接口的對象中的指定方法,調(diào)用預(yù)先定義的預(yù)定義類中的指定方法。
A9、根據(jù)A8所述的方法,其中,所述目標(biāo)進(jìn)程為常駐進(jìn)程。
A10、根據(jù)A8或A9所述的方法,其中,所述宿主程序的接口為IPluginHost接口。
A11、根據(jù)A1-A10中任一項所述的方法,其中,調(diào)用目標(biāo)插件的接口的對象中的指定方法獲取IBinder對象,包括:
調(diào)用目標(biāo)插件的接口的對象中的指定方法;
根據(jù)module名字返回對應(yīng)的IBinder對象。
A12、根據(jù)A1-A11中任一項所述的方法,其中,當(dāng)宿主程序接收到加載插件的指令時,調(diào)用插件加載方法對目標(biāo)插件進(jìn)行加載,包括:
將插件加載事件拆分為獨立的至少一個加載階段,其中,各個加載階段對應(yīng)不同的插件內(nèi)容;
當(dāng)宿主程序接收到加載插件的指令時,確定所述請求對應(yīng)的目標(biāo)加載階段;
加載所述目標(biāo)加載階段對應(yīng)的插件內(nèi)容。
A13、根據(jù)A12所述的方法,其中,所述至少一個加載階段包括下列至少之一:
插件信息的獲取、插件資源的加載、插件代碼的加載。
本發(fā)明實施例還提供了B14、一種插件加載裝置,包括:
加載模塊,適于當(dāng)宿主程序接收到加載插件的指令時,調(diào)用插件加載方法對目標(biāo)插件進(jìn)行加載;
創(chuàng)建模塊,適于在加載目標(biāo)插件的過程中,創(chuàng)建目標(biāo)插件的入口類的對象;
緩存模塊,適于利用所述入口類的對象,調(diào)用所述入口類中的指定方法緩存目標(biāo)插件的接口的對象。
B15、根據(jù)B14所述的裝置,其中,目標(biāo)插件的接口的對象用于獲取IBinder對象,所述裝置還包括:
調(diào)用模塊,適于當(dāng)外部調(diào)用方需要獲取目標(biāo)插件的IBinder對象時,調(diào)用預(yù)先定義的預(yù)定義類中的指定方法;
第一獲取模塊,適于利用所述預(yù)定義類中的指定方法,從所述入口類中的指定方法中獲取目標(biāo)插件的接口的對象;
第二獲取模塊,適于調(diào)用目標(biāo)插件的接口的對象中的指定方法獲取IBinder對象。
B16、根據(jù)B15所述的裝置,其中,還包括:
通信模塊,適于在所述第二獲取模塊調(diào)用目標(biāo)插件的接口的對象中的指定方法獲取IBinder對象之后,利用獲取的IBinder對象進(jìn)行與所述目標(biāo)插件進(jìn)行通信。
B17、根據(jù)B14-B16中任一項所述的裝置,其中,所述目標(biāo)插件的入口類為Entry類。
B18、根據(jù)B14-B17中任一項所述的裝置,其中,所述目標(biāo)插件的接口為IPlugin接口,所述IPlugin接口的對象為mPlugin對象。
B19、根據(jù)B14-B18中任一項所述的裝置,其中,還包括:
第三獲取模塊,適于利用所述入口類的對象,反射獲取所述入口類中的指定方法。
B20、根據(jù)B15-B19中任一項所述的裝置,其中,所述調(diào)用模塊還適于:
當(dāng)外部調(diào)用方需要獲取目標(biāo)插件的IBinder對象時,判斷所述外部調(diào)用方所在當(dāng)前進(jìn)程與即將返回所述目標(biāo)插件的IBinder對象的接收方所在目標(biāo)進(jìn)程是否為同一進(jìn)程;
若是,則直接調(diào)用預(yù)先定義的預(yù)定義類中的指定方法。
B21、根據(jù)B20所述的裝置,其中,所述調(diào)用模塊還適于:
若所述外部調(diào)用方所在當(dāng)前進(jìn)程與即將返回所述目標(biāo)插件的IBinder對象的接收方所在目標(biāo)進(jìn)程不為同一進(jìn)程,則通過所述目標(biāo)進(jìn)程中的Provider獲取宿主程序的接口的對象;
由宿主程序的接口的對象中的指定方法,調(diào)用預(yù)先定義的預(yù)定義類中的指定方法。
B22、根據(jù)B21所述的裝置,其中,所述目標(biāo)進(jìn)程為常駐進(jìn)程。
B23、根據(jù)B21或B22所述的裝置,其中,所述宿主程序的接口為IPluginHost接口。
B24、根據(jù)B14-B23中任一項所述的裝置,其中,所述第二獲取模塊還適于:
調(diào)用目標(biāo)插件的接口的對象中的指定方法;
根據(jù)module名字返回對應(yīng)的IBinder對象。
B25、根據(jù)B14-B24中任一項所述的裝置,其中,所述加載模塊還適于:
將插件加載事件拆分為獨立的至少一個加載階段,其中,各個加載階段對應(yīng)不同的插件內(nèi)容;
當(dāng)宿主程序接收到加載插件的指令時,確定所述請求對應(yīng)的目標(biāo)加載階段;
加載所述目標(biāo)加載階段對應(yīng)的插件內(nèi)容。
B26、根據(jù)B25所述的裝置,其中,所述至少一個加載階段包括下列至少之一:
插件信息的獲取、插件資源的加載、插件代碼的加載。