简体   繁体   中英

How to load cordova plugin dynamically into android app

I use the following code to dynamically load my class to android app. (Note: successfully loaded)

File file = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
String fileInput = file.getAbsolutePath() + "/file.jar";

File optimizedDexOutputPath = activity.getDir("dex", Context.MODE_PRIVATE);
String fileOutput = optimizedDexOutputPath.getAbsolutePath();

DexClassLoader classLoader = new DexClassLoader(fileInput, fileOutput, null, getClass().getClassLoader());
try {
    Class<?> helloClass = classLoader.loadClass("HelloClass");
    Toast.makeText(activity, "Loaded success: " + helloClass.toString(), Toast.LENGTH_SHORT).show();
} catch (ClassNotFoundException e) {
    e.printStackTrace();
}

And I have the following cordova config.xml:

<feature name="HelloClass">
    <param name="android-package" value="HelloClass" />
</feature>

When I called execute method from javascript, I got the following error.

05-12 18:06:19.180: W/System.err(17862): java.lang.ClassNotFoundException: HelloClass 05-12 18:06:19.180: W/System.err(17862): Caused by: java.lang.NoClassDefFoundError: HelloClass 05-12 18:06:19.180: W/System.err(17862): ... 13 more 05-12 18:06:19.190: W/System.err(17862): Caused by: java.lang.ClassNotFoundException: Didn't find class "HelloClass" on path: /data/app/sandbox.apk

I wonder what went wrong in here. Any help is really appreciated.

I assume that you want to dynamically load external class from cordova plugin into android app.

From what have mentioned, your approach of loading class using DexClassLoader seems okay. However, to make the class available when you call it from your javascript, you need to load the class right after cordova execute method called.

You can modify the existing codova PluginManager.java as follows:

private CordovaPlugin instantiatePlugin(String className) {
    CordovaPlugin ret = null;
    try {
        Class<?> c = null;
        if ("HelloClass".equals(className)) {
            File file = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
            String fileInput = file.getAbsolutePath();
            File optimizedDexOutputPath = this.ctx.getActivity().getDir("dex", Context.MODE_PRIVATE);
            String fileOutput = optimizedDexOutputPath.getAbsolutePath();

            DexClassLoader classLoader = new DexClassLoader(fileInput, fileOutput, null, getClass().getClassLoader());
            try {
                c = classLoader.loadClass(className);
                ret = (CordovaPlugin) c.newInstance();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
        else {
            if ((className != null) && !("".equals(className))) {
                c = Class.forName(className);
            }
            if (c != null & CordovaPlugin.class.isAssignableFrom(c)) {
                ret = (CordovaPlugin) c.newInstance();
            }
        }            
    } catch (Exception e) {
        e.printStackTrace();
        System.out.println("Error adding plugin " + className + ".");
    }
    return ret;
} 

Now, you should be able to execute method in HelloClass from your .js without any problem.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM