如何从phonegap插件获取android服务返回消息

发布于 2024-12-11 18:42:17 字数 5194 浏览 0 评论 0原文

我正在尝试为 Phonegap (Android) 制作一个插件,允许我的 javascript 向服务发送消息或从服务接收消息。 我的确切问题是,因为消息异步返回,所以我无法将 PluginResult 发送到插件的执行函数。

这是插件代码:

public class ServiceClient_plugin extends Plugin {
    Messenger messenger_service=null;
    boolean connected_to_service=false;
    final Messenger messenger_receive = new Messenger(new IncomingHandler());

    @Override
    public PluginResult execute(String action, JSONArray data, String callbackId) {
        PluginResult result = null;

        try {
            if (action.toUpperCase().equals("CONNECT")) {
                result = ConnectService();
            } else if (action.toUpperCase().equals("DISCONNECT")) {
                result = DisconnectService();
            } else if (action.toUpperCase().equals("IS_CONNECTED")) {
                result = new PluginResult(Status.OK,connected_to_service);
            } else if (action.toUpperCase().equals("COMMAND")) {
                sendMSG (data.getString(0));
                result = new PluginResult(Status.OK);
            } else {
                result = new PluginResult(Status.INVALID_ACTION);
            }
        } catch(JSONException e) {
             result= new PluginResult(PluginResult.Status.JSON_EXCEPTION);
        }
        return result;
    }

    private PluginResult ConnectService() {
        doBindService();
        return new PluginResult(Status.OK);
    }
    private PluginResult DisconnectService() {
        doUnbindService();
        return new PluginResult(Status.OK);
    }

    class IncomingHandler extends Handler {
    @Override
    public void handleMessage(Message msg) {
        switch (msg.what) {
            case MoMe_Service.MSG_COMMAND:
                Log.i("CLIENT","Received from service: " + msg.getData().getString("MSG"));
                break;
            default:
                super.handleMessage(msg);
        }
    }
}

private ServiceConnection service_connection = new ServiceConnection() {
    public void onServiceConnected(ComponentName className,  IBinder service) {
        messenger_service = new Messenger(service);
        connected_to_service=true;
        try {
            Message msg = Message.obtain(null,  My_Service.MSG_REGISTERED);
            msg.replyTo = messenger_receive;
            messenger_service.send(msg);
        } catch (RemoteException e) {
            // In this case the service has crashed before we could even
            // do anything with it; we can count on soon being
            // disconnected (and then reconnected if it can be restarted)
            // so there is no need to do anything here.
        }

    }

    public void onServiceDisconnected(ComponentName className) {
        // This is called when the connection with the service has been
        // unexpectedly disconnected -- that is, its process crashed.
        messenger_service = null;
        connected_to_service=false;
    }
};    

private void doBindService() {
    // Establish a connection with the service.  We use an explicit
    // class name because there is no reason to be able to let other
    // applications replace our component.
    this.ctx.bindService(new Intent(this.ctx, My_Service.class), service_connection, Context.BIND_AUTO_CREATE);
}

private void doUnbindService() {
    if (connected_to_service) {
        if (messenger_service != null) {
            try {
                Message msg = Message.obtain(null, My_Service.MSG_UNREGISTERED);
                msg.replyTo = messenger_receive;
                messenger_service.send(msg);
            } catch (RemoteException e) {
                // There is nothing special we need to do if the service
                // has crashed.
            }
        }

        // Detach our existing connection.
        this.ctx.unbindService(service_connection);
        connected_to_service = false;
    }
}

private void sendMSG (String message) {
    try {
        Message msg=Message.obtain(null, My_Service.MSG_COMMAND);
        Bundle msg_bundle=new Bundle();
        msg_bundle.putString("MSG", message);
        msg.setData(msg_bundle);
        messenger_service.send(msg);
    } catch (RemoteException e) {
        doUnbindService();
    }
}

}

从这个插件中,真正的麻烦来自于这部分代码,它处理返回消息和插件返回(转到javascript):

    @Override
    public PluginResult execute(String action, JSONArray data, String callbackId) {
        PluginResult result = null;

        try {
            result = new PluginResult(Status.ok);
            }
        } catch(JSONException e) {
             result= new PluginResult(PluginResult.Status.JSON_EXCEPTION);
        }
        return result;
    }

    class IncomingHandler extends Handler {
    @Override
    public void handleMessage(Message msg) {
        switch (msg.what) {
            case MoMe_Service.MSG_COMMAND:
                msg.getData().getString("MSG")); // THIS IS THE DATA I NEED RETURNED
                break;
            default:
                super.handleMessage(msg);
        }
      }
     }

我能想到的唯一解决方案是将响应存储在数据库或变量,并让 javascript 执行 setInterval 来不断检查更改。但是我不太喜欢这个解决方案。我想使用某种回调函数让 javascript 知道消息已返回,但我不知道如何。我将非常感谢任何帮助和想法。

谢谢你, 弗拉德

I am trying to make a plugin for Phonegap (Android) that allows my javascript to send and receive messages to / from a service.
My exact problem is, that because the messages return asynchronous, I cannot send the PluginResult to the execute function of the plugin.

This is the plugin code:

public class ServiceClient_plugin extends Plugin {
    Messenger messenger_service=null;
    boolean connected_to_service=false;
    final Messenger messenger_receive = new Messenger(new IncomingHandler());

    @Override
    public PluginResult execute(String action, JSONArray data, String callbackId) {
        PluginResult result = null;

        try {
            if (action.toUpperCase().equals("CONNECT")) {
                result = ConnectService();
            } else if (action.toUpperCase().equals("DISCONNECT")) {
                result = DisconnectService();
            } else if (action.toUpperCase().equals("IS_CONNECTED")) {
                result = new PluginResult(Status.OK,connected_to_service);
            } else if (action.toUpperCase().equals("COMMAND")) {
                sendMSG (data.getString(0));
                result = new PluginResult(Status.OK);
            } else {
                result = new PluginResult(Status.INVALID_ACTION);
            }
        } catch(JSONException e) {
             result= new PluginResult(PluginResult.Status.JSON_EXCEPTION);
        }
        return result;
    }

    private PluginResult ConnectService() {
        doBindService();
        return new PluginResult(Status.OK);
    }
    private PluginResult DisconnectService() {
        doUnbindService();
        return new PluginResult(Status.OK);
    }

    class IncomingHandler extends Handler {
    @Override
    public void handleMessage(Message msg) {
        switch (msg.what) {
            case MoMe_Service.MSG_COMMAND:
                Log.i("CLIENT","Received from service: " + msg.getData().getString("MSG"));
                break;
            default:
                super.handleMessage(msg);
        }
    }
}

private ServiceConnection service_connection = new ServiceConnection() {
    public void onServiceConnected(ComponentName className,  IBinder service) {
        messenger_service = new Messenger(service);
        connected_to_service=true;
        try {
            Message msg = Message.obtain(null,  My_Service.MSG_REGISTERED);
            msg.replyTo = messenger_receive;
            messenger_service.send(msg);
        } catch (RemoteException e) {
            // In this case the service has crashed before we could even
            // do anything with it; we can count on soon being
            // disconnected (and then reconnected if it can be restarted)
            // so there is no need to do anything here.
        }

    }

    public void onServiceDisconnected(ComponentName className) {
        // This is called when the connection with the service has been
        // unexpectedly disconnected -- that is, its process crashed.
        messenger_service = null;
        connected_to_service=false;
    }
};    

private void doBindService() {
    // Establish a connection with the service.  We use an explicit
    // class name because there is no reason to be able to let other
    // applications replace our component.
    this.ctx.bindService(new Intent(this.ctx, My_Service.class), service_connection, Context.BIND_AUTO_CREATE);
}

private void doUnbindService() {
    if (connected_to_service) {
        if (messenger_service != null) {
            try {
                Message msg = Message.obtain(null, My_Service.MSG_UNREGISTERED);
                msg.replyTo = messenger_receive;
                messenger_service.send(msg);
            } catch (RemoteException e) {
                // There is nothing special we need to do if the service
                // has crashed.
            }
        }

        // Detach our existing connection.
        this.ctx.unbindService(service_connection);
        connected_to_service = false;
    }
}

private void sendMSG (String message) {
    try {
        Message msg=Message.obtain(null, My_Service.MSG_COMMAND);
        Bundle msg_bundle=new Bundle();
        msg_bundle.putString("MSG", message);
        msg.setData(msg_bundle);
        messenger_service.send(msg);
    } catch (RemoteException e) {
        doUnbindService();
    }
}

}

From this plugin the real trouble comes with this part of code, which handles the return messages and the plugin return (which goes to the javascript):

    @Override
    public PluginResult execute(String action, JSONArray data, String callbackId) {
        PluginResult result = null;

        try {
            result = new PluginResult(Status.ok);
            }
        } catch(JSONException e) {
             result= new PluginResult(PluginResult.Status.JSON_EXCEPTION);
        }
        return result;
    }

    class IncomingHandler extends Handler {
    @Override
    public void handleMessage(Message msg) {
        switch (msg.what) {
            case MoMe_Service.MSG_COMMAND:
                msg.getData().getString("MSG")); // THIS IS THE DATA I NEED RETURNED
                break;
            default:
                super.handleMessage(msg);
        }
      }
     }

The only solution I can think of, is storing the response in either a database or a variable and have the javascript do a setInterval to keep checking for changes. However I am not very fond of this solution. I would like to use some sort of callback function to let the javascript know the message has returned but I have no idea how. I would greatly appreciate any help and ideas.

Thank you,
Vlad

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

游魂 2024-12-18 18:42:17

这可能是一个迟到的答案,但我大约 5 个月前开始使用 Cordova 插件,我刚刚看到你的问题。既然你没有选择正确的答案,我想回答你的问题。

假设您有异步进程,并且有一个侦听器和方法、 success 和 failed ,我们将其称为 onSuccess()onFail()。只要您使用 pluginResult.setKeepCallback(true) 发送 true,该过程就会保持未完成状态,因此您可以稍后在完成后台过程后发送插件结果数据。这是一个例子,看一下。

@Override
public boolean execute(String action, JSONArray data, String callbackId)  throws JSONException {
        if (action.equals("start")) {

              start();
        } else {
            PluginResult pluginResult = new PluginResult(PluginResult.Status.INVALID_ACTION);
            callbackContext.sendPluginResult(pluginResult);
            return false;
        }
}


    private boolean start() throws JSONException {

        MyClass.startProcess(new MyInterface() {

            @Override
            public void onSuccess(String data) {

                PluginResult result = new PluginResult(PluginResult.Status.OK, data);
                result.setKeepCallback(false);
                callbackContext.sendPluginResult(result);
            }

            @Override
            public void onFail() {

                PluginResult result = new PluginResult(PluginResult.Status.ERROR);
                result.setKeepCallback(false);
                callbackContext.sendPluginResult(result);
            }

        });

    PluginResult.Status status = PluginResult.Status.NO_RESULT;

    PluginResult pluginResult = new PluginResult(status);
    pluginResult.setKeepCallback(true);
    callbackContext.sendPluginResult(pluginResult);
    return true;

    }

This might be a late answer but I started to work with Cordova Plugin around 5 months ago and I just saw your question. Since you did not choose the correct answer I wanted to answer your question.

Assuming you have asynchronous process and you have a listener and methods, success and fail , lets call it onSuccess() and onFail(). As long as you send true with pluginResult.setKeepCallback(true), the process will remain as unfinished, so you can send your plugin result data later on when you are done with background process. Here is an example take a look.

@Override
public boolean execute(String action, JSONArray data, String callbackId)  throws JSONException {
        if (action.equals("start")) {

              start();
        } else {
            PluginResult pluginResult = new PluginResult(PluginResult.Status.INVALID_ACTION);
            callbackContext.sendPluginResult(pluginResult);
            return false;
        }
}


    private boolean start() throws JSONException {

        MyClass.startProcess(new MyInterface() {

            @Override
            public void onSuccess(String data) {

                PluginResult result = new PluginResult(PluginResult.Status.OK, data);
                result.setKeepCallback(false);
                callbackContext.sendPluginResult(result);
            }

            @Override
            public void onFail() {

                PluginResult result = new PluginResult(PluginResult.Status.ERROR);
                result.setKeepCallback(false);
                callbackContext.sendPluginResult(result);
            }

        });

    PluginResult.Status status = PluginResult.Status.NO_RESULT;

    PluginResult pluginResult = new PluginResult(status);
    pluginResult.setKeepCallback(true);
    callbackContext.sendPluginResult(pluginResult);
    return true;

    }
尸血腥色 2024-12-18 18:42:17

我的问题的答案实际上是在 PluginResult 对象和 success 方法中。
我发现一个插件必须面对同样的问题才能工作,从这段代码中我能够找到我的答案。这是一个 onPhoneStatusChange 插件,可以在 这里

谜底就在这几行:

PluginResult res = new PluginResult(PluginResult.Status.OK, obj);
res.setKeepCallback(true);
success(res, callbackId);

The answer to my problem was actually in the the PluginResult object and success method.
I've found a plugin that had to face the same problem in order to work, and from this code i was able to figure out my answer.This is a onPhoneStatusChange plugin, which can be found here!

The mystery lies in these lines:

PluginResult res = new PluginResult(PluginResult.Status.OK, obj);
res.setKeepCallback(true);
success(res, callbackId);
枉心 2024-12-18 18:42:17

此问题的通用解决方案是让服务将响应存储到持久存储(如数据库)中,然后触发广播意图。然后,只需在 ServiceClient_plugin 类中设置一个 BroadcastReciever 来监听广播。这样您就不必继续轮询来查看数据是否已到达。

The generic solution to this problem is to have the service store the response into persistent storage (like a database) and then fire off a broadcast intent. Then just have a BroadcastReciever in your ServiceClient_plugin class listening for the broadcast. This way you woun't have to keep polling to see if the data has arrived yet.

独自唱情﹋歌 2024-12-18 18:42:17

您可以使用 success() 函数发送 PluginResult,如下所示:

public PluginResult execute(String action, JSONArray data, String callbackId) {}
private BroadcastReceiver Wifi_Receiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        MyClass.this.success(new PluginResult(PluginResult.Status.OK,"count"+count),callback);
    }
}

这里 callbackexecute(的 callbackId) ) 函数

You can send PluginResult using success() function like this:

public PluginResult execute(String action, JSONArray data, String callbackId) {}
private BroadcastReceiver Wifi_Receiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        MyClass.this.success(new PluginResult(PluginResult.Status.OK,"count"+count),callback);
    }
}

here callback is callbackId of execute() function

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文