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<ResolveInfo> 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;
-
- String dexOutputDir = mContext.getApplicationInfo().dataDir;
-
- String libPath = activityInfo.applicationInfo.nativeLibraryDir;
-
-
- 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中的方法
- 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
转自:http://blog.csdn.net/l2show/article/details/40619585