如何将 cordova 插件动态加载到 android 应用程序中

How to load cordova plugin dynamically into android app

我使用以下代码将我的 class 动态加载到 android 应用程序。 (注:加载成功)

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

我有以下 cordova config.xml:

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

当我从 javascript 调用执行方法时,出现以下错误。

05-12 18:06:19.180: W/System.err(17862): java.lang.ClassNotFoundException: HelloClass 05-12 18:06:19.180: W/System.err(17862): 引起: java.lang.NoClassDefFoundError: HelloClass 05-12 18:06:19.180: W/System.err(17862): ... 13 更多 05-12 18:06:19.190: W/System.err(17862): 原因: java.lang.ClassNotFoundException: 在路径上找不到 class "HelloClass": /data/app/sandbox.apk

我想知道这里出了什么问题。非常感谢任何帮助。

我假设您想将外部 class 从 cordova 插件动态加载到 android 应用程序中。

从上面提到的情况来看,您使用 DexClassLoader 加载 class 的方法似乎没问题。但是,要使 class 在您从 javascript 调用它时可用,您需要在调用 cordova execute 方法后立即加载 class。

您可以修改现有的codovaPluginManager.java如下:

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

现在,您应该可以毫无问题地从 .js 执行 HelloClass 中的方法。