1. 程式人生 > >android 動態載入sd卡的jar檔案

android 動態載入sd卡的jar檔案

下面以一個例子列出Android程式執行時動態載入sd卡jar包的步驟:

1. 首先要準備好jar包。

本例中要對com.test.dynamic包進行打包,com.test.dynamic包下面有一個MyClass類.程式碼如下:

  1. package com.test.dynamic;  
  2. import android.util.Log;  
  3. publicclass MyClass {  
  4.     public MyClass() {  
  5.         Log.d("com.test.dynamic""MyClass:constructor called");  
  6.     }  
  7.     publicvoid doSomething() {  
  8.         Log.d("com.test.dynamic""MyClass:doSomething called");  
  9.     }  
  10. }  

eclipse中選擇com.test.dynamic包,使用export匯出得到test.jar. 接下來一定不能忘記使用dx命令對test.jar處理,否則的話會報Java.lang.ClassNotFoundException異常.dx命令位於sdk\build-tools\android-4.4W下面(android-4.4W是android的一個版本,其他android版本下面也能找到dx.bat). cmd命令列模式下進入dx.bat所在目錄,使用dx --dex --output=dynamic.jar test.jar ,dynamic.jar是對test.jar處理後得到的jar檔案.

重要:

dx.bat命令使用示例如下:dx.bat --dex --output=輸出.jar 輸入.jar。

2. 把dynamic.jar 拷貝到手機的sd卡目錄下,刪除掉eclipse專案中的com.test.dynamic包

不同的手機sd卡目錄不太一樣,比如本人使用的魅族3手機sd卡目錄是\storage\emulated\0.如果不知道手機sd卡目錄的話,大家可以列印Environment.getExternalStorageDirectory()資訊來檢視sd卡目錄.

3.android程式執行時動態載入sd卡中的jar包

下面簡單寫了一個Activity來動態載入jar,程式碼如下:

  1. package com.dynamicLoading;  
  2. import java.io.File;  
  3. import java.lang.reflect.Method;  
  4. import dalvik.system.DexClassLoader;  
  5. import android.annotation.SuppressLint;  
  6. import android.app.Activity;  
  7. import android.os.Bundle;  
  8. import android.os.Environment;  
  9. publicclass Main extends Activity {  
  10.     @SuppressLint("NewApi")  
  11.     @Override
  12.     protectedvoid onCreate(Bundle savedInstanceState) {  
  13.         super.onCreate(savedInstanceState);  
  14.         setContentView(R.layout.activity_main);  
  15.         String libPath = Environment.getExternalStorageDirectory()+ File.separator + "dynamic.jar"// 要動態載入的jar 
  16.         File dexDir = getDir("dex", MODE_PRIVATE); // 優化後dex的路徑
  17.         /** 
  18.          * 進行動態載入,利用java的反射呼叫com.test.dynamic.MyClass的方法 
  19.          */
  20.         DexClassLoader classLoader = new DexClassLoader(libPath, dexDir.getAbsolutePath(), null, getClassLoader());  
  21.         try {  
  22.             Class<Object> cls = (Class<Object>) classLoader.loadClass("com.test.dynamic.MyClass");  
  23.             Object object = cls.newInstance();  
  24.             Method method = cls.getMethod("doSomething"null);  
  25.             method.invoke(object, null);  
  26.         } catch (Exception e) {  
  27.             e.printStackTrace();  
  28.         }  
  29.     }  
  30. }  


程式執行後logcat打印出如下的資訊,說明動態載入jar包成功:


下面對程式碼進行分析,

DexClassLoader的建構函式DexClassLoader(String dexPath,String optimizedDirectory,String libraryPath, ClassLoader parent)需要傳入四個引數.第一個引數dexPath是dex檔案的路徑,在本例當中是dynamic.jar的路 徑. optimizedDirectory是優化後的dex檔案的路徑,optimizedDirectory一定不能為null,官方文件上不建議把優化後的dex檔案存放在外存,本例當中優化後的app_dex存放在/data/data/packagename/目錄下(app_是android系統自動加的字首). libraryPath是包含原生庫的路徑,可為null,本例中傳的就是null。parent引數是父載入器.本例的大致流程:系統對sd卡下的dynamic.jar包進行動態載入,loadClass方法返回一個Class物件,利用java的反射機制呼叫MyClass當中的方法doSomething()

大家有什麼問題或者意見可以和我交流~