Android ClassLoader:如果 class 实现接口,则 loadClass 失败

Android ClassLoader: loadClass fails if the class implements an interface

我正在使用以下代码从外部包动态加载 class:

Object plugin = null;
    String packageName = "unipd.elia.deltapluginaccelerometersensor";
    String className = "unipd.elia.deltapluginaccelerometersensor.AccelerometerPlugin";
    try {
        PackageManager packageManager = getPackageManager();
        ApplicationInfo appInfo = packageManager.getApplicationInfo(packageName, 0);
        DexFile df = new DexFile(appInfo.sourceDir);
        ClassLoader cl = getClassLoader();
        Class classToInvestigate = df.loadClass(className, cl);
        plugin = classToInvestigate.newInstance();


    } catch (Exception e) {
        System.out.println("EXCEPTION");
    }

问题如下:如果我尝试加载的 class 是 "simple" class 一切正常,但如果它实现了一个接口,加载就会失败。这是无法加载的 class 示例:

    package unipd.elia.deltapluginaccelerometersensor;

public class AccelerometerPlugin implements IDeltaPlugin {

    @Override
    public String getPluginName() {
        return "Accelerometer Sensor Plugin";
    }

    @Override
    public String getPluginID() {
        return "delta.plugin.accelerometersensor";
    }

    @Override
    public String getPluginAuthor() {
        return "Me";
    }
}

及其实现的接口:

public interface IDeltaPlugin {

    String getPluginName();
    String getPluginID();
    String getPluginAuthor();
}

基本上,如果 class 实现接口,则对 loadClass() returns 的调用为 null。删除 "implements" 语句,它加载正常。

我做错了什么?

好吧,原来问题是有问题的接口在一个 Android 库项目中,该项目由执行加载的应用程序和 class 要加载的 apk 共享定义。

ClassLoader 然后会感到困惑,因为它在 class 路径中找到同一接口的两个副本。

解决方法:将共享库转为JAR库,在插件apk中以"provided"(而不是"compile")方式导入。这样只有一个接口副本存在(apk 中正在进行 class 加载的那个)