Android IPC中AIDL与Messenger双向通信:服务端向客户端传参咨询
Android IPC:服务端向客户端传输数据实现方案
不管是AIDL还是Messenger,双向通信的核心都是让服务端持有客户端的通信入口,从而主动发起数据传输。以下是两种方式的具体实现:
一、AIDL实现服务端向客户端推送数据
AIDL通过回调接口实现服务端到客户端的通信,步骤如下:
1. 定义回调AIDL接口
新建IClientCallback.aidl文件,声明服务端调用客户端的方法:
package com.example.ipcdemo; interface IClientCallback { void onDataReceived(String serverData); }
2. 修改主AIDL接口,添加回调注册/注销方法
在你的主AIDL(比如IServerAidlInterface.aidl)中,新增管理回调的方法:
package com.example.ipcdemo; import com.example.ipcdemo.IClientCallback; interface IServerAidlInterface { // 客户端向服务端发数据的方法 void sendDataToServer(String clientData); // 注册客户端回调 void registerCallback(IClientCallback callback); // 注销客户端回调 void unregisterCallback(IClientCallback callback); }
3. 服务端实现AIDL接口,维护回调列表
服务端使用RemoteCallbackList来管理跨进程回调(避免内存泄漏和线程安全问题),在需要时主动调用客户端的回调方法:
public class ServerService extends Service { private final RemoteCallbackList<IClientCallback> mCallbackList = new RemoteCallbackList<>(); private final IServerAidlInterface.Stub mBinder = new IServerAidlInterface.Stub() { @Override public void sendDataToServer(String clientData) throws RemoteException { // 处理客户端发来的数据 } @Override public void registerCallback(IClientCallback callback) throws RemoteException { if (callback != null) { mCallbackList.register(callback); } } @Override public void unregisterCallback(IClientCallback callback) throws RemoteException { if (callback != null) { mCallbackList.unregister(callback); } } }; // 模拟服务端主动向客户端推送数据 private void pushDataToClients() { int count = mCallbackList.beginBroadcast(); for (int i = 0; i < count; i++) { try { mCallbackList.getBroadcastItem(i).onDataReceived("来自服务端的推送数据"); } catch (RemoteException e) { e.printStackTrace(); } } mCallbackList.finishBroadcast(); } @Nullable @Override public IBinder onBind(Intent intent) { return mBinder; } }
4. 客户端实现回调接口,注册到服务端
客户端绑定服务后,实现IClientCallback.Stub,并注册到服务端,即可接收服务端的推送:
public class ClientActivity extends AppCompatActivity { private IServerAidlInterface mServer; private IClientCallback mCallback = new IClientCallback.Stub() { @Override public void onDataReceived(String serverData) throws RemoteException { // 收到服务端数据,更新UI需切换到主线程 runOnUiThread(() -> { // 处理服务端发来的数据 }); } }; private ServiceConnection mConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { mServer = IServerAidlInterface.Stub.asInterface(service); try { // 注册回调到服务端 mServer.registerCallback(mCallback); } catch (RemoteException e) { e.printStackTrace(); } } @Override public void onServiceDisconnected(ComponentName name) { mServer = null; } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_client); // 绑定服务端服务 Intent intent = new Intent(); intent.setComponent(new ComponentName("com.example.serverapp", "com.example.serverapp.ServerService")); bindService(intent, mConnection, BIND_AUTO_CREATE); } @Override protected void onDestroy() { super.onDestroy(); if (mServer != null) { try { mServer.unregisterCallback(mCallback); } catch (RemoteException e) { e.printStackTrace(); } } unbindService(mConnection); } }
二、Messenger实现服务端向客户端推送数据
Messenger基于Handler和Message实现,通过replyTo字段传递客户端Messenger,让服务端能反向发送消息:
1. 客户端创建自己的Messenger和Handler
客户端实现Handler处理服务端发来的消息,并创建对应的Messenger:
public class ClientActivity extends AppCompatActivity { private Messenger mServerMessenger; // 客户端的Messenger,用于接收服务端消息 private Messenger mClientMessenger = new Messenger(new ClientHandler()); private static class ClientHandler extends Handler { @Override public void handleMessage(@NonNull Message msg) { super.handleMessage(msg); if (msg.what == 1) { // 获取服务端发来的数据 String serverData = msg.getData().getString("server_data"); // 处理数据 } } } private ServiceConnection mConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { mServerMessenger = new Messenger(service); // 向服务端发送消息,并携带客户端的Messenger Message msg = Message.obtain(null, 0); msg.replyTo = mClientMessenger; Bundle bundle = new Bundle(); bundle.putString("client_data", "客户端初始数据"); msg.setData(bundle); try { mServerMessenger.send(msg); } catch (RemoteException e) { e.printStackTrace(); } } @Override public void onServiceDisconnected(ComponentName name) { mServerMessenger = null; } }; // 绑定服务逻辑同AIDL客户端,此处省略 }
2. 服务端保存客户端的Messenger,主动发送数据
服务端收到客户端消息后,取出replyTo保存,之后通过这个Messenger向客户端发消息:
public class ServerService extends Service { private Messenger mClientMessenger; private Messenger mServerMessenger = new Messenger(new ServerHandler()); private static class ServerHandler extends Handler { @Override public void handleMessage(@NonNull Message msg) { super.handleMessage(msg); if (msg.what == 0) { // 获取客户端数据 String clientData = msg.getData().getString("client_data"); // 保存客户端的Messenger,用于反向通信 mClientMessenger = msg.replyTo; // 模拟服务端主动推送数据 sendDataToClient(); } } } private void sendDataToClient() { if (mClientMessenger != null) { Message msg = Message.obtain(null, 1); Bundle bundle = new Bundle(); bundle.putString("server_data", "来自服务端的推送数据"); msg.setData(bundle); try { mClientMessenger.send(msg); } catch (RemoteException e) { e.printStackTrace(); } } } @Nullable @Override public IBinder onBind(Intent intent) { return mServerMessenger.getBinder(); } }
为什么称AIDL和Messenger是双向通信?
因为这两种方式下,客户端和服务端都持有对方的通信通道:
- AIDL中,服务端通过客户端注册的回调接口调用客户端方法;客户端通过服务端的Binder调用服务端方法。
- Messenger中,服务端通过客户端传递的
replyToMessenger发送消息;客户端通过服务端的Messenger发送消息。
双方都能主动发起数据传输,因此属于双向通信。
内容的提问来源于stack exchange,提问作者Nikhil
相关产品推荐
相关产品推荐

