android 動態載入sd卡的jar檔案
下面以一個例子列出Android程式執行時動態載入sd卡jar包的步驟:
1. 首先要準備好jar包。
本例中要對com.test.dynamic包進行打包,com.test.dynamic包下面有一個MyClass類.程式碼如下:
- package com.test.dynamic;
- import android.util.Log;
- publicclass MyClass {
- public MyClass() {
- Log.d("com.test.dynamic", "MyClass:constructor called");
-
}
- publicvoid doSomething() {
- Log.d("com.test.dynamic", "MyClass:doSomething called");
- }
- }
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,程式碼如下:
- package com.dynamicLoading;
- import java.io.File;
- import java.lang.reflect.Method;
- import dalvik.system.DexClassLoader;
- import android.annotation.SuppressLint;
- import android.app.Activity;
- import android.os.Bundle;
- import android.os.Environment;
- publicclass Main extends Activity {
- @SuppressLint("NewApi")
- @Override
- protectedvoid onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- String libPath = Environment.getExternalStorageDirectory()+ File.separator + "dynamic.jar"; // 要動態載入的jar
- File dexDir = getDir("dex", MODE_PRIVATE); // 優化後dex的路徑
- /**
- * 進行動態載入,利用java的反射呼叫com.test.dynamic.MyClass的方法
- */
- DexClassLoader classLoader = new DexClassLoader(libPath, dexDir.getAbsolutePath(), null, getClassLoader());
- try {
- Class<Object> cls = (Class<Object>) classLoader.loadClass("com.test.dynamic.MyClass");
- Object object = cls.newInstance();
- Method method = cls.getMethod("doSomething", null);
- method.invoke(object, null);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
程式執行後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()
大家有什麼問題或者意見可以和我交流~