转自http://www.tuicool.com/articles/FneqEjz


Android类装载器DexClassLoader的简单使用-----制作android插件的前奏 - David小硕

时间 2014-04-23 10:54:00   博客园-原创精华区 原文   http://www.cnblogs.com/dividxiaoshuo-fighting/p/3682398.html 主题  安卓开发

声明:此篇文章借鉴《android内核剖析》整理得来。

一、装载器简介

“类装载器”(ClassLoader),顾名思义,就是用来动态装载class文件的。标准的Java SDK中有个ClassLoader类,借助此类可以装载需要的class文件,前提是

ClassLoader类初始化必须制定class文件的路径。

import关键字引用的类文件和ClassLoader动态加载类的区别:

import引用类的两个特点:1、必须存在于本地,当程序运行该类时,内部类装载器会自动装载该类。

2、编译时必须在现场,否则编译过程会因找不到引用文件而不能正常编译。

classLoader的特点正好于import相反,而且更自由灵活。

每一个ClassLoader必须有一个父ClassLoader,在装载Class文件时,子ClassLoader会先请求其父ClassLoader加载该文件,只有当其父ClassLoader找不到该文件时,子ClassLoader才会继承装载该类。这是一种安全机制。对于Android而言,最终的apk文件包含的是dex类型的文件,dex文件是将class文件重新打包,打包的规则又不是简单地压缩,而是完全对class文件内部的各种函数表,变量表进行优化,产生一个新的文件,即dex文件。因此加载这种特殊的Class文件就需要特殊的类加载器DexClassLoader。

二、DexClassLoader的方法的实用

假设有两个apk,第一个叫做Host,第二个叫Plugin。Plugin中第一个一个类Plugin,该类中定义了一个addition函数。

 1 package com.david.plugin; 2  3 import android.util.Log; 4  5 public class Plugin { 6      7     private static final String TAG=Plugin.class.getSimpleName(); 8      9     public Plugin(){10         Log.i(TAG, "PluginClass is initialized");11     }12     13     public int addition(int a,int b){14         return a+b;15     }16     17 }

plugin的apk中AndroidManifest文件中,activity必须声明一个action。

1 <activity2             android:name="com.david.plugin.MainActivity"3             android:label="@string/app_name" >4             <intent-filter>5                 <action android:name="com.david.plugin.client"/>6                 <action android:name="android.intent.action.MAIN" />7                 <category android:name="android.intent.category.LAUNCHER" />8             intent-filter>9         activity>

将plugin.apk装载进Android设备中。Host.apk中主activity调用的代码如下:

 1 package com.david.host; 2  3 import java.lang.reflect.InvocationTargetException; 4 import java.lang.reflect.Method; 5 import java.util.List; 6  7 import dalvik.system.DexClassLoader; 8 import android.support.v7.app.ActionBarActivity; 9 import android.annotation.SuppressLint;10 import android.content.Intent;11 import android.content.pm.ActivityInfo;12 import android.content.pm.PackageManager;13 import android.content.pm.ResolveInfo;14 import android.os.Bundle;15 import android.view.View;16 import android.view.View.OnClickListener;17 import android.widget.Button;18 19 20 public class MainActivity extends ActionBarActivity implements OnClickListener{21 22     private static final String plugin_package = "com.david.plugin.client";23     private PackageManager pm;24     private ResolveInfo resolveInfo;25     private Button btn_classLoader;26 27     @Override28     protected void onCreate(Bundle savedInstanceState) {29         super.onCreate(savedInstanceState);30         setContentView(R.layout.activity_main);31 //        useDexClassLoader();32         btn_classLoader=(Button) findViewById(R.id.btn_classLoader);33         btn_classLoader.setOnClickListener(this);34     }35 36     @SuppressLint("NewApi")37     public void useDexClassLoader() {38         Intent classIntent = new Intent(plugin_package, null);39         pm = getPackageManager();40         List activities = pm.queryIntentActivities(classIntent, 0);41         resolveInfo = activities.get(0);42         ActivityInfo activityInfo = resolveInfo.activityInfo;43 44         String div = System.getProperty("path.separator");45         String packageName = activityInfo.packageName;46         String sourceDir = activityInfo.applicationInfo.sourceDir;47         System.out.println(sourceDir);48         String outDir = getApplicationInfo().dataDir;49         System.out.println(outDir);50         String libraryDir = activityInfo.applicationInfo.nativeLibraryDir;51         System.out.println(libraryDir);52 53         DexClassLoader dexcl = new DexClassLoader(sourceDir, outDir,54                 libraryDir, this.getClass().getClassLoader());55         try {56             Class<?> loadClass = dexcl.loadClass(packageName+".Plugin");57             Object instance = loadClass.newInstance();58             Class[] params = new Class[2];59             params[0]=Integer.TYPE;60             params[1]=Integer.TYPE;61             Method method = loadClass.getMethod("addition", params);62             Integer result = (Integer) method.invoke(instance, 12,32);63             System.out.println(result);64         } catch (ClassNotFoundException e) {65             e.printStackTrace();66         } catch (InstantiationException e) {67             e.printStackTrace();68         } catch (IllegalAccessException e) {69             e.printStackTrace();70         } catch (NoSuchMethodException e) {71             e.printStackTrace();72         } catch (IllegalArgumentException e) {73             e.printStackTrace();74         } catch (InvocationTargetException e) {75             // TODO Auto-generated catch block76             e.printStackTrace();77         } 78 79     }80 81     @Override82     public void onClick(View v) {83         useDexClassLoader();84     }85 }

运行后得到的结果是:

类加载器在应用中还是用到比较多,还可以基于它设计一种“插件”架构。


更多相关文章

  1. Android(安卓)对话框【Dialog】去除白色边框代码
  2. Android(安卓)多媒体扫描过程(Android(安卓)Media Scanner Proces
  3. android webview 自定义404错误页面!
  4. android插件化研究
  5. Android(安卓)读取U盘或SD卡中的所有.txt文件
  6. 面试例题6:两种方法将图像显示在View上
  7. gif文件导出png
  8. 转Android(安卓)安全攻防(一):SEAndroid的编译
  9. NPM 和webpack 的基础使用

随机推荐

  1. ubuntu下无法更新android sdk
  2. Android(安卓)常用编程技巧
  3. android调用cocos2dx例子
  4. Android(安卓)配置 FileProvider
  5. android IP
  6. [置顶] Android学习博客和文章存档
  7. Android(安卓)控件布局常用属性
  8. android 电容屏(二):驱动调试之基本概念篇
  9. android修改底层键值
  10. 修改android 系统设置 android 版本