Android 使用Messenger實現跨app通訊
Android中使用跨程序通訊有以下幾種方式:檔案、廣播、aidl、messenger,今天要講的是使用messenger來實現跨app通訊也就是在兩個不同的app中實現雙向通訊。其實Messenger底層也是使用aidl的方式來實現的,只不過其使用handler來處理訊息,因為handler是執行緒安全的,所以Messenger也是執行緒安全的,自然Messenger只能處理單執行緒的問題,如果要使用多執行緒就該使用aidl的方式實現。
我們來說下通訊的大致流程:首先我們建立兩個應用A、B,在應用B中建立一個Service取名:BService,然後我們在A中通過bindService來繫結BService,這樣之後兩個App就實現了破冰之旅。
上面的情況只是說明了大體的流程,具體如何實現繫結遠端的BService和如何在BService中來回復A應用,這裡我詳細的說下。我們知道bindService()方法中需要三個引數,
bindService(intent, serviceConnection, BIND_AUTO_CREATE);
第一個為Intent物件,第二個為ServiceConnection,最後一個引數為如何去繫結,一般都是寫的這個值。這些相信大家都非常的清楚了,和平時的繫結服務是一樣的,我們做的也是一樣的,不同的是在ServiceConnection中,我們這樣處理返回的IBinder:
ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
messenger = new Messenger(service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.e("kk", "連結斷開!");
}
};
我們看到,這裡我們使用IBinder來建立Messenger物件,然後我們就可以使用這個mesender來像遠端的服務傳送資料:
Message message = Message.obtain(null, 1);
Bundle bundle = new Bundle();
bundle.putString("data", "我要和B說話!");
message.setData(bundle);
try {
messenger.send(message);//傳送資料
} catch (RemoteException e) {
e.printStackTrace();
}
這裡我們使用messenger.send()方法來發送資料。下面我們來看看BService中的程式碼:
public class BService extends Service {
Messenger messenger = new Messenger(new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
}
});
@Override
public IBinder onBind(Intent intent) {
Log.e("kk", "繫結成功!");
return messenger.getBinder();
}
}
這裡我們使用Messenger.getBinder()方法返回IBinder,和A中的程式碼做比較我們就會發現,這裡使用messenger的getBinder()返回IBinder,A中又通過返回的IBinder建立了一個Messenger物件,所以他們都是用的同一個IBinder物件,這樣通過Messenger傳送的訊息自然是會在B中的Messenger建立時候的Handler裡面來處理了,這樣就實現了A像B應用傳送訊息。
那麼B中如何像A傳送訊息呢???我們知道 Message中有屬性:replyTo,該屬性是一個Messenger類別的,如果我們在A類中將該屬性賦值給一個Messenger物件,然後在B類中獲取到該物件然後通過其傳送訊息,這樣訊息自然就會在A類中的Messenger中來處理,這樣就實現了B類向A類傳送訊息,到這裡我們就實現了雙向的通訊,具體修改後的程式碼這裡我貼出來,首先是A類:
message.replyTo = replyMessenger;
essenger replyMessenger = new Messenger(new Handler() {
@Override
public void handleMessage(Message msg) {
Log.e("kk", msg.getData().getString("data"));
super.handleMessage(msg);
}
});
然後是在B類中:
public class BService extends Service {
Messenger messenger = new Messenger(new Handler() {
@Override
public void handleMessage(Message msg) {
Log.e("kk", msg.getData().getString("data"));
Message message = Message.obtain();
Bundle bundle = new Bundle();
bundle.putString("data","你要說什麼?");
message.setData(bundle);
try {
msg.replyTo.send(message);
} catch (RemoteException e) {
e.printStackTrace();
}
super.handleMessage(msg);
}
});
@Override
public IBinder onBind(Intent intent) {
Log.e("kk", "繫結成功!");
return messenger.getBinder();
}
}
我再貼出A類中所有的程式碼:
public class MainActivity extends AppCompatActivity {
Messenger messenger;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
messenger = new Messenger(service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.e("kk", "連結斷開!");
}
};
Intent intent = new Intent();
intent.setComponent(new ComponentName("com.example.leixinxue.b", "com.example.leixinxue.b.BService"));
bindService(intent, serviceConnection, BIND_AUTO_CREATE);
}
public void sendMessageToB(View view) {
Message message = Message.obtain(null, 1);
message.replyTo = replyMessenger;
Bundle bundle = new Bundle();
bundle.putString("data", "我要和B說話!");
message.setData(bundle);
try {
messenger.send(message);
} catch (RemoteException e) {
e.printStackTrace();
}
}
Messenger replyMessenger = new Messenger(new Handler() {
@Override
public void handleMessage(Message msg) {
Log.e("kk", msg.getData().getString("data"));
super.handleMessage(msg);
}
});
}
A類的佈局檔案:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:onClick="sendMessageToB"
android:text="傳送訊息!" />
</RelativeLayout>
好啦,這裡兩個類就可以實現通訊了,點選A類中的傳送訊息按鈕就可以給B傳送一條訊息,B收到訊息後立馬回覆一個訊息給A。
總結:
兩個app間通訊通過Messenger其實很簡單的,就是通過bindService繫結到遠端的service,然後用在繫結的Serviceconnection中返回的IBinder來建立一個Messenger物件,通過Messenger的send傳送訊息到遠端的服務,遠端的服務通過Message中的屬性replyTo就可以回覆收到的訊息,不要忘了給replyTo賦值。好了,詳細我已經將的很詳細了,如果你還有什麼疑問,歡迎給我留言,bye~~