在 Java 裡面,我們可以把一些類放到 .jar 檔案裡面,然後用 ClassLoader 動態載入。例如:
URLClassLoader ucl = URLClassLoader.newInstance(new URL[]{new URL("file:/sdcard/files/test.jar")});<br />Class clazz = ucl.loadClass("com.test.TestClass");<br />
但是在 Android 上面,情況有所不同。
首先第一個是 jar 檔案的製作,Java 裡面直接把 .class 檔案打包到 .jar 檔案裡面就可以了,但是 Android
的 Dalvik VM 是不認 Java 的 byte code
的,所以不能直接這麼打包,而要用 dx 工具轉成 Dalvik byte code 才可以。當然,dx 工具轉了之後,jar 包裡面就不
是 .class 檔案了,而是 .dex 檔案。關於這一點可以參考我的另外一篇文章:http://blog.csdn.net/quaful
/archive/2010/12/23/6094940.aspx
第二個是,Android 裡面雖然也提供了 URLClassLoader 的實現,但是並不能用。要動態載入其它類,可以用的 Class Loader 有:
DexClassLoader
PathClassLoader
其中,DexClassLoader 可以載入 apk, jar 或者 dex 檔案,例如:
File jarFile = new File("/sdcard/test.dex");<br /># if ( jarFile.exists() ) {<br />DexClassLoader cl = new DexClassLoader(jarFile.toString(), "/sdcard/test", null, ClassLoader.getSystemClassLoader());<br />Class<?> c = cl.loadClass("com.qihoo360.test.Test");<br />}
但是 DexClassLoader 要求指定一個可寫的目錄,即 DexClassLoader 建構函式的第二個參數,在上例中是 /sdcard/test
這個參數的含義是:directory where optimized DEX files should be written
因為 Dalvik 在載入 dex 檔案時,會動態進行最佳化,DexClassLoader 要求指定最佳化後 dex 檔案存放的位置。
PathClassLoader 的限制要更多一些,它只能載入已經安裝到 Android 系統中的 apk 檔案,也就是 /data/app 目錄下的 apk 檔案。其它位置的檔案載入的時候都會出現 ClassNotFoundException. 例如:
PathClassLoader cl = new
PathClassLoader(jarFile.toString(), "/data/app/"
, ClassLoader.getSystemClassLoader());
為什麼有這個限制呢?我認為這其實是當前 Android 的一個 bug, 因為 PathClassLoader 會去讀取
/data/dalvik-cache 目錄下的經過 Dalvik 最佳化過的 dex 檔案,這個目錄的 dex 檔案是在安裝 apk 包的時候
由 Dalvik 產生的。例如,如果包的名字是 com.qihoo360.test,Android 應用安裝之後都儲存在 /data/app 目
錄下,即 /data/app/com.qihoo360.test-1.apk,那麼 /data/dalvik-cache 目錄下就會產生
data@app@com.qihoo360.test-1.apk@classes.dex 檔案。在調用 PathClassLoader 時,它就
會按照這個規則去找 dex 檔案,如果你指定的 apk 檔案是 /sdcard/test.apk,它按照這個規則就會去讀 /data
/dalvik-cache/sdcard@test.apk@classes.dex 檔案,顯然這個檔案不會存在,所
以 PathClassLoader 會報錯。
在 Google 修正這個問題之前,我們要麼就只能用 DexClassLoader,要麼就只能用 PathClassLoader 載入已安裝的 apk 了。
轉自http://blog.csdn.net/quaful/archive/2010/12/24/6096951.aspx