电竞比分网-中国电竞赛事及体育赛事平台

分享

android 程序開發(fā)的插件化 模塊化方法 之一

 aaie_ 2017-02-17

框架已經(jīng)放出:

Logo

   

 

 

 

 

     在Android的項目開發(fā)中,都會遇到后期功能拓展增強與主程序代碼變更的現(xiàn)實矛盾,也就是程序的靈活度。

     由于linux平臺的安全機制,再加上dalvik的特殊機制,各種權限壁壘,使得開發(fā)一個靈活多變的程序,變得比較困難,不像pc平臺下那么容易。

     瞅瞅elipse的插件,瞅瞅360的插件,在android下,我們一開始很難寫好一個主程序,然后通過插件機制來應對以后的功能拓展,于是程序變得不那么靈活多變了。

     比如一款android下的安全軟件,新版本增加了一個功能,如短信攔截,往往會因為一個模塊的增加,而重新編譯一個apk包,這樣周而復始,哪怕只增加50kb的功能代碼,用戶也需要升級一個完整的apk,往往是5~6M的體積。

 

     最近思來想去,想到一個方法,既然tencent qq在android下面可以以apk的形式來換皮膚,這資源文件的拓展都可以這樣簡便的搞,為何功能性的拓展就不可以?

想出來了兩種解決方案。

先來說說第一種。

 

demo下載在最后

 

先說分析思路。

     android下,默認的情況是,每個apk相互獨立的,基本上每個應用都是一個dalvik虛擬機,都有一個uid,再配合上linux本身的權限機制,使得apk互通很難直接進行。但作為一個獨立應用的集成,不管多少個apk,都可以并為一個單獨的dalvik虛擬機,直觀的反映給開發(fā)人員就是在shell下列出進程,那幾個apk同時加載后,會一個進程存在。

     這主要就是工程的清單文件 Mainfest中配置了,只需要一句話,以我的測試demo為例:

復制代碼
....

<manifest xmlns:android="http://schemas./apk/res/android"
      package="org.igeek.plugintest.main"
      <!-- 就是這句關鍵代碼 -->
      android:sharedUserId="org.igeek.plugintest"
      android:versionCode="1"      
      android:versionName="1.0">

.....
復制代碼


    在上面的代碼中,android:sharedUserId是指共用一個uid,也就是,凡是這個屬性相同的工程,都會共用同一個uid,這樣,權限壁壘就消除了,dalvik也會融合為一個,可以測試一下,寫幾個工程,沒有這個屬性和有這個屬性的情況下,同時運行,在列出當前進程,就直觀的說明了。

 

   程序拓展的插件化,當然需要一個主程序,主程序是實現(xiàn)基本功能,以及UI,還有插件的檢索以及插件的調(diào)用。

   這里貼出我demo中的主activity代碼:

View Code


    看注釋吧,主要有兩點

插件的掃描

        這種方案是,每個插件以一個單獨的apk發(fā)布,這樣可以在程序中很靈活的知道是否有新的插件,提示用戶下載安裝,插件的apk清單描述為Action為非Luncher,Category為Default。

        主程序偵聽packgeManager的安裝完成廣播,之后掃描同包名(插件當然得這么定義了,只要通過packgeManager能判斷是否為自己的插件就行)的apk,之后列出來,讓用戶選擇是否加載。

 

插件的加載與調(diào)用

         在獲取包后,通過調(diào)用系統(tǒng)的api可以得到 sharedUserId 與主程序相同的apk的context,也就是句柄,獲得了句柄,通過這個context可以得到classloader,之后就簡單了,如何知道這個插件提供什么功能?

         這個可以用xml描述,比如這個xml是插件apk的一個資源,就像spring這個框架一樣。xml中描述了這個插件有哪些類,提供哪些方法,這些方法需要傳入什么參數(shù),返回什么類型。我的demo中為了方便,是用接口,每個插件有一個類提供一個相同的方法,來獲取一個map集合,獲得這個插件的描述。

 

         ok,到這里就知道加載的插件提供什么功能了。

 

         在上面貼出來的代碼中,是循環(huán)遍歷每個插件,并把每個插件提供的功能以Button的方式顯示給用戶,點擊按鈕,就執(zhí)行了插件的功能,執(zhí)行時,并不是activity轉(zhuǎn)向(這樣就無意義了),而是在主程序自身的context句柄中執(zhí)行,也就是在自身的窗體中執(zhí)行。

         代碼中有一段注釋,說明,如果插件有用到context時,記得傳遞進去的是主程序的context,這樣窗體才能附加到這個句柄中,如果傳遞的是插件的context,它沒有一個窗體實例,是無法將一些窗體附加進去的,無任何效果。

 

這里只提供思路,有時間的話研究一下,看能不能搞個通用的框架出來。還有另一種方法,不通過apk形式,以后會寫出來。

      這里有一些待驗證的問題,比如插件的權限問題,如果插件需要的一些權限在主程序中沒有聲明,會是個什么情況,能不能實時申請呢?這個需要高人指點。或者在主程序中把能聲明的權限預先聲明了也不錯。還有就是native層代碼的問題,如果插件包含了native層代碼,會是個什么情況,這也需要驗證。

 

這是demo下載:

http://files.cnblogs.com/hangxin1940/android_plugin_program.rar

    本站是提供個人知識管理的網(wǎng)絡存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多