如何将加载的类转换为Android中的接口类

时间:2015-03-20 14:01:02

标签: java android plugins interface casting

我有两个项目,让我们说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转换为接口类?

谢谢。

1 个答案:

答案 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());