从Android触发JavaScript事件

3
我创建了一个cordova应用程序。我正在运行后台服务来执行应用程序中的一些本地任务。一旦后台服务完成其任务,我需要触发一个JavaScript事件。是否可能从安卓触发JS事件?没有找到任何确定的答案。我需要事件,因为应用程序将等待后台服务中的任务完成。我希望事件通知应用程序任务已完成。有更好的实现这个逻辑的方法吗?
1个回答

3

Cordova本身并不公开其webview属性以供其他Java类使用,但您可以使用最小的Cordova插件来实现这一点,该插件将允许后台服务访问Cordova webview,以便从Java层中执行其中的javascript。然后,只需注入JS以触发事件即可。

首先,您需要创建一个Cordova插件,以将Cordova的必要元素暴露给您的后台服务:

public class MyPlugin extends CordovaPlugin{
    private static final String TAG = "MyPlugin";
    static MyPlugin instance = null;
    static CordovaWebView cordovaWebView;
    static CordovaInterface cordovaInterface;

    @Override
    public void initialize(CordovaInterface cordova, CordovaWebView webView) {
        super.initialize(cordova, webView);

        instance = this;
        cordovaWebView = webView;
        cordovaInterface = cordova;
    }

    @Override
    public void onDestroy() {
        instance = null;
    }

    private static void executeGlobalJavascript(final String jsString) {
        if (instance == null) {return;}
        instance.cordovaInterface.getActivity().runOnUiThread(new Runnable() {
            @Override
            public void run() {
                try {
                    instance.cordovaWebView.loadUrl("javascript:" + jsString);
                } catch (Exception e) {
                    Log.e(TAG, "Error executing javascript: "+ e.toString());
                }
            }
        });
    }

    public static void triggerJavascriptEvent(final String eventName){
        executeGlobalJavascript(String.format("document.dispatchEvent(new Event('%s'));", eventName));
    }
}

然后您的后台服务可以调用该插件类公开的公共方法:

public class MyService {
    public static void myMethod(){
        MyPlugin.triggerJavascriptEvent("myserviceevent");
    }
}

最后,在您的 Cordova 应用程序的 JS 层中,您将监听自定义事件:
document.addEventListener('myserviceevent', function(){
    console.log("myserviceevent received");
}, false);

我创建了一个示例 Cordova 项目,其中包含实现此目的所需的最小自定义插件,您可以在此处下载:http://ge.tt/8UeL6lu2

下载后,请解压缩然后执行以下操作:

cd cordova-test
cordova platform add android
cordova run android

在这种情况下,您需要从js调用此插件。只有当我们通过exec方法从js调用插件时,才会调用initialize方法。因此,如果我尝试直接从服务中调用它,则在initialize方法内分配的变量将为null,并且loadUrl方法将不会被调用。如果我有所错误,请纠正我。 - sijo jose
如果您在<feature>定义中添加<param name="onload" value="true" />,则initialize()方法将在应用程序启动时被调用:请参阅插件初始化和生命周期。我的示例项目说明了这一点。 - DaveAlden

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接