哈喽,大家好,接觸Android的同學們對AIDL這個概念肯定不會陌生,就算沒用過,那肯定也是聽過。很多剛開始接觸Android的朋友可能會感覺AIDL很難。今天,就用Messenger來教大家如何簡單的實作跨程序通信。
Messenger
Messenger翻譯為信使,通過它可以在不同的程序中傳遞Message對象。Messenger就一種輕量級的IPC方案,它的底層實作還是AIDL,隻是Android幫我們把大部分方法都封裝在了裡面,這樣使用起來會更加友善。
下面用一個簡單的例子來看看Messenger是如何實作跨程序通信的。
在寫代碼之前,先理一理Messenger跨程序通信的步驟:
服務端
首先我們要在服務端建立一個Service來處理客戶的連接配接請求。
在Service中建立一個Handler并通過它建立一個Messenger。
通過Service的onBind方法将Messenger對象底層的Binder傳回。
用戶端
首先需要綁定服務端Service。
用服務端傳回的Binder對象建立一個Messenger。
然後就可以用Messenger給服務的發送消息。
服務端:
public class OtherService extends Service {
public static final int SERVICE_GET_MESSAGE = 0;
@Override
public IBinder onBind(Intent intent) {
//将messenger底層的Binder對象傳回給用戶端。
return messenger.getBinder();
}
private static class MessageHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case SERVICE_GET_MESSAGE:
//接受到用戶端發送的消息。
Log.d("Test", "get message = " + msg.getData().getString("msg"));
break;
default:
super.handleMessage(msg);
}
}
}
private final Messenger messenger = new Messenger(new MessageHandler());
}
用戶端:
public class MainActivity extends AppCompatActivity {
private Messenger messenger;
public static final int ACTIVITY_HANDLER_MSG = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//綁定服務
Intent intent = new Intent(this, OtherService.class);
bindService(intent, connection, Context.BIND_AUTO_CREATE);
}
private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//用服務端傳回的Binder對象建立新的Messenger對象
messenger = new Messenger(service);
Message sendMsg = Message.obtain(null, OtherService.SERVICE_GET_MESSAGE);
Bundle bundle = new Bundle();
bundle.putString("msg", "this is a msg");
sendMsg.setData(bundle);
try {
//用戶端給服務端發送消息
messenger.send(sendMsg);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
}
上面是一個很簡單的例子,在啟動應用後,用戶端綁定服務端,然後服務端接收到用戶端發送的消息。一些相關注釋已經标在了代碼中,大家可以簡單看看。
上面的例子是用戶端單方面給服務端發送消息,如果服務端想要回複用戶端該怎麼辦呢。這個時候我們可以在用戶端建立一個Handler,然後用Handler生成一個Messenger對象,最後用Message的replyTo将Messenger對象傳遞給服務端,這時候服務端就可以用用戶端傳遞過來的Messenger對象來給用戶端發送消息了。
下面我們來看看如何修改代碼
服務端:
private static class MessageHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case SERVICE_GET_MESSAGE:
Log.d("Test", "get message = " + msg.getData().getString("msg"));
//擷取用戶端傳遞過來的Messenger對象
Messenger activityMessager = msg.replyTo;
Message message = Message.obtain(null, MainActivity.ACTIVITY_HANDLER_MSG);
Bundle bundle = new Bundle();
bundle.putString("msg", "用戶端發送消息成功");
message.setData(bundle);
try {
//給用戶端發送消息
activityMessager.send(message);
} catch (Exception e) {
e.printStackTrace();
}
break;
default:
super.handleMessage(msg);
}
}
}
服務端的改動很小,就是接收到用戶端傳遞過來的Messenger後用這個Messenger來和用戶端通信。
用戶端:
private static class MessageHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case ACTIVITY_HANDLER_MSG:
Log.d("Test", "服務端消息:" + msg.getData().getString("msg"));
break;
default:
super.handleMessage(msg);
}
}
}
private final Messenger serviceMessage = new Messenger(new MessageHandler());
首先我們建立用戶端接收消息的Handler和發送消息的Messenger。
private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
messenger = new Messenger(service);
Message sendMsg = Message.obtain(null, OtherService.SERVICE_GET_MESSAGE);
Bundle bundle = new Bundle();
bundle.putString("msg", "this is a msg");
sendMsg.setData(bundle);
//将用戶端的Messenger傳遞給服務端
sendMsg.replyTo = serviceMessage;
try {
messenger.send(sendMsg);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
然後在綁定成功Service的時候将用戶端的Messenger對象傳遞給服務端。
這樣就實作了用戶端與服務端的雙方通信。
到這裡就講完了Messenger的簡單使用,如果文中有錯誤的地方歡迎大家指正,如果有疑惑的地方,歡迎大家留言讨論。
3Q