參考:https://blog.csdn.net/u010961631/article/details/48179305
1、AsyncChannel
AsyncChannel的主要特點:
- 可以在單進程或不同進程間實現消息傳遞
- 支持建立單向通信或雙向通信
- 是對Handler,Messenger的一種包裝,並沒有實現額外的通信方式
1、單項通道模式,在該模式下,客戶端只能向服務端發起請求,服務端給出迴應。
2、雙向通道模式,在該模式下,客戶端和服務端同時連接上AsyncChannel,客戶端可以向服務端發送請求,服務端也可以向客戶端發送請求。
使用實例類圖:
2、單向通道建立方法併發送消息
從通道的建立方法可以知道,創建通道需要三個步驟:
1、準備服務端的Messenger對象;
2、創建本地的Handler對象;
3、創建AsyncChannel對象,然後調用connect()方法。
客戶端操作:
1、獲取服務端的Messenger對象,該對象其實就是利用服務端的Handler構建的Messenger;
2、創建客戶端自己的Handler對象;
3、創建AsyncChannel對象;
4、通過AsyncChannel對象,連接當前的Handler和服務端的Messenger,從而申請連接
1、服務啓動:
Intent intent = new Intent(); intent.setComponent(new ComponentName(this, AsyncChannelService.class)); startService(intent); Intent inte = new Intent(); inte.setComponent(new ComponentName(this, AsyncChannelClient.class)); inte.setAction("Normal"); startService(inte);
2、客戶端發起連接
HandlerThread handlerThread = new HandlerThread("ClientThread"); handlerThread.start(); Handler clientHandler = new ClientHandler(handlerThread.getLooper()); sClientAsyncChannel = new AsyncChannel(); String act = intent.getAction();
Messenger serviceMessenger = AsyncChannelService.getServiceMessenger(); Log.d(tag, "Client Start require half connect"); sClientAsyncChannel.connect(this, clientHandler, serviceMessenger);
3、向服務端發送異步消息
sClientAsyncChannel.sendMessage(MainActivity.MSG_ASYNC_REQ);
服務端接收消息並回復
public void handleMessage(Message msg) { switch (msg.what) { case MainActivity.MSG_ASYNC_REQ: { Log.d(tag, "Service get client ASYNC reqest,next reply to client"); Message reply = msg.obtain(); reply.what = MainActivity.MSG_ASYNC_REPLY; reply.obj = "ServiceAsyncReply"; try { msg.replyTo.send(reply); } catch (RemoteException e) { } break; }
3、雙向通道的建立
雙向通道是在單項通道基礎上完成的,當客戶端與服務端的單項通道創建完成後,也就是當客戶端收到AsyncChannel.CMD_CHANNEL_HALF_CONNECTED之後,可以向AsyncChannel對象發送CMD_CHANNEL_FULL_CONNECTION消息申請建立雙向通道。
1、客戶端收到單向通道建立完成消息後,發送消息服務端請求雙向通道的建立
public void handleMessage(Message message) { switch (message.what) { case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: { Log.d(tag, "Client half connected,next send full connect require"); sClientAsyncChannel.sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION);
2、服務端收到請求消息,發起連接
public void handleMessage(Message msg) { case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION: { Log.d(tag, "Service full connected,next require asynchannel connect"); sServiceAsyncChannel.connect(AsyncChannelService.this, mServiceHandler, msg.replyTo); break; }
當客戶端發起雙向通道建立請求時,服務端將會收到AysncChannel.CMD_CHANNEL_FULL_CONNECTION的請求,此時的服務端如果同意建立雙向通道,則使用自己的AsyncChannel對象將自己的Handler與客戶端的Handler連接起來。
至此,雙向通道建立完成,此時不僅客戶端可以通過自己的AsyncChannel對象向服務端發送請求,服務端也可以通過自己的AsyncChannel對象向客戶端發送請求。
3、發送同步消息
客戶端:
Message replyMsg = sClientAsyncChannel.sendMessageSynchronously(MainActivity.MSG_SYNC_REQ);
String msg = (String) replyMsg.obj;
服務端:
public void handleMessage(Message msg) { case MainActivity.MSG_SYNC_REQ: { Log.d(tag, "Service get client SYNC reqest,next reply to client"); Message reply = msg.obtain(); reply.what = MainActivity.MSG_SYNC_REPLY; reply.obj = "ServiceSyncReply"; sServiceAsyncChannel.replyToMessage(msg, reply); break; }
4、fullyConnectSync 建立雙向通道
fullyConnectSync()方法。通過該方法,客戶端只需要一次就可以申請到雙向通道,並且可以知道通道是否建立成功
1、服務的啓動
Intent intent = new Intent(); intent.setComponent(new ComponentName(this, AsyncChannelServiceFull.class)); startService(intent); Intent inte = new Intent(); inte.setComponent(new ComponentName(this, AsyncChannelClient.class)); inte.setAction("Fast"); startService(inte);
2、客戶端發起同步雙向通道的連接fullyConnectSync
Handler serviceHandler = AsyncChannelServiceFull.getServiceHandler(); Log.d(tag, "Client Start require full connect"); int result = sClientAsyncChannel.fullyConnectSync(this, clientHandler, serviceHandler); if (AsyncChannel.STATUS_SUCCESSFUL == result) { Log.d(tag, "client full connected"); }
3、服務端收到同向雙向通道連接請求,發起連接,並回復連接完成
case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION: { Log.d(tag, "FullService received full connect require,reply OK to channel"); sServiceAsyncChannel.connect(AsyncChannelServiceFull.this, mServiceHandler, msg.replyTo); sServiceAsyncChannel.replyToMessage(msg, AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED, AsyncChannel.STATUS_SUCCESSFUL); break; }