small的插件化的基本使用

small的插件化

最近在看插件化的相關(guān)內(nèi)容童漩,就研究了一下非臣ㄖ裕火的small插件化(Github地址:https://github.com/wequick/Small), 這篇文章主要分析small插件化的Sample的主要的開發(fā)步驟,和插件化的基本的使用淘正,原理會在后來的文章中持續(xù)更新古徒。
1.插件化和組件化
組件化和插件化開發(fā)上其實(shí)大體思路是差不多拓提,但是還是有本質(zhì)上的區(qū)別。組件化開發(fā)就是將一個項(xiàng)目app拆分成多個模塊隧膘,每個模塊都是一個組件代态,組件化開發(fā)過程中相互依賴或單獨(dú)調(diào)試,最終發(fā)布的時候是將這些組件合并統(tǒng)一成一個apk疹吃。插件化開發(fā)也是將一個項(xiàng)目app拆分成多個模塊蹦疑,這些模塊包括宿主和插件。本質(zhì)上插件化開發(fā)的每個模塊相當(dāng)于一個apk萨驶,而組件化相當(dāng)于一個個lib歉摧。插件化最終發(fā)布的時候?qū)⑺拗鱝pk和插件apk單獨(dú)打包或者聯(lián)合打包,而組件化則是把所有的lib打包成一個apk。

2.插件化的作用

①.并發(fā)開發(fā) 各個模塊之間可以單獨(dú)開發(fā)叁温,極大地提高了開發(fā)效率
②.動態(tài)更新插件或者遠(yuǎn)端調(diào)試 app每次啟動回去校驗(yàn)是否有插件更新再悼,有的話,就去服務(wù)器上下載最新的插件替換掉已有的膝但。熱修復(fù)其實(shí)是插件化的一個小小的應(yīng)用冲九。
③.按需下載模塊 其實(shí)和2的思路一樣,也屬于動態(tài)加載的功能跟束,例如可能一個apk我們對于不同的賬號設(shè)置了不同的權(quán)限莺奸,相應(yīng)的就會有不同的功能模塊對于不同的權(quán)限人員。
④.可以針對不同的早期設(shè)計(jì)推出不同的版本冀宴,觀察用戶的使用反饋灭贷,來確定最終的版本。

3.small插件化的開發(fā)步驟(這兩種開發(fā)方式Github上都有相關(guān)的說明)

(1) 手動創(chuàng)建工程
①. Create Project

File->New->New Project...

②.加入Small編譯庫

1.加入classpath

classpath 'net.wequick.tools.build:gradle-small:1.0.0-alpha2'

apply plugin: 'net.wequick.small'

2.配置Small DSL (可選)

small {
aarVersion = '1.1.0-beta5'
}

③.創(chuàng)建Moudle

File->New->Module來創(chuàng)建插件模塊花鹅,需要滿足:

模塊名形如:app., lib.或者web.*
包名包含:.app., .lib.或者.web.

命名規(guī)則如下:
app 宿主工程
app.* 包含Activity/Fragment的組件
lib.* 公共庫組件
web.* 本地網(wǎng)頁組件
sign 簽名文件

為什么要這樣氧腰?因?yàn)镾mall會根據(jù)包名對插件進(jìn)行歸類,特殊的域名空間如:“.app.” 會讓這變得容易刨肃。

④. Configure UI route

右鍵app模塊->New->Folder->Assets Folder古拴,新建assets目錄,

右鍵assets目錄->New->File真友,新建bundle.json文件黄痪,加入:

{
  "version": "1.0.0",
  "bundles": [
        {
          "uri": "main",
              "pkg": "com.example.mysmall.app.main"
        }
      ]
}

使用uri定位,加載插件中的Activity或者Fragment

⑤.配置apk的簽名

⑥.在宿主App中初始化Small

Small.preSetUp(this);

⑦.加載插件

重載宿主Activity的onStart()方法盔然。

Small.setBaseUri("http://example.com/");
Small.setUp(this, new net.wequick.small.Small.OnCompleteListener() {

    @Override
    public void onComplete() {
        Small.openUri("main", LaunchActivity.this);//啟動默認(rèn)的Activity桅打,參考wiki中的UI route啟動其他Activity
    }
});

(1)使用模板創(chuàng)建工程

①.導(dǎo)入工程模板
②.新建宿主Activity的時候選擇@Small模板,修改build.gradle文件引入small

buildscript {
dependencies {
classpath 'net.wequick.tools.build:gradle-small:1.0.0-alpha2'
}
}

apply plugin: 'net.wequick.small'

small {
aarVersion = '1.1.0-beta5'
}

③.新建插件的app愈案,在as中和普通的創(chuàng)建moudle的方式一樣

④.gradle進(jìn)行打包的相關(guān)操作]gradlew buildLib -q(準(zhǔn)備基礎(chǔ)庫) gradlew buildBundle -q(打包所有組件)挺尾。

⑤在插件的app中加載其他的插件頁面 Small.openUri("detail?from=app.home", getContext());
插件之間的通信用本地廣播。

4.small到底在做了什么站绪,可以讓我們動態(tài)的加載看似沒有太多聯(lián)系的apk中的文件遭铺?

難道我們所有的apk都被安裝了,打開手機(jī)的所有應(yīng)用程序并沒有發(fā)現(xiàn)有除了宿主之外的其他的apk被安裝恢准,打開我們的app工程也就是入口工程魂挂,可以看到我們正常開發(fā)有所不同的是,文件夾里多了一個smallLibs文件夾馁筐,可以看到里面有一個armeabi文件涂召,發(fā)現(xiàn)里面是.so文件,看一下文件的后綴名敏沉,app_main.so(對應(yīng)我們工程的app.main),app_home.so(對應(yīng)我們工程的app.home).....,其實(shí)就是通過buildLib和buildBundle來把非宿主的app中的文件打包為.so文件果正,我們最終安裝到手機(jī)上的apk其實(shí)就是只有宿主的apk和其內(nèi)部的.so文件炎码,通過加載.so文件來實(shí)現(xiàn)加載插件中的文件。但是當(dāng)我們安裝到電腦模擬器的過程中會出現(xiàn)一個異常舱卡,如下圖:


關(guān)于這一點(diǎn)是因?yàn)樵谖覀兊哪M器上的CPU架構(gòu)的問題辅肾,因?yàn)槲覀儎?chuàng)建模擬器的時候會有選擇讓我們選擇是選擇armeabi還是x86類型的模擬器队萤,目前手機(jī)處理器主要是高通和三星轮锥,MTK,華為等要尔,主要用的都是ARM公司的arm架構(gòu)舍杜,而英特爾公司也有自己的手機(jī)處理器,他用的是x86的架構(gòu)赵辕,目前很多平板產(chǎn)品在使用既绩。而small產(chǎn)生的.so文件默認(rèn)是產(chǎn)生在armeabi文件夾的,而我們創(chuàng)建模擬器的過程中还惠,一般都會選擇x86架構(gòu)的饲握,因?yàn)槲覀冸娔X的CPU都是x86架構(gòu)的,能讓模擬器的速度飛快蚕键,但是當(dāng)我們安裝的small的Sample的過程中救欧,則會出錯,所以我們的解決方法就是在libs目錄下新建一個x86的文件夾锣光,然后把我們aremabi文件夾下的.so文件全部復(fù)制到x86文件夾下就可以了笆怠。如下圖所示我們創(chuàng)建的模擬器時選擇架構(gòu)的問題:

我們自己開發(fā)的過程中,通過 gradlew buildLib -q(準(zhǔn)備基礎(chǔ)庫) gradlew buildBundle -q(打包所有組件) 的操作誊爹,我們也就可以看到在我們的宿主app的目錄下產(chǎn)生一個smallLibs目錄蹬刷,里面的armeabi的文件中就有有我們的非宿主的插件中的文件產(chǎn)生的.so文件。

5.small的動態(tài)加載和實(shí)現(xiàn)熱修復(fù)是如何實(shí)現(xiàn)的频丘?

我們打開Sample的主頁面

可以看到有一個更新的按鈕办成,但是點(diǎn)擊后好像并沒有什么效果,打開Sample工程中的相關(guān)按鈕操作的邏輯部分搂漠,有一個這樣的方法


      private void requestUpgradeInfo(Map versions, OnResponseListener listener) {
                System.out.println(versions); // this should be passed as HTTP parameters
                mResponseHandler = new ResponseHandler(listener);
                new Thread() {
                    @Override
                    public void run() {
                        try {
                            // Example HTTP request to get the upgrade bundles information.
                            // Json format see http://wequick.github.io/small/upgrade/bundles.json
                            URL url = new URL("http://wequick.github.io/small/upgrade/bundles.json");
                            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                            StringBuilder sb = new StringBuilder();
                            InputStream is = conn.getInputStream();
                            byte[] buffer = new byte[1024];
                            int length;
                            while ((length = is.read(buffer)) != -1) {
                                sb.append(new String(buffer, 0, length));
                            }
                            // Parse json
                            JSONObject jo = new JSONObject(sb.toString());
                            JSONObject mf = jo.has("manifest") ? jo.getJSONObject("manifest") : null;
                            JSONArray updates = jo.getJSONArray("updates");
                            int N = updates.length();
                            List<UpdateInfo> infos = new ArrayList<UpdateInfo>(N);
                            for (int i = 0; i < N; i++) {
                                JSONObject o = updates.getJSONObject(i);
                                UpdateInfo info = new UpdateInfo();
                                info.packageName = o.getString("pkg");
                                info.downloadUrl = o.getString("url");
                                infos.add(info);
                            }
    
                            // Post message
                            UpgradeInfo ui = new UpgradeInfo();
                            ui.manifest = mf;
                            ui.updates = infos;
                            Message.obtain(mResponseHandler, 1, ui).sendToTarget();
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }.start();
            }

可以看到其內(nèi)部有一個url迂卢,然后我們打開url看一下里面是什么東西


可以看到底部有一個updates數(shù)組,然后數(shù)組內(nèi)部是.so文件的地址状答,然后我們在看一下代碼中的下載的部分冷守,下載的核心部分是requestUpgradeInfo()這個方法。

里面主要是通過http請求獲取服務(wù)器bundles.json這個文件惊科,然后去解析json.把信息存儲到UpgradeInfo里面拍摇。mResponseHandler完成回調(diào)

然后就是調(diào)用upgradeBundles方法。我們跟進(jìn)去看看馆截,這個方法具體做什么充活。

這個方法主要是校驗(yàn)服務(wù)器上bundles.json的信息蜂莉,然后開始下載插件和加載插件。插件下載完成后我們就實(shí)現(xiàn)了動態(tài)的更新操作混卵。

我們開發(fā)的過程中怎么實(shí)現(xiàn)插件化的動態(tài)更新呢映穗,我們可以在我們的原有的工程中直接修改代碼,使用small的命令的打包后取出.so文件幕随,然后將.so文件上傳到我們的目標(biāo)服務(wù)器地址就可以了蚁滋,我們的程序就可以實(shí)現(xiàn)動態(tài)的更新,其實(shí)這個.so文件你可以直接解壓赘淮,發(fā)現(xiàn)解壓后的格式和我們apk直接解壓后格式是一樣的辕录。

基本的用法就先到這里,small原理我們團(tuán)隊(duì)有不同的人在研究梢卸,后續(xù)可以更新走诞。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市蛤高,隨后出現(xiàn)的幾起案子蚣旱,更是在濱河造成了極大的恐慌,老刑警劉巖戴陡,帶你破解...
    沈念sama閱讀 219,188評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件塞绿,死亡現(xiàn)場離奇詭異,居然都是意外死亡猜欺,警方通過查閱死者的電腦和手機(jī)位隶,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,464評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來开皿,“玉大人涧黄,你說我怎么就攤上這事「尘#” “怎么了笋妥?”我有些...
    開封第一講書人閱讀 165,562評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長窄潭。 經(jīng)常有香客問我春宣,道長,這世上最難降的妖魔是什么嫉你? 我笑而不...
    開封第一講書人閱讀 58,893評論 1 295
  • 正文 為了忘掉前任月帝,我火速辦了婚禮,結(jié)果婚禮上幽污,老公的妹妹穿的比我還像新娘嚷辅。我一直安慰自己,他們只是感情好距误,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,917評論 6 392
  • 文/花漫 我一把揭開白布簸搞。 她就那樣靜靜地躺著扁位,像睡著了一般。 火紅的嫁衣襯著肌膚如雪趁俊。 梳的紋絲不亂的頭發(fā)上域仇,一...
    開封第一講書人閱讀 51,708評論 1 305
  • 那天,我揣著相機(jī)與錄音寺擂,去河邊找鬼暇务。 笑死,一個胖子當(dāng)著我的面吹牛沽讹,可吹牛的內(nèi)容都是我干的般卑。 我是一名探鬼主播,決...
    沈念sama閱讀 40,430評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼爽雄,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了沐鼠?” 一聲冷哼從身側(cè)響起挚瘟,我...
    開封第一講書人閱讀 39,342評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎饲梭,沒想到半個月后乘盖,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,801評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡憔涉,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,976評論 3 337
  • 正文 我和宋清朗相戀三年订框,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片兜叨。...
    茶點(diǎn)故事閱讀 40,115評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡穿扳,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出国旷,到底是詐尸還是另有隱情矛物,我是刑警寧澤,帶...
    沈念sama閱讀 35,804評論 5 346
  • 正文 年R本政府宣布跪但,位于F島的核電站履羞,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏屡久。R本人自食惡果不足惜忆首,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,458評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望被环。 院中可真熱鬧糙及,春花似錦、人聲如沸蛤售。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,008評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至揣钦,卻和暖如春雳灾,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背冯凹。 一陣腳步聲響...
    開封第一講書人閱讀 33,135評論 1 272
  • 我被黑心中介騙來泰國打工谎亩, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人宇姚。 一個月前我還...
    沈念sama閱讀 48,365評論 3 373
  • 正文 我出身青樓匈庭,卻偏偏與公主長得像,于是被迫代替她去往敵國和親浑劳。 傳聞我的和親對象是個殘疾皇子阱持,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,055評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 1.框架的選擇:本次選擇的插件化框架在經(jīng)過數(shù)次比較之后選擇了國產(chǎn)大神開發(fā)的目前在市場上較為流行的small插件化框...
    鳳天凌閱讀 3,529評論 8 11
  • 最近幾年移動開發(fā)業(yè)界興起了「 插件化技術(shù) 」的旋風(fēng),各個大廠都推出了自己的插件化框架魔熏,各種開源框架都評價自身功能優(yōu)...
    斜杠時光閱讀 3,947評論 1 36
  • 引言 先簡單介紹一下Android插件化衷咽。很早之前已經(jīng)有公司在研究這項(xiàng)技術(shù),淘寶做得比較早蒜绽,但淘寶的這項(xiàng)技術(shù)一直是...
    流水潺湲閱讀 11,347評論 8 149
  • 蒲公英隨風(fēng)飄散镶骗,落到了小樹苗的身上。蒲公英愉快地打著招呼:“嗨躲雅,小樹苗你好啊鼎姊。”小樹苗看著蒲公英一時入了迷相赁,許久才...
    這個是真帥氣的昵稱閱讀 212評論 0 0
  • 你想要的是什么相寇,二十多年來一直在想這個問題,可能有些人一輩子也想不明白自己到底想要的是什么噪生,人在路上裆赵,心在路上,沉...
    蛇精譚小美閱讀 144評論 0 1