Master_T
Master_T

Reputation: 7913

Android ClassLoader: loadClass fails if the class implements an interface

I'm using the following code to dynamically load a class from an external package:

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

The problem is the following: if the class I try to load is a "simple" class everything goes fine, but if it implents an interface the loading fails. Here's an example of a class that fails to load:

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

And the interface it implements:

public interface IDeltaPlugin {

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

Basically the call to loadClass() returns null if the class implements the interface. Remove the "implements" statement and it loads fine.

What am I doing wrong?

Upvotes: 0

Views: 582

Answers (1)

Master_T
Master_T

Reputation: 7913

Well, turns out the problem was that the interface in question was in an Android Library project shared by both the app that was doing the loading and the apk where the class to load was defined.

The ClassLoader then gets confused because it finds two copies of the same interface in the classpath.

The solution: turn the shared library into a JAR library and in the plugin apk import it in "provided" (rather than "compile") mode. This way only one copy of the interface exists (the one in the apk that is doing the classloading)

Upvotes: 1

Related Questions