有時候我們需要使用動态更新技術,簡單來說就是:當我們把開發jar包發送給使用者後,如果後期更新了部分代碼,這時讓使用者的jar包自動更新,而不是使用者主動手動地去更新的技術就是動态更新。這個需要使用的技術之一就是Android動态加載JAR包。
主要的過程分為兩步,一個是将需要導出的java檔案導出位jar包,java檔案代碼如下所示:
package adapter;
public class RoutePlanManager {
private String name = "RoutePlanManager";
public static String get() {
return "hello world";
}
}
導出為Hello.jar,這時我們需要使用Android SDK提供的工具(在platform-tools目錄下),有些版本的沒有,可以網上下載下傳。利用dx工具,将java的jar包轉為Android虛拟機可以認識的位元組碼。具體來說,就是執行如下的指令:
dx --dex --output=dex.jar Hello.jar
其中,Hello.jar是我們的源jar包,dex.jar是我們用dx工具處理後的jar包,是Android虛拟機可以識别的jar檔案,接下來就可以進行第二步操作了。
這裡,我們需要使用DexClassLoader類實作Jar的動态加載,該類構造方法的官方文檔如下所示:
public DexClassLoader (String dexPath, String optimizedDirectory, String libraryPath, ClassLoader parent)
Added in API level 3
Creates a DexClassLoader that finds interpreted and native code. Interpreted classes are found in a set of DEX files contained in Jar or APK files.
The path lists are separated using the character specified by the path.separator system property, which defaults to :.
Parameters
dexPath the list of jar/apk files containing classes and resources, delimited by File.pathSeparator, which defaults to ":" on Android
optimizedDirectory directory where optimized dex files should be written; must not be null
libraryPath the list of directories containing native libraries, delimited by File.pathSeparator; may be null
parent the parent class loader
該接口具有四個參數,第一個是dex.jar包的路徑,第二個可以認為是挂載路徑,就是優化後的dex檔案的存放路徑,對權限有要求,是以需要通過上下文擷取路徑,第三個參數設定為null,第四個代表父親類加載器。
我們在Android中實作動态加載的代碼如下所示:
String sdcard = Environment.getExternalStorageDirectory().getAbsolutePath();
String jarPath = sdcard + "/Jar/dex.jar";
String tmpPath = getApplicationContext().getDir("Jar", 0).getAbsolutePath();
DexClassLoader cl = new DexClassLoader(jarPath, tmpPath
, null, this.getClass().getClassLoader());
Class<?> libProviderCls = null;
try {
libProviderCls = cl.loadClass("adapter.RoutePlanManager");
Constructor<?> localConstructor = libProviderCls.getConstructor(new Class[] {});
Object obj = localConstructor.newInstance(new Object[] {});
Method mMethodWrite = libProviderCls.getDeclaredMethod("get");
mMethodWrite.setAccessible(true);
String str = (String) mMethodWrite.invoke(obj);
Toast.makeText(LoadJarActivity.this, str, Toast.LENGTH_LONG).show();
} catch (Exception e) {
e.printStackTrace();
}
當加載了Jar包之後,我們需要執行Jar包中的方法,這個時候我們需要使用Java的反射來處理。以上就是實作動态加載的方式。