1.Java和Android中的类加载器的区别
Java:ClassLoaderAndroid:DexClassLoader
2.DexClassLoader使用
实例:应用程序MyHost调用应用程序MyPlugin中PluginClass类中的方法invoke()步骤:
1)创建MyPlugin应用程序:按正常的创建应用的步骤创建应用程序MyPlugin
2)在MyPlugin中创建PluginClass类:如下代码(去除import)
public class PluginClass {private static final String tag = PluginClass.class.getSimpleName();
public PluginClass() {
Log.i(tag, "initialized");
}
public void invoke(String s) {
Log.i(tag, s);
}
}
3)将MyPlugin应用程序运行在Android设备上
4)创建MyHost应用程序:按正常的创建应用的步骤创建应用程序MyHost
5)在MyHost中创建MyHost类
public class MyHost {private static final String tag = MyHost.class.getSimpleName();
private Context mContext = null;
public MyHost(Context context) {
this.mContext = context;
}
public String useDexClassLoader() {
String result = null;
Intent intent = new Intent();
intent.setPackage("com.mokee.myplugin");
PackageManager pm = mContext.getPackageManager();
List<ResolveInfo> plugins = pm.queryIntentActivities(intent, 0);
if(plugins.size() <= 0) {
Log.i(tag, "Resolve Info List size is :" + plugins.size());
return null;
}
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++的库文件的存放路径
result = "div:" + div + " " +
"packageName:" + packageName + " " +
"dexPath:" + dexPath + " " +
"dexOutputDir:" + dexOutputDir + " " +
"libPath:" + libPath;
Log.i(tag, result);
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) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return result;
}
}
6)在MyHost应用程序的MainActivity中初始化MyHost类,并调用useDexClassLoader方法,同时接受返回值,将返回值显示在TextView控件上。代码如下:
public class MainActivity extends Activity {private TextView show;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
show = (TextView) findViewById(R.id.show);
MyHost host = new MyHost(this);
String hostResult = host.useDexClassLoader();
show.setText(hostResult);
}
}