dynamic-load-apk-Apk動態加載框架使用初體驗
因為想要將本網站上的開源代碼直接做成一個能顯示效果的app,決定摸索下android的插件開發,發現只有兩個開源的插件系統可選:
因為第一個只允許在fragment的基礎上開發插件,第二個沒有此限制并且是國人開發,文檔比較齊全,所以選擇了第二個。
下載dynamic-load-apk
dynamic-load-apk 簡稱DL框架,從github上下載DL,如下:
lib是Library,sample是例子程序,打開sample如下:
根據官方的解釋,有三種模式,其中main目錄下才是其推薦的獨立插件模式,所以直接不管depend_on_interface這個文件夾了。
其中main-host是宿主,他需要引用DL的Library才能運行,main-plugin-a,以及main-plugin-b是插件。
運行sample中的宿主和插件
我將main直接import到eclispe中,并且將DL的Library也導入,將main-host添加Library依賴,運行main-host程序,當然了 顯示的是沒有插件,因為main-host程序需要在sdcard的根目錄下建立DynamicLoadHost目錄,然后DynamicLoadHost目錄中放入插件的apk。這主要是因為main-host程序的代碼是這樣寫的:
private void initData() { String pluginFolder = Environment.getExternalStorageDirectory() + "/DynamicLoadHost"; File file = new File(pluginFolder); File[] plugins = file.listFiles(); if (plugins == null || plugins.length == 0) { mNoPluginTextView.setVisibility(View.VISIBLE); return; } for (File plugin : plugins) { PluginItem item = new PluginItem(); item.pluginPath = plugin.getAbsolutePath(); item.packageInfo = DLUtils.getPackageInfo(this, item.pluginPath); if (item.packageInfo.activities != null && item.packageInfo.activities.length > 0) { item.launcherActivityName = item.packageInfo.activities[0].name; } mPluginItems.add(item); DLPluginManager.getInstance(this).loadApk(item.pluginPath); } mListView.setAdapter(mPluginAdapter); mListView.setOnItemClickListener(this); mPluginAdapter.notifyDataSetChanged(); }
pluginFolder
指定為DynamicLoadHost。
當然你自己寫的宿主程序完全可以指定為其他目錄,甚至直接來源于網上(只是猜想),如果不支持直接加載遠程的apk,我們可以先從網上下載下來,放到我們程序指定的一個目錄。
接著我們再運行main-plugin-a,產生一個apk放到剛剛在sdcard建立的DynamicLoadHost目錄。
然后再次打開宿主程序,點擊這個插件,和預期是一致的,插件就像一個apk一樣執行了。
嘗試自己的apk
雖然官方文檔已經說明插件apk需要滿足一些要求(context不能用this,jar不能打包在apk中(主要是DL的jar以及surport的jar)等),但是我還是忍不住要嘗試一下直接把我的apk放進sdcard的DynamicLoadHost目錄,運行宿主程序,列表中能看到我的apk程序,點擊,沒反應。。。。。。。。。
雖然在意料之中,但是小心臟還是小小的失落。
先說下我運行的這個程序叫GossipView,在github上可以下載,因為GossipView非常簡單且具有代表性,沒有依賴其他庫(GossipView是直接在demo中一起的),有activity,有一個自定義的GossipView。對于我準備開發的東西來說,如果這個東西都不能運行,那就沒什么意義了。
我開始改造我的GossipView,讓他可以作為插件了:增加了external-jars 將DL的jar放進去,并且將surport的jar也放進去,同時在.classpath中追加如下兩句:
<classpathentry kind="lib" path="external-jars/dl-lib.jar"/>
<classpathentry kind="lib" path="external-jars/android-support-v4.jar"/>
這樣,編譯的時候就能夠正常進行,但是打包的時候,就不會把上面兩個jar包打入到插件apk中。
接下來不是要改this為that嗎,改唄,我發現我的activity中只有一處用了this,替換成that,運行。得到了一個apk,但是很奇怪的是我的插件居然能直接運行,不是說那樣做兩個jar不會被打包進去嗎怎么還能運行了呢。。。。
管他的哦,先將這次的apk放進去再說。
運行宿主,點開我的插件,報錯了:
看來還真的是包多了,也就是說我的插件apk中其實把DL和surport的jar打包進去了。
我找啊找啊找,發現是自己粗心了,我在插件項目中添加了兩次DL,一次是用jar,一次是直接添加了Library的依賴。fuck。
好吧改過來之后,完全可以了,只是原本我應用的白色背景變成了黑色背景。