Android IPC程序間通訊(二)Messenger
阿新 • • 發佈:2018-11-11
Messenger實現程序間低併發即時通訊
Messenger是一種輕量級的IPC,底層實現是AIDL,即可認為Binder。通過在Message中攜帶Bundle進而實現程序之間傳遞資料。由於Messenger一次只能處理一個請求,因此服務端們不用考慮執行緒同步問題。
一,我們在服務端建立一個Handler用於接受來自客戶端訊息,並以此Handler建立Messenger,我們將這個Messenger的Binder物件通過onBinde( )方法返回給客戶端;在客戶端連結服務的onServiceConnected( )方法中取得Binder物件,轉化為Messenger,即可傳送訊息給服務端。
二,我們在客戶端建立一個Handler用於接受來自服務端的訊息,同樣需要以此Handler建立一個Messenger並將它返回給服務端用於傳送訊息,怎麼返回的呢?在客戶端連結服務的onServiceConnected( )方法中,當客戶端向服務端傳送訊息時攜帶上剛剛建立的Messenger物件,message.replyTo = 剛剛建立的Messenger物件,而在服務端的Handler中我們可以從msg中取出來自客戶端的訊息和Messenger物件,Messenger reply = msg.replyTo;以此向客戶端傳送訊息。
三,優點:功能一般,支援一對多序列通訊,支援實時通訊
缺點:不能很好處理高併發,不支援遠端RPC,只能傳輸Bundle支援的資料型別。
適用場景:低併發一對多即時通訊,無RPC請求,或者無需返回結果的RPC請求。
1.服務端
public class MessengerService extends Service {
public static final int SERVICE_REPLY_WHAT = 100;
public static final String SERVICE_REPLY_KEY = "service_reply_key";
//將此Messenger物件傳遞給客戶端,以此向服務端傳送訊息
private Messenger mMessenger = new Messenger(new ServiceHandler());
public MessengerService () {
}
private class ServiceHandler extends Handler {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
//收到來自客戶端的指令並進行回覆
case MainActivity.MAIN_SEND_WHAT:
String msgStr = msg.getData().getString(MainActivity.MAIN_SEND_KEY);
Toast.makeText(MessengerService.this, msgStr, Toast.LENGTH_SHORT).show();
//取出來自客戶端的Messemger物件,以此想客戶端傳送訊息
Messenger reply = msg.replyTo;
Message message = Message.obtain(null, SERVICE_REPLY_WHAT);
Bundle bundle = new Bundle();
bundle.putString(SERVICE_REPLY_KEY, "收到來自客戶端訊息,服務端很高興,這是回信。");
message.setData(bundle);
try {
reply.send(message);
} catch (RemoteException e) {
e.printStackTrace();
}
break;
default:
super.handleMessage(msg);
}
}
}
@Override
public IBinder onBind(Intent intent) {
//將服務端Handler構造的Messenger的Binger物件傳送給客戶端
return mMessenger.getBinder();
}
}
2.客戶端
public class MainActivity extends AppCompatActivity {
public static final int MAIN_SEND_WHAT = 101;
public static final String MAIN_SEND_KEY = "main_send_key";
//用來自service的IBinder物件構造Messenger,向Service端傳送訊息
private Messenger mMessenger;
//以客戶端Handler構造Messenger並傳遞給服務端,服務端以此向客戶端傳送訊息
private Messenger mSendMessenger = new Messenger(new mainHandler());
private class mainHandler extends Handler{
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
//收到來自服務端的回信
case MessengerService.SERVICE_REPLY_WHAT:
String msgStr = msg.getData().getString(MessengerService.SERVICE_REPLY_KEY);
Toast.makeText(MainActivity.this, msgStr, Toast.LENGTH_SHORT).show();
default:
super.handleMessage(msg);
break;
}
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = new Intent(this,MessengerService.class);
//繫結服務
bindService(intent,mConnection,BIND_AUTO_CREATE);
}
//服務連線
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder Binder) {
//取出來自服務端的Binder物件構建Messenger,以此向服務端傳送訊息
mMessenger = new Messenger(Binder);
Message message = Message.obtain(null,MAIN_SEND_WHAT);
Bundle bundle = new Bundle();
bundle.putString(MAIN_SEND_KEY,"你好Service,這是來自客戶端的問候。");
message.setData(bundle);
//將客戶端Handler構造的Messenger傳給服務端,服務端以此Messenger向客戶端傳送訊息
message.replyTo = mSendMessenger;
try {
mMessenger.send(message);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
}
};
}