[英]How to get an android service return message from a phonegap plugin
I am trying to make a plugin for Phonegap (Android) that allows my javascript to send and receive messages to / from a service. 我正在尝试为Phonegap(Android)制作一个插件,允许我的javascript向/从服务发送和接收消息。 My exact problem is, that because the messages return asynchronous, I cannot send the PluginResult to the execute function of the plugin.
我确切的问题是,因为消息返回异步,我不能将PluginResult发送到插件的execute函数。
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): 从这个插件真正的麻烦来自这部分代码,它处理返回消息和插件返回(转到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. 我能想到的唯一解决方案是将响应存储在数据库或变量中,并让javascript执行setInterval以继续检查更改。 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.
我想使用某种回调函数让javascript知道消息已经返回,但我不知道如何。 I would greatly appreciate any help and ideas.
我非常感谢任何帮助和想法。
Thank you, Vlad 弗拉德谢谢你
This might be a late answer but I started to work with Cordova Plugin around 5 months ago and I just saw your question. 这可能是一个迟到的答案,但我在5个月前开始使用Cordova插件,我刚看到你的问题。 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()
. 假设你有异步进程并且你有一个监听器和方法,成功和失败,让我们在
onSuccess()
和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. 只要您使用
pluginResult.setKeepCallback(true)
发送true,该过程将保持未完成状态,因此您可以在完成后台进程后稍后发送插件结果数据。 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;
}
The answer to my problem was actually in the the PluginResult object and success method. 我的问题的答案实际上是在PluginResult对象和成功方法中。 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 !
我找到了一个插件,为了工作必须面对同样的问题,从这个代码我能够找出我的答案。这是一个onPhoneStatusChange插件,可以在这里找到!
The mystery lies in these lines: 神秘之处在于以下几点:
PluginResult res = new PluginResult(PluginResult.Status.OK, obj);
res.setKeepCallback(true);
success(res, callbackId);
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.
然后在ServiceClient_plugin类中使用BroadcastReciever监听广播。 This way you woun't have to keep polling to see if the data has arrived yet.
这样您就不必继续轮询以查看数据是否已到达。
You can send PluginResult
using success()
function like this: 您可以使用
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);
}
}
here callback
is callbackId
of execute()
function 这里
callback
是execute()
函数的callbackId
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.