如何从不同进程中的远程服务向IPC客户端发送数据

How to send data to an IPC client from a remote service in different processes

有一个IPC客户端和一个IPC服务器(远程服务)属于不同的进程。在客户端绑定到远程服务后,我需要开始向客户端连续发送数据。我可以绑定到服务并从客户端调用 AIDL 方法,但是我找不到方法将数据从远程服务发送到客户端。

这可以通过在 AIDL 中使用远程回调来实现。服务器实现了一个AIDL,它允许客户端在绑定到服务后注册一个远程回调(回调也是一个AIDL)。然后服务器可以在需要时调用远程回调向客户端发送数据。请参阅下面来自 Android API 演示的代码片段。

IRemoteService.aidl

interface IRemoteService {
/**
 * Often you want to allow a service to call back to its clients.
 * This shows how to do so, by registering a callback interface with
 * the service.
 */
void registerCallback(IRemoteServiceCallback cb);

/**
 * Remove a previously registered callback interface.
 */
void unregisterCallback(IRemoteServiceCallback cb);

}

IRemoteServiceCallback.aidl

oneway interface IRemoteServiceCallback {
/**
 * Called when the service has a new value for you.
 */
void valueChanged(int value);

}

客户端和服务器端代码都可以在RemoteService.java

看到

注册远程回调的客户端代码

        private ServiceConnection mConnection = new ServiceConnection() {
        public void onServiceConnected(ComponentName className,
                IBinder service) {
            // This is called when the connection with the service has been
            // established, giving us the service object we can use to
            // interact with the service.  We are communicating with our
            // service through an IDL interface, so get a client-side
            // representation of that from the raw service object.
            mService = IRemoteService.Stub.asInterface(service);
            mKillButton.setEnabled(true);
            mCallbackText.setText("Attached.");

            // We want to monitor the service for as long as we are
            // connected to it.
            try {
                mService.registerCallback(mCallback);
            } 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.
            }

调用客户端远程回调的服务端代码

               `// Broadcast to all clients the new value.
                final int N = mCallbacks.beginBroadcast();
                for (int i=0; i<N; i++) {
                    try {
                        mCallbacks.getBroadcastItem(i).valueChanged(value);
                    } catch (RemoteException e) {
                        // The RemoteCallbackList will take care of removing
                        // the dead object for us.
                    }
                }
                mCallbacks.finishBroadcast();`