from:http://code.google.com/p/android-application-plug-ins-frame-work/
介紹
這個框架的初衷,是為了方便讓程序模塊化、插件化,將一個apk應(yīng)用拆分為多個apk。
不明白這個插件化、模塊化是怎么回事的話,可以看看騰訊微信的安卓客戶端中的插件配置。
在這里我會以騰訊微信為例,如何使用這個框架。 (騰訊微信并不是真正的插件化,它是偽的,插件并非與它的主程序分離開,結(jié)果就是每次插件的更新,都必須以整個程序的更新為代價)
都能干啥
框架的思想,主要是通過apk清單文件中的sharedUserId屬性來吧多個apk融合為單一的dalvik虛擬機(jī),也就是融合為一個進(jìn)程,這樣就變相逾越了android框架中不同apk權(quán)限不同無法互通的鴻溝(rpc啦什么的其它的畢竟不如這個來的實在)。
從最簡單的皮膚插件到復(fù)雜的涉及數(shù)據(jù)庫的拓展功能,從普通activity跳轉(zhuǎn)到把插件的activity轉(zhuǎn)變?yōu)関iew并附加到主程序中的拓展功能,都是可以通過本框架來實現(xiàn)的,當(dāng)然,本框架只是提供了一種途徑,如何編碼還得靠自己。
本人能力有限,可能有一些錯誤、疏漏或者不足之處,請不吝指教,我的博客地址在左下角,或者我的郵箱,都可以聯(lián)系到我。
ps:下面會以騰訊微信為例,這里聲明一下,本人沒有對微信安卓客戶端進(jìn)行任意形式的反編譯與破解工作,只是看球半天進(jìn)行簡單的猜測而已。
框架結(jié)構(gòu)
本插件框架由三個包組成:
- org.igeek.android.pluginframework 這個包種類是框架的主要操作類
- PluginBuilder 組裝插件
- PluginDescription 組裝用戶自定義的插件描述
- PluginInvoke 插件功能調(diào)用
- PluginSearch 查找插件
- org.igeek.android.pluginframework.annotation 未來可能會考慮使用注解
- PluginDescription 用于用戶自定義描述類的注解
- PluginFeature 用于插件類的注解
- PluginMethod 用于插件類方法的注解
- org.igeek.android.pluginframework.beans 框架內(nèi)部使用的一些beans
- Plugin 插件包
- PluginFeature 插件類
- PluginFeatureMethod 插件方法
- org.igeek.android.pluginframework.util 一些工具類
- XMLParse 插件包
如何使用
以騰訊微信為例,雖然從表面來看,它是插件化的多種功能的一種集成。但是,這都是虛的,每次更新時你會發(fā)現(xiàn),哪怕一個小小的功能添加,都會讓用戶更新整個程序,截至目前(2011-12-17),微信讓我更新到3.5,修復(fù)了一些小bug,增加了1個插件功能,以及其它的小改進(jìn),就得讓我下載并升級整個程序,6.8m啊。。
在工程開發(fā)時,預(yù)留插件的使用、管理頁面,如:

這是微信的插件瀏覽頁面,所有可暴露在這里的插件都會被列出來
這是微信的插件管理界面,可以卸載安卓,但這些都是虛的,可能只是把服務(wù)關(guān)了,并非真正的卸載
主程序(APK)
首先為工程想好一個名字,并在清單中加入sharedUserId屬性,屬性值就是想好的那個名字,例如微信:com.qq.weixin android:sharedUserId="com.qq.weixin"
這就是插件描述
首先在主程序中單獨建立一個包,并寫一個類,這個類相當(dāng)于一個bean,具有相應(yīng)的插件描述信息的字段,如微信,那么這個bean的字段就有 插件名:漂流瓶 插件logo:那個人頭 插件描述:描述信息...
這個類在主程序中不會很多的使用,只會讀取框架返回的插件的bean。
正式編碼時,可在任何地方調(diào)用框架。具體步驟是這樣的
1、查找插件 本框架是根據(jù)sharedUserId來查找插件。它首先會根據(jù)自身apk的sharedUserId值來查找系統(tǒng)中具有相同屬性的包并加載。
- ??以說,插件apk的sharedUserId值也應(yīng)與主程序相同
//首先,就是查找插件
PluginSearch psearch=new PluginSearch();
//第一次獲得的是簡要的插件描述
List<Plugin> plugins=psearch.getPlugins(this);
//然后將插件再組裝一下
PluginBuilder pbuilder=new PluginBuilder(this);
//將用戶所定義插件描述融合進(jìn)去
plugins=pbuilder.buildPluginsDescrition(plugins);
這樣就把所有插件找到手了,很簡單吧?
1、調(diào)用插件 找到插件后肯定是調(diào)用,最簡單應(yīng)用,就是靠Button按鈕來調(diào)用
比如微信的搖一搖,點了它就觸發(fā)框架的插件調(diào)用 @Override
public void onClick(View v) {
//新建一個插件調(diào)用類
PluginInvoke pi=new PluginInvoke(AndroidPluginFrameworkActivity.this);
//這是真正的調(diào)用
//三個參數(shù),第一個是Plugin類型,第二個是PluginFeature,第三個PluginFeatureMethod
pi.invoke(plug, pf, fm);
}
});
插件程序(APK)
同主程序的清單文件一樣,sharedUserId必須有且和主程序的一樣 插件的activity的意圖過濾描述必須是這樣 示例: <intent-filter>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
插件可以包含任意類,如同一個普通的apk工程一樣。
但是,向主程序提供調(diào)用的類,必須是個activity,方法必須是無返回值的,有且只有一個Context參數(shù),框架會反射這個方法,并將主程序的context句柄傳入,也就是,不管你用不用這個context,他都是被框架傳入的。
如果主程序規(guī)定了描述類,也就是框架中需要PluginDescription來調(diào)用的bean,在插件工程中,也必須有主程序這個bean,包名也必須一樣。插件程序可以直接繼承或者更改這個bean的字段,方便主程序去獲取這個插件的描述信息。這種方式,是避過框架,給主程序一種方便。
http://android-application-plug-ins-frame-work.googlecode.com/files/plugin.xml plugin.xml不能改名,必須放在工程的 assets 目錄下。
內(nèi)容大致是這樣:<?xml version="1.0" encoding="UTF-8"?>
<!-- 這個xml配置文件放在插件工程的 assets 目錄下 -->
<!-- 插件提供的功能(類) -->
<plugin-features>
<!-- 描述類,這個是自定義的 -->
<!-- 這個描述類使用戶定義的,在主程序中必須有,插件工程中也必須有,并被繼承 -->
<description name="org.pakage.name.and.description.name"/>
<!-- 這是一個功能(類),必須是activity的子類 -->
<feature name="org.pakage.name.and.activity.name1">
<!-- 這是一個方法 -->
<!-- name 方法名 -->
<method need-context="true" name="methodName1" >描述信息</method>
<method need-context="true" name="methodName2" >描述信息</method>
</feature>
<feature name="org.pakage.name.and.activity.name2">
<method need-context="true" name="methodName1" >描述信息</method>
</feature>
</plugin-features>
按著上面的套路來配置,就很容易了。
最后
上面說的比較泛,最好還是看看示例工程,里面包含了一個主程序和兩個插件擴(kuò)展,總共是4個工程,也就是說,在用戶端是4個apkhttp://android-application-plug-ins-frame-work.googlecode.com/files/demo.zip