? ? ? ? 最近項目有一個需求,需要根據用戶需求動態加載APP內某功能模塊,且當該部分功能模塊代碼有變動,只需更新該功能JAR,無需更新整個APK,基于這個需求,決定采用動態加載Jar的方式去實現,于是各種查資料進行驗證,終于搞定,由于最近腦子容量不夠,所以將實現方式整理出來并開放給大家進行參考。
實現過程需要注意的點:
1、當我們實現功能的Library工程中還依賴了其他第三方Jar,我們需要將其合并,否則你生成的Library對應的Jar包不含第三方文件會報錯;
2、Android的虛擬機(Dalvik VM)是無法識別Java打出jar的class文件,DVM識別的是dex文件,所以需要通過dx工具轉換成包含有dex文件的jar;
所以整個過程可以分為以下三個步驟來實現:
第一步:創建Library工程,導出Jar;
第二步:將主Jar和依賴Jar進行合并(ANT),將合并后的Jar進行DX處理;
第三步:利用DexClassLoader動態加載;
下面通過一個例子來介紹具體實現,首先看一下整個項目組成部分:
app:主工程Module;
commoninterfacelibrary:用于定義標準接口,供主項目集成,第三方實現具體功能;
dynamiclibrary:第三方實現功能庫,在主項目中,動態加載該庫;
utillibrary:工具庫,模擬動態加載庫中引用的第三方類庫;
一、生成Jar
1、在commoninterfacelibrary中定義通用接口及方法:
定義完成后,生成common_interface.jar;
注:生成jar包方法比較簡單,直接Build——>Make Project后,在build/intermediates/bundles/debug下找到classes.jar進行重命名。
2、將common_interface.jar拷貝到dynamiclibrary項目app/libs下,然后在dynamiclibrary下的gradle中添加對此jar的依賴:
定義ICommonInterface的實現類DynamicImp并實現具體方法:
注:MathUtil是定義在utillibrary下的一個工具類,生成出common_util.jar后拷貝到dynamiclibrary進行依賴,此處實現比較簡單忽略該步。
按照上面生成jar的方法,生成出dynamiclibrary對應的dynamic.jar;
經過上述步驟后,我們得到三個jar包,分別是:
common_interface.jar? 定義了標準接口;
common_util.jar 定義了工具類;
dynamic.jar 標準接口的實現類,我們需要動態加載的jar;
二、合并JAR并使用DX工具處理JAR包
? ? ? ? 下面我們開始介紹合并Jar的流程,由于common_interface.jar是標準接口,我們會在主項目中引用,所以不需要合并它,我們只需要合并common_util.jar和dynamic.jar。
? ? ? ? 對于合并Jar的方式,網上有很多方式,如fatjar插件、或者用IDEA工具,具體操作方法自行百度,我這里用的是ANT合并的方式,首先我們需要安裝并配置ANT環境:
ANT下載官網地址:http://ant.apache.org/bindownload.cgi
下載完成后,解壓,然后在我的電腦 –> 右鍵屬性 –> 高級系統配置 -> 環境變量中配置ANT:
然后加入到系統變量的path中:
驗證ANT環境是否已配置好:
看到上面的信息,證明ANT配置成功,下面來合并包,將需要合并的jar包放在同一個文件夾下,了解ant的都知道,ant構建的文件默認為build.xml,所以在文件夾下我們還需要創建該文件,并進行如下配置:
name? : 表示的是你即將合成的jar包的名字 ;
basedir :? 表示你存放jar包的目錄;
上面配置文件的含義就是,將當前目錄下所有jar進行合并,并在該目錄下載生成名字為dynamic_combine.jar的新包,文件配置好后,執行下面的命令:
執行成功后,我們需要將該jar包使用dx工具進行轉化:
將合并后的jar包拷貝到android-sdk/buildtools下的任意一個版本目錄下,執行“dx --dex --output=dynamic_combine_dx.jar dynamic_combine.jar”
三、動態加載
執行成功后,我們得到最終的dynamic_combine_dx.jar,下面我們可以在主項目中進行動態加載了,通過兩步來介紹動態加載過程:
1、下載dynamic_combine_dx.jar到SD卡:
首先將dynamic_combine_dx.jar拷貝到app/assets下(這里是為了模擬下載過程,實際項目中可配置到后臺,從后臺下載)
注:需在manifest添加權限
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
2、下載到SD卡成功后,進行動態加載調用相應方法:
先執行下載方法,后執行加載方法:
執行結果為:
成功,撒花!??!