Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android 使用DexClassLoader來運行其他apk中的方法

Android 使用DexClassLoader來運行其他apk中的方法

編輯:關於Android編程

Android中apk文件裡的dex文件是對java編譯出來的.class文件進行重新打包,當然在打包之前會利用自己的協議做一些數據處理,例如優化函數表和變量表。在java程序中是使用classloader來加載這些編譯生成的.class文件,然而在android程序中是通過DexClassLoader來裝載這些文件的.這裡我們就可以通過DexClassLoader在程序A裡面動態裝載程序B中的類,並且來調用B程序中的方法.


1.首先先建立一個普通的Android工程,在這個工程中定義一個叫做plugin的類,類中實現一個簡單的方法,如下所示:

public class PluginClass {
	private static String TAG = PluginClass.class.getSimpleName();
	public PluginClass(){
		Log.i(TAG, "initialized");
	}
	public void invoke(String s){
		Log.i(TAG, s);
	}
}
2.將這個Android工程運行到安卓設備當中去

3.再重新建立一個Android工程,其中定義一個叫做host的類,在這個類中實現DexClassLoader動態加載第一個工程中的plugin類,如下所示:

public class HostClass {
	private static String TAG = HostClass.class.getSimpleName();
	private Context mContext = null;
	public HostClass(Context contect){
		mContext = contect;
	}
	public void useDexClassLoader(){
		Intent intent = new Intent();
		intent.setPackage("com.example.plugin");
		PackageManager pm = mContext.getPackageManager();
		final List plugins = pm.queryIntentActivities(intent,0);
		if(plugins.size() <= 0){
			Log.i(TAG, "resolve info size is:" + plugins.size());
			return;
		}
		ResolveInfo resolveInfo = plugins.get(0);
		ActivityInfo activityInfo = resolveInfo.activityInfo;
		
		String div = System.getProperty("path.separator");
		String packageName = activityInfo.packageName;
		String dexPath = activityInfo.applicationInfo.sourceDir;
		//目標類所在的apk或者jar的路徑,class loader會通過這個路徑來加載目標類文件
		String dexOutputDir = mContext.getApplicationInfo().dataDir;
		//由於dex文件是包含在apk或者jar文件中的,所以在加載class之前就需要先將dex文件解壓出來,dexOutputDir為解壓路徑
		String libPath = activityInfo.applicationInfo.nativeLibraryDir;
		//目標類可能使用的c或者c++的庫文件的存放路徑
		
		Log.i(TAG, "div:" + div + "   " + 
					"packageName:" + packageName + "   " +
					"dexPath:" + dexPath + "   " +
					"dexOutputDir:" + dexOutputDir + "   " +
					"libPath:" + libPath);
		
		DexClassLoader dcLoader = new DexClassLoader(dexPath,dexOutputDir,libPath,this.getClass().getClassLoader());
		try {
			Class clazz = dcLoader.loadClass(packageName + ".PluginClass");
			Object obj = clazz.newInstance();
			Class[] param = new Class[1];
			param[0] = String.class;
			Method action = clazz.getMethod("invoke", param);
			action.invoke(obj, "test this function");
		} catch (ClassNotFoundException e) {
			Log.i(TAG, "ClassNotFoundException");
		} catch (InstantiationException e) {
			Log.i(TAG, "InstantiationException");
		} catch (IllegalAccessException e) {
			Log.i(TAG, "IllegalAccessException");
		} catch (NoSuchMethodException e) {
			Log.i(TAG, "NoSuchMethodException");
		} catch (IllegalArgumentException e) {
			Log.i(TAG, "IllegalArgumentException");
		} catch (InvocationTargetException e) {
			Log.i(TAG, "InvocationTargetException");
		}
	}
}
4.運行第二個工程之後查看log就會發現host通過DexClassLoader加載了pluginclass類,並成功調用了plugin中的方法
I/HostClass( 8341): div::   packageName:com.example.plugin   dexPath:/data/app/com.example.plugin-1.apk   dexOutputDir:/data/data/com.example.host   libPath:/data/app-lib/com.example.plugin-1
D/dalvikvm( 8341): DexOpt: --- BEGIN 'com.example.plugin-1.apk' (bootstrap=0) ---
D/dalvikvm( 8341): DexOpt: --- END 'com.example.plugin-1.apk' (success) ---
D/dalvikvm( 8341): DEX prep '/data/app/com.example.plugin-1.apk': unzip in 39ms, rewrite 723ms
I/PluginClass( 8341): initialized
I/PluginClass( 8341): test this function
D/libEGL  ( 8341): loaded /system/lib/egl/libEGL_mali.so
D/libEGL  ( 8341): loaded /system/lib/egl/libGLESv1_CM_mali.so
D/libEGL  ( 8341): loaded /system/lib/egl/libGLESv2_mali.so
D/OpenGLRenderer( 8341): Enabling debug mode 0
I/HostClass( 8341): div::   packageName:com.example.plugin   dexPath:/data/app/com.example.plugin-1.apk   dexOutputDir:/data/data/com.example.host   libPath:/data/app-lib/com.example.plugin-1
I/PluginClass( 8341): initialized
I/PluginClass( 8341): test this function


  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved