Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/378.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Android:使用用于IPC的信使实现同步/阻塞API_Java_Android_Ipc_Android Handler - Fatal编程技术网

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
    应与收到的消息相同
  • 服务通过replyTo中的
    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;
        }