Java Android:使用用于IPC的信使实现同步/阻塞API
我有一个后台服务,它使用Java Android:使用用于IPC的信使实现同步/阻塞API,java,android,ipc,android-handler,Java,Android,Ipc,Android Handler,我有一个后台服务,它使用 android:process=":deamon" 在服务的清单条目中。我希望通过活动和服务(远程进程)通信,并从中接收数据。 我通过向远程进程发送消息和从远程进程发送消息来实现这一点,如中所述以及他们建议我遵循的 如果希望服务响应,则还需要在客户端中创建Messenger。>然后,当客户端接收到onServiceConnected()回调时,它会向>服务发送一条消息,该消息在send()方法的replyTo参数中包含客户端的Messenger 问题是,我需要提供一个
android:process=":deamon"
在服务的清单条目中。我希望通过活动和服务(远程进程)通信,并从中接收数据。
我通过向远程进程发送消息和从远程进程发送消息来实现这一点,如中所述以及他们建议我遵循的
如果希望服务响应,则还需要在客户端中创建Messenger。>然后,当客户端接收到onServiceConnected()回调时,它会向>服务发送一条消息,该消息在send()方法的replyTo参数中包含客户端的Messenger
问题是,我需要提供一个阻塞/同步API来从远程服务获取数据,我的“get”函数如何阻塞调用者,然后返回传入处理程序中接收到的数据?
最好的方法是什么?这是客户端消息部分的代码
SparseArray<CountDownLatch> lockArray = new SparseArray<>();
SparseArray<Bundle> msgDataArray = new SparseArray<>();
public Bundle sendAndWaitResponse(Message msg) throws
RemoteException, InterruptedException {
int msgId = msg.arg2;
Log.d("PlatformConnector", "Sending message to service, Type: "
+ msg.what + ", msgId: " + msg.arg2);
CountDownLatch latch = new CountDownLatch(1);
lockArray.put(msgId, latch);
platformMessenger.send(msg);
latch.await();
Bundle response = msgDataArray.get(msgId);
lockArray.delete(msgId);
msgDataArray.delete(msgId);
return response;
}
void storeResponseAndNotify(Message msg) {
int msgId = msg.arg2;
// Because the message itself is recycled after Handler returns,
// we should store only the data of message
msgDataArray.put(msgId, msg.getData());
lockArray.get(msgId).countDown();
}
private class ClientMessageHandler extends Handler {
@Override
public void handleMessage(Message msg) {
storeResponseAndNotify(msg);
}
}
顺序如下:
消息
,并将其arg2
设置为某个随机整数
(此整数将是同步的消息id)倒计时闩锁
,并将其放入锁阵列
sendAndWaitResponse()
发送消息。它通过Messenger
向服务发送消息,并调用latch.await()
arg2
应与收到的消息相同Messenger
向客户端发送回复消息storeResponseAndNotify
处理消息msgDataArray
中准备好CountDownLatch
是阻止和解除阻止线程的简单开关。
()
SparseArray
类似于HashMap
,但对于较小的集合,内存效率更高。
()
小心不要阻塞通讯器的线程
Messenger
以单线程运行,如果您从handleMessage()
阻止,它将阻止所有其他消息并导致deaklock问题。您应该尝试一下AIDL,您定义了方法并只需调用,一切都是同步的,在定义协议和“anti”方面不再有问题对aidl的感觉,但现在我会看一眼谢谢,这显然是一个更好的方法。也许您可以避免等待应答的消息的稀疏数组,因为文档中说service messenger接收的消息是排队的;您可以更简单地设置一个同步的响应队列。“[Messenger]是执行进程间通信(IPC)的最简单方法,因为Messenger将所有请求排队到单个线程中,这样您就不必将服务设计为线程安全的。”
public JSONObject doSomething(JSONObject object) {
Message msg = Message.obtain(null, Constants.MESSAGE_SOMETHING, 0, RandomInt.getNextInt());
Bundle bundle = new Bundle();
bundle.putString(Constants.MESSAGE_DATA_SOMETHING, object.toString());
msg.setData(bundle);
try {
Bundle responseData = sendAndWaitResponse(msg);
return new JSONObject(responseData.getString(Constants.MESSAGE_DATA_RETURN));
} catch (RemoteException e) {
Log.e(TAG, "Failed to send message to platform");
e.printStackTrace();
} catch (InterruptedException e) {
Log.e(TAG, "Interrupted while waiting message from platform");
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}