我有两个项目,让我们说projectMain和projectPlugin。 我有一个接口类。
这是接口类代码:
package com.far.lib;
public interface IPlugin {
public String getNamaModul();
public String getNamaPaket();
}
我使用projectMain作为projectPlugin的库项目。 我创建了一个实现projectMain接口类的类,这里是代码:
package com.example.helloworld.plugin;
public class PluginHelloWorld implements com.far.lib.IPlugin{
@Override
public String getNamaModul() {
// TODO Auto-generated method stub
return "Modul Hello World";
}
@Override
public String getNamaPaket() {
// TODO Auto-generated method stub
return "com.example.helloworld";
}
}
然后我编译projectPlugin来获取apk文件,我将apk文件更改为jar文件,并在其中添加清单文件,这里是清单代码:
Manifest-Version: 1.0
Module-Class: com.example.helloworld.plugin.PluginHelloWorld <-- this line of code is the code that i added in the manifest file
然后我有一个类从jar文件中读取以加载jar文件。这是代码:
public class PluginManager {
public static List<PluginModel> getPlugins(Activity activty) {
List<PluginModel> plugins = new ArrayList<PluginModel>();
File pluginLoc = new File(Environment.getExternalStorageDirectory()
+ "/Plugin/");
File[] pluginList = pluginLoc.listFiles(new FileFilter() {
@Override
public boolean accept(File pathname) {
Log.d("file path", pathname.toString());
return pathname.getPath().toLowerCase().endsWith(".jar");
}
});
// URL[] urls = new URL[pluginList.length];
for (int i = 0; i < pluginList.length; i++) {
JarFile jarFile = null;
try {
jarFile = new JarFile(pluginList[i]);
Manifest manifest = jarFile.getManifest();
String ModuleClassName = manifest.getMainAttributes().getValue(
"Module-Class");
Log.d("test", ModuleClassName);
File DexOutputFile = activty.getDir("outdex",
Context.MODE_PRIVATE);
DexClassLoader dcl = new DexClassLoader(
pluginList[i].getAbsolutePath(),
DexOutputFile.getAbsolutePath(), null,
ClassLoader.getSystemClassLoader());
Class<?> clazz = dcl.loadClass(ModuleClassName);
// Log.d("test", clazz.getClassLoader().toString());
// Log.d("test1",IPlugin.class.getClassLoader().toString());
IPlugin temp = (IPlugin) clazz.newInstance();
plugins.add(new PluginModel(namaModul, namaPaket));
} catch (Exception e) {
e.printStackTrace();
}
}
return plugins;
}
}
我收到ClassCastException错误,如下图所示:
03-20 20:53:30.453:W / System.err(15986):java.lang.ClassCastException:com.example.helloworld.plugin.PluginHelloWorld无法强制转换为com.far.lib.IPlugin 03-20 20:53:30.453:W / System.err(15986):at com.far.plugin.PluginManager.getPlugins(PluginManager.java:61) 03-20 20:53:30.453:W / System.err(15986):at com.far.exampleplugin2.MainActivity.onResume(MainActivity.java:32) 03-20 20:53:30.453:W / System.err(15986):在android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1192) 03-20 20:53:30.453:W / System.err(15986):在android.app.Activity.performResume(Activity.java:5211) 03-20 20:53:30.453:W / System.err(15986):在android.app.ActivityThread.performResumeActivity(ActivityThread.java:2780) 03-20 20:53:30.453:W / System.err(15986):在android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2819) 03-20 20:53:30.453:W / System.err(15986):在android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2266) 03-20 20:53:30.453:W / System.err(15986):在android.app.ActivityThread.access $ 600(ActivityThread.java:141) 03-20 20:53:30.453:W / System.err(15986):在android.app.ActivityThread $ H.handleMessage(ActivityThread.java:1256) 03-20 20:53:30.453:W / System.err(15986):在android.os.Handler.dispatchMessage(Handler.java:99) 03-20 20:53:30.453:W / System.err(15986):在android.os.Looper.loop(Looper.java:137) 03-20 20:53:30.453:W / System.err(15986):在android.app.ActivityThread.main(ActivityThread.java:5103) 03-20 20:53:30.453:W / System.err(15986):at java.lang.reflect.Method.invokeNative(Native Method) 03-20 20:53:30.453:W / System.err(15986):at java.lang.reflect.Method.invoke(Method.java:525) 03-20 20:53:30.453:W / System.err(15986):at com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run(ZygoteInit.java:737) 03-20 20:53:30.453:W / System.err(15986):at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553) 03-20 20:53:30.453:W / System.err(15986):at dalvik.system.NativeStart.main(Native Method)
我使用Log从clazz和IPlugin打印每个类加载器,结果不同。这是结果:
03-20 20:56:09.253:D / test(16698):dalvik.system.DexClassLoader [DexPathList [[zip file&#34; /storage/emulated/0/Plugin/HelloWorld1.jar"] ,nativeLibraryDirectories = [/系统/ lib中]]] 03-20 20:56:09.253:D / test1(16698):dalvik.system.PathClassLoader [DexPathList [[zip file&#34; /data/app/com.far.exampleplugin2-1.apk"], nativeLibraryDirectories = [/ data / app-lib / com.far.exampleplugin2-1,/ system / lib]]]
我在这里问的问题是如何将一个加载的类从projectMain转换为接口类?
谢谢。答案 0 :(得分:0)
如果类加载不兼容,则会发生java中兼容类的ClassCastExceptions。如果您的应用程序未被系统类加载器加载,则可能会发生这种情况。由于我不是Android专家,我不确定锁定的类加载器是否是系统类加载器。因此,您可以使用在this.getClass().getClassLoader()
处执行的类的类加载器或者要与IPlugin.class.getClassLoader()
兼容的接口作为父类加载器来配置DexClassLoader。这些是您需要兼容的类加载器。 Thread.currentThread().getContextClassLoader()
也值得一试。
DexClassLoader dcl = new DexClassLoader(
pluginList[i].getAbsolutePath(),
DexOutputFile.getAbsolutePath(), null,
IPlugin.class.getClassLoader());