如何从phonegap插件获取android服务返回消息
我正在尝试为 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
这可能是一个迟到的答案,但我大约 5 个月前开始使用 Cordova 插件,我刚刚看到你的问题。既然你没有选择正确的答案,我想回答你的问题。
假设您有异步进程,并且有一个侦听器和方法、 success 和 failed ,我们将其称为
onSuccess()
和onFail()
。只要您使用pluginResult.setKeepCallback(true)
发送 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()
andonFail()
. As long as you send true withpluginResult.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.我的问题的答案实际上是在 PluginResult 对象和 success 方法中。
我发现一个插件必须面对同样的问题才能工作,从这段代码中我能够找到我的答案。这是一个 onPhoneStatusChange 插件,可以在 这里!
谜底就在这几行:
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:
此问题的通用解决方案是让服务将响应存储到持久存储(如数据库)中,然后触发广播意图。然后,只需在 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.
您可以使用
success()
函数发送PluginResult
,如下所示:这里
callback
是execute(的
函数callbackId
) )You can send
PluginResult
usingsuccess()
function like this:here
callback
iscallbackId
ofexecute()
function