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 這個包種類是框架的主要操作類
    1. PluginBuilder 組裝插件
    2. PluginDescription 組裝用戶自定義的插件描述
    3. PluginInvoke 插件功能調(diào)用
    4. PluginSearch 查找插件
  • org.igeek.android.pluginframework.annotation 未來可能會考慮使用注解
    1. PluginDescription 用于用戶自定義描述類的注解
    2. PluginFeature 用于插件類的注解
    3. PluginMethod 用于插件類方法的注解
  • org.igeek.android.pluginframework.beans 框架內(nèi)部使用的一些beans
    1. Plugin 插件包
    2. PluginFeature 插件類
    3. PluginFeatureMethod 插件方法
  • org.igeek.android.pluginframework.util 一些工具類
    1. 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。

  • 、引入本框架的jar包或?qū)朐创a

正式編碼時,可在任何地方調(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的字段,方便主程序去獲取這個插件的描述信息。這種方式,是避過框架,給主程序一種方便。
  • 、插件程序的plugin.xml配置
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