對(duì)于不同進(jìn)程中的Activity和Service侧巨,要實(shí)現(xiàn)IPC(跨進(jìn)程通信)愧捕,其實(shí)就是通過(guò)IBinder接口,其中可能涉及到AIDL編程兔综,和操作系統(tǒng)提供的進(jìn)程通信接口這些底層c++知識(shí)燕刻。然而只泼,Google已經(jīng)為我們封裝了一套Messenger機(jī)制,其底層也是使用AIDL實(shí)現(xiàn)的卵洗。要使用這套機(jī)制请唱,必須為通信雙方建立各自的Messenger,然后Service的Messenger依然是通過(guò)IBinder傳遞到Activity忌怎,Activity也可以將自己的Messenger通過(guò)Message的replyTo屬性傳遞到Service籍滴。
Messenger使用步驟:
- Service需要實(shí)現(xiàn)一個(gè)Hanlder,用以處理從客戶端收到的消息
- 用該Handler創(chuàng)建一個(gè)Messenger對(duì)象榴啸,Messenger對(duì)象內(nèi)部會(huì)引用該Handler對(duì)象
- 用創(chuàng)建好的Messenger對(duì)象獲得一個(gè)IBinder實(shí)例孽惰,并且將該IBinder通過(guò)Service的onBind方法返回給各個(gè)客戶端
- 客戶端通過(guò)收到的IBinder對(duì)象實(shí)例化一個(gè)Messenger對(duì)象,該Messenger內(nèi)部指向指向Service中的Handler鸥印⊙Γ客戶端通過(guò)該Messenger對(duì)象就可以向Service中的Hanlder發(fā)送消息坦报。
- Service中的Hanlder收到消息后,在Handler中的handleMessage方法中處理消息狂鞋。
- 通過(guò)上面的第4步與第5步片择,就完成了客戶端向Service發(fā)送消息并且Service接收到消息的單向通信過(guò)程,即客戶端 -> Service骚揍。如果要實(shí)現(xiàn)Service向客戶端回消息的通信過(guò)程字管,即Service -> 客戶端,那么前提是在客戶端中也需要像Service一樣內(nèi)部維護(hù)有一個(gè)指向Handler的Messenger信不。當(dāng)在第四步中客戶端向Service發(fā)送信息時(shí)嘲叔,將Message的replyTo屬性設(shè)置為客戶端自己的Messenger。這樣在第5步Service在Handler的handleMessage中處理收到的消息時(shí)抽活,可以通過(guò)Message的Messenger再向客戶端發(fā)送Message硫戈,這樣客戶端內(nèi)維護(hù)的Handler對(duì)象就會(huì)收到來(lái)自于Service的Message,從而完成Service向客戶端發(fā)送消息且客戶端接收到消息的通信過(guò)程下硕。
綜上六步就能完成客戶端與Service的跨進(jìn)程雙向通信過(guò)程:
客戶端 -> Service -> 客戶端
為了演示客戶端與Service的跨進(jìn)程通信丁逝,我建立了兩個(gè)應(yīng)用ClientApp和ServiceApp,兩個(gè)應(yīng)用的名稱(chēng)也是見(jiàn)名知意:
- ClientApp, 該App是客戶端梭姓,用于調(diào)用服務(wù)
- ServiceApp霜幼,該App是Service端,用于供客戶端ClientApp調(diào)用
注意:跨進(jìn)程通信使用Bundle糊昙,否則會(huì)報(bào)錯(cuò)Java.lang.RuntimeException: Can’t marshal non-Parcelable objects across processes.
客戶端demo
package com.axaet.servicecommunication;
import android.app.ActivityManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.support.design.widget.FloatingActionButton;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
private static final String TAG = "yushu";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
textView = (TextView) findViewById(R.id.text_show);
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
assert fab != null;
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Message message = Message.obtain(null, 101);
bundle.putString("key","from MainActivity button");
message.setData(bundle);
message.replyTo = messenger;
try {
mService.send(message);
} catch (RemoteException e) {
e.printStackTrace();
}
}
});
}
String getCurProcessName(Context context) {
int pid = android.os.Process.myPid();
ActivityManager mActivityManager = (ActivityManager) context
.getSystemService(Context.ACTIVITY_SERVICE);
for (ActivityManager.RunningAppProcessInfo appProcess : mActivityManager
.getRunningAppProcesses()) {
if (appProcess.pid == pid) {
return appProcess.processName;
}
}
return null;
}
class MyHandler extends Handler {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case 111:
int i = msg.arg1;
if (i == 1) {
Log.i(TAG,"Main="+getCurProcessName(getApplication()));
Bundle bundle=msg.getData();
Toast.makeText(MainActivity.this, "接收到Service消息"+bundle.getString("key"), Toast.LENGTH_SHORT).show();
}
default:
}
}
}
private Bundle bundle = new Bundle();
private Messenger messenger = new Messenger(new MyHandler());
private Messenger mService;
private TextView textView;
private ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.i(TAG, "onServiceConnected: ComponentName = " + name);
mService = new Messenger(service);
textView.setText("連接成功");
Message message = Message.obtain(null, 101);
bundle.putString("key","from MainActivity=11111");
message.setData(bundle);
message.replyTo = messenger;
try {
mService.send(message);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
@Override
protected void onStart() {
super.onStart();
Intent intent = new Intent();
//參數(shù)一為服務(wù)端APP包名辛掠,參數(shù)二為service的完整類(lèi)名
ComponentName name = new ComponentName("com.axaet.servicecommunication", "com.axaet.servicecommunication.MyService");
intent.setComponent(name); //發(fā)送信息
intent.putExtra("data", "msg from MainActivity");
bindService(intent, serviceConnection, BIND_AUTO_CREATE);
}
@Override
protected void onStop() {
super.onStop();
unbindService(serviceConnection);
}
}
服務(wù)端demo
package com.axaet.servicecommunication;
import android.annotation.SuppressLint;
import android.app.ActivityManager;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.util.Log;
import java.util.ArrayList;
import java.util.List;
public class MyService extends Service {
private static final String TAG = "yushu";
public List<String> data = new ArrayList<>();
private Messenger mClient;
@SuppressLint("HandlerLeak")
class MyHandler extends Handler {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case 101:
Bundle bundle=msg.getData();
Log.i(TAG,"service="+ bundle.getString("key"));
Log.i(TAG,"service="+getCurProcessName(getApplication()));
Message message = Message.obtain(null, 111, 1, 1);
bundle.putString("key","from service222222");
message.setData(bundle);
mClient = msg.replyTo;
try {
mClient.send(message);
} catch (RemoteException e) {
e.printStackTrace();
}
default:
}
}
}
String getCurProcessName(Context context) {
int pid = android.os.Process.myPid();
ActivityManager mActivityManager = (ActivityManager) context
.getSystemService(Context.ACTIVITY_SERVICE);
for (ActivityManager.RunningAppProcessInfo appProcess : mActivityManager
.getRunningAppProcesses()) {
if (appProcess.pid == pid) {
return appProcess.processName;
}
}
return null;
}
private Messenger messenger = new Messenger(new MyHandler());
public MyService() {
data.add("This is some msg from " + TAG);
}
@Override
public IBinder onBind(Intent intent) {
String s = intent.getStringExtra("data");
Log.i(TAG, "onBind: 接收 " + s);
data.add(s);
return messenger.getBinder();
}
}
參考文章:http://blog.csdn.net/zhou114108/article/details/52050242