from:http://code.google.com/p/android-application-plug-ins-frame-work/
介紹
這個框架的初衷,是為了方便讓程序模塊化、插件化,將一個apk應用拆分為多個apk。
不明白這個插件化、模塊化是怎么回事的話,可以看看騰訊微信的安卓客戶端中的插件配置。
在這里我會以騰訊微信為例,如何使用這個框架。 (騰訊微信并不是真正的插件化,它是偽的,插件并非與它的主程序分離開,結果就是每次插件的更新,都必須以整個程序的更新為代價)
都能干啥
框架的思想,主要是通過apk清單文件中的sharedUserId屬性來吧多個apk融合為單一的dalvik虛擬機,也就是融合為一個進程,這樣就變相逾越了android框架中不同apk權限不同無法互通的鴻溝(rpc啦什么的其它的畢竟不如這個來的實在)。
從最簡單的皮膚插件到復雜的涉及數據庫的拓展功能,從普通activity跳轉到把插件的activity轉變為view并附加到主程序中的拓展功能,都是可以通過本框架來實現的,當然,本框架只是提供了一種途徑,如何編碼還得靠自己。
本人能力有限,可能有一些錯誤、疏漏或者不足之處,請不吝指教,我的博客地址在左下角,或者我的郵箱,都可以聯系到我。
ps:下面會以騰訊微信為例,這里聲明一下,本人沒有對微信安卓客戶端進行任意形式的反編譯與破解工作,只是看球半天進行簡單的猜測而已。
框架結構
本插件框架由三個包組成:
- org.igeek.android.pluginframework 這個包種類是框架的主要操作類
- PluginBuilder 組裝插件
- PluginDescription 組裝用戶自定義的插件描述
- PluginInvoke 插件功能調用
- PluginSearch 查找插件
- org.igeek.android.pluginframework.annotation 未來可能會考慮使用注解
- PluginDescription 用于用戶自定義描述類的注解
- PluginFeature 用于插件類的注解
- PluginMethod 用于插件類方法的注解
- org.igeek.android.pluginframework.beans 框架內部使用的一些beans
- Plugin 插件包
- PluginFeature 插件類
- PluginFeatureMethod 插件方法
- org.igeek.android.pluginframework.util 一些工具類
- XMLParse 插件包
如何使用
以騰訊微信為例,雖然從表面來看,它是插件化的多種功能的一種集成。但是,這都是虛的,每次更新時你會發現,哪怕一個小小的功能添加,都會讓用戶更新整個程序,截至目前(2011-12-17),微信讓我更新到3.5,修復了一些小bug,增加了1個插件功能,以及其它的小改進,就得讓我下載并升級整個程序,6.8m啊。。
在工程開發時,預留插件的使用、管理頁面,如:
這是微信的插件瀏覽頁面,所有可暴露在這里的插件都會被列出來
這是微信的插件管理界面,可以卸載安卓,但這些都是虛的,可能只是把服務關了,并非真正的卸載
主程序(APK)
- 、主程序清單
首先為工程想好一個名字,并在清單中加入sharedUserId屬性,屬性值就是想好的那個名字,例如微信:com.qq.weixinandroid:sharedUserId="com.qq.weixin"
- 、為插件描述寫一個類
這就是插件描述
首先在主程序中單獨建立一個包,并寫一個類,這個類相當于一個bean,具有相應的插件描述信息的字段,如微信,那么這個bean的字段就有 插件名:漂流瓶 插件logo:那個人頭 插件描述:描述信息...
這個類在主程序中不會很多的使用,只會讀取框架返回的插件的bean。
- 、引入本框架的jar包或導入源碼
正式編碼時,可在任何地方調用框架。具體步驟是這樣的
1、查找插件 本框架是根據sharedUserId來查找插件。它首先會根據自身apk的sharedUserId值來查找系統中具有相同屬性的包并加載。
- ??以說,插件apk的sharedUserId值也應與主程序相同
//首先,就是查找插件
PluginSearch psearch=new PluginSearch();
//第一次獲得的是簡要的插件描述
List<Plugin> plugins=psearch.getPlugins(this);
//然后將插件再組裝一下
PluginBuilder pbuilder=new PluginBuilder(this);
//將用戶所定義插件描述融合進去
plugins=pbuilder.buildPluginsDescrition(plugins);
這樣就把所有插件找到手了,很簡單吧?
1、調用插件 找到插件后肯定是調用,最簡單應用,就是靠Button按鈕來調用
比如微信的搖一搖,點了它就觸發框架的插件調用@Override
public void onClick(View v) {
//新建一個插件調用類
PluginInvoke pi=new PluginInvoke(AndroidPluginFrameworkActivity.this);
//這是真正的調用
//三個參數,第一個是Plugin類型,第二個是PluginFeature,第三個PluginFeatureMethod
pi.invoke(plug, pf, fm);
}
});
插件程序(APK)
- 、插件程序清單
同主程序的清單文件一樣,sharedUserId必須有且和主程序的一樣 插件的activity的意圖過濾描述必須是這樣 示例:<intent-filter>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
- 、插件程序的功能
插件可以包含任意類,如同一個普通的apk工程一樣。
但是,向主程序提供調用的類,必須是個activity,方法必須是無返回值的,有且只有一個Context參數,框架會反射這個方法,并將主程序的context句柄傳入,也就是,不管你用不用這個context,他都是被框架傳入的。
如果主程序規定了描述類,也就是框架中需要PluginDescription來調用的bean,在插件工程中,也必須有主程序這個bean,包名也必須一樣。插件程序可以直接繼承或者更改這個bean的字段,方便主程序去獲取這個插件的描述信息。這種方式,是避過框架,給主程序一種方便。
- 、插件程序的plugin.xml配置
http://android-application-plug-ins-frame-work.googlecode.com/files/plugin.xml plugin.xml不能改名,必須放在工程的 assets 目錄下。
內容大致是這樣:<?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>
按著上面的套路來配置,就很容易了。
最后
上面說的比較泛,最好還是看看示例工程,里面包含了一個主程序和兩個插件擴展,總共是4個工程,也就是說,在用戶端是4個apkhttp://android-application-plug-ins-frame-work.googlecode.com/files/demo.zip