1、先对比一下,咱们要知道什么时候使用Messenger更合适,下面是官网给出的解释。
Messenger 与 AIDL 比较
当您需要执行 IPC 时,为您的接口使用 Messenger
要比使用 AIDL 实现它更加简单,因为 Messenger
会将所有服务调用排入队列,而纯粹的 AIDL 接口会同时向服务发送多个请求,服务随后必须应对多线程处理。
对于大多数应用,服务不需要执行多线程处理,因此使用 Messenger
可让服务一次处理一个调用。如果您的服务必须执行多线程处理,则应使用 AIDL 来定义接口。
2、创建一个独立进程的服务
public class MyService extends Service {
static final int MSG_SAY_HELLO = 1;
class IncomingHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_SAY_HELLO:
Toast.makeText(getApplicationContext(), "hello!", Toast.LENGTH_SHORT).show();
break;
default:
super.handleMessage(msg);
}
}
}
/**
* Target we publish for clients to send messages to IncomingHandler.
*/
final Messenger mMessenger = new Messenger(new IncomingHandler());
@Nullable
@Override
public IBinder onBind(Intent intent) {
Toast.makeText(getApplicationContext(), "binding", Toast.LENGTH_SHORT).show();
return mMessenger.getBinder();
}
}
IncomingHandler用来接受我们从客户端传递过来的消息
mMessenger可以看作一个承载Handler可以跨进程的信使
别忘了独立进程的服务需要加process
<service android:name=".MyService"
android:exported="false"
android:process=":myService"
></service>
3、客户端链接服务端
客户端只需根据服务返回的 IBinder
创建一个 Messenger
,然后利用 Messenger
send()方法
发送消息
public class MainActivity extends AppCompatActivity {
final String TAG = getClass().getSimpleName();
Messenger mService = null;
boolean mBound;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mService = new Messenger(service);
mBound = true;
}
@Override
public void onServiceDisconnected(ComponentName name) {
mService = null;
mBound = false;
}
};
public void sayHello(View v) {
if (!mBound) return;
// Create and send a message to the service, using a supported 'what' value
Message msg = Message.obtain(null, MyService.MSG_SAY_HELLO, 0, 0);
try {
mService.send(msg);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
protected void onStart() {
super.onStart();
bindService(new Intent(this,MyService.class),mConnection,Context.BIND_AUTO_CREATE);
}
@Override
protected void onStop() {
super.onStop();
if (mBound) {
unbindService(mConnection);
mBound = false;
}
}
}
这样就实现了与服务端的链接和给服务端发送消息的实例。
4、实现服务端回传数据给客户端
实现方式其实是很简单,同样用Messenger。首先在客户端创建一个Handler和Messenger,在服务链接成功后onServiceConnected方法里通过Message的replyTo方法赋值 使用服务端的Messenger的send方法回传回去。
public class MainActivity extends AppCompatActivity {
final String TAG = getClass().getSimpleName();
Messenger mService = null;
boolean mBound;
static final int MSG_RESULT_CODE = 1;
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_RESULT_CODE:
msg.getData().setClassLoader(Book.class.getClassLoader());
Book book = msg.getData().getParcelable("book");
Toast.makeText(MainActivity.this,""+ book.toString(),Toast.LENGTH_SHORT).show();
break;
default:
super.handleMessage(msg);
}
}
};
final Messenger mMessenger = new Messenger(mHandler);
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mService = new Messenger(service);
mBound = true;
Message message = new Message();
message.replyTo = mMessenger;
message.what = MyService.MSG_REQUEST_MESSAGE;
try {
mService.send(message);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
mService = null;
mBound = false;
}
};
.........
}
public class Book implements Parcelable {
String name;
int price;
public Book() {}
protected Book(Parcel in) {
writeToParcel(in);
}
public void writeToParcel(Parcel in) {
name = in.readString();
price = in.readInt();
}
public static final Creator<Book> CREATOR = new Creator<Book>() {
@Override
public Book createFromParcel(Parcel in) {
return new Book(in);
}
@Override
public Book[] newArray(int size) {
return new Book[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeInt(price);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
@Override
public String toString() {
return "Book{" +
"name='" + name + '\'' +
", price=" + price +
'}';
}
}
注意:在使用Messenger进行跨进程通信时,传递非基本类型和系统类型需要实现Parcelable接口,并且在取数据前Bundle要
setClassLoader,具体请看https://blog.youkuaiyun.com/dongbaoming/article/details/54312824
5、服务端接受客户端的Messenger,并使用客户端的Messenger回传数据
public class MyService extends Service {
static final int MSG_SAY_HELLO = 1;
static final int MSG_REQUEST_MESSAGE = 2;
private Messenger mRequestMessenger = null;
class IncomingHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_SAY_HELLO:
Toast.makeText(getApplicationContext(), "hello!", Toast.LENGTH_SHORT).show();
Book book = new Book();
book.setName("Java 编程思想");
book.setPrice(66);
Message message = new Message();
message.what = MainActivity.MSG_RESULT_CODE;
message.getData().putParcelable("book",book);
try {
mRequestMessenger.send(message);
} catch (RemoteException e) {
e.printStackTrace();
}
break;
case MSG_REQUEST_MESSAGE:
mRequestMessenger = msg.replyTo;
break;
default:
super.handleMessage(msg);
}
}
}
.......................
}
简单的跨进程Service通信已经完成了。