Android ClassLoader:如果类实现了接口,loadClass 就会失败



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

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");
    }

问题如下:如果我尝试加载的类是一个"简单"类,一切正常,但如果它包含接口,加载就会失败。下面是一个无法加载的类的示例:

    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();
}

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

我做错了什么?

好吧,事实证明,问题在于有问题的界面位于执行加载的应用程序和定义要加载的类的apk共享的Android库项目中。

然后,类

加载器会感到困惑,因为它在类路径中找到同一接口的两个副本。

解决方案:将共享库转换为JAR库,并在插件apk中以"提供"(而不是"编译")模式导入它。这样,仅存在接口的一个副本(apk中正在执行类加载的副本)

最新更新