IPC簡介
IPC,即Inter-Process Communication進程間通信或者跨進程通信,是指兩個進程之間進行數據交換的過程。
android中的IPC方式有很多種,以下是幾個簡單的對比:以上幾種各有利弊,可能我們平時用的多的還是Bundle、文件共享、AIDL、ContentProvider這幾種,對於Messenger這種方式很少用,而本章內容爲了彌補這塊的缺憾特寫此貼,希望我們的知識又能擴展擴展,不好勿噴。
Messenger
Messenger可以翻譯爲信使,通過它可以在不同進程中傳遞Message對象,這時候可能會聯想到咱們之前學的Handler對象,只不過Handler對象主要是進行線程間的數據通信的,而現在的Messenger則是進程間的通信的。
Messenger是一種輕量級的IPC方案,它的底層實現是AIDL;它實際上是對AIDL的一種封裝。
下面是Messenger類的繼承關係:
使用Messenger與之前使用的Handler類似,同樣分爲服務端和客戶端。
- 服務端進程
拿Service舉例,需要創建一個Messenger對象,用於接收Activity中發送過來的消息,服務端代碼如下:
- 服務端進程
public class MyService extends Service{
private Messenger messenger;
private Handler handler;
@Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
handler = new Handler(new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
// TODO Auto-generated method stub
//獲取從Activity中發送過來的消息
Bundle bundle = msg.getData();
String str = bundle.getString("msg");
System.out.println("----->>"+str);
//回執消息 即服務器收到消息之後可以反向給客戶端發送消息
Messenger servi = msg.replyTo;//獲得從客戶端傳過來的信使對象Messenger
Message reMsg = Message.obtain();
Bundle bundle2 = new Bundle();
bundle2.putString("msg", "消息回來了");
reMsg.setData(bundle2);
try {
servi.send(reMsg);//向Activity中發送回執消息
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return false;
}
});
//通過Handler對象創建一個Messenger對象
messenger = new Messenger(handler);
}
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
//從Messenger對象中獲取IBinder對象並返回
return messenger.getBinder();
}
}
備註:此處的replyTo主要是爲了反向傳輸數據,即Service向ACtivity發送數據,Service中需要獲得Activity創建的Messenger對象,用於消息的發送。
- 客戶端進程
相當於綁定服務的Activity對象,首先需要綁定服務端的Service,成功後用服務端返回的IBinder對象創建一個Messenger,通過這個Messenger就可以向服務端發送消息了。
public class MessengerActivity extends Activity{
private Messenger messenger,replyMessenger;
private Handler handler;
private ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
// TODO Auto-generated method stub
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// TODO Auto-generated method stub
//服務綁定成功之後 通過返回的IBinder對象創建Messenger對象 用於消息的發送
messenger = new Messenger(service);
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_b);
handler = new Handler(new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
// TODO Auto-generated method stub
//獲取從Service中發送過來的數據
Bundle bundle = msg.getData();
String str = bundle.getString("msg");
System.out.println("======>>>>"+str);
return false;
}
});
//創建一個Messenger對象 用於接收從Service中發送過來的消息
replyMessenger = new Messenger(handler);
//啓動服務 採用的是bindService的方式
Intent intent = new Intent(this, MyService.class);
bindService(intent, conn, Context.BIND_AUTO_CREATE);
}
@Override
protected void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
//解綁服務對象
unbindService(conn);
}
public void onMyClick(View v) {
if (messenger != null) {
//構建要發送的Message消息
Message msg = Message.obtain();
Bundle bundle = new Bundle();
bundle.putString("msg", "hello word");
msg.setData(bundle);
msg.replyTo = replyMessenger;//如果想收到服務器向客戶端發送過來的消息 必須把回執類傳遞給服務類
try {
messenger.send(msg);//發送消息 向存活在另一進程的service
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
總結上述代碼的工作原理,如下圖所示:
注意:在AndroidManifest.xml文件中爲了更能體現進程間的通信,可將Service註冊爲遠程服務:即
<service android:name="com.example.exampledemo.MyService"
android:process=":remote"></service>