前言
Android IPC (Inter-Process Communication) 进程间通信或跨进程通信。
主要是 Binder 、AIDL 及 Android 跨进程通信的实现方式及原理简单梳理。
Android 中如何实现多进程。
通过给四大组件 (Activity、Service、Broadcast Receiver、ContentProvider )在 AndroidManifest.xml
文件中指定 android:process
属性即可。
当然,除了自身实现多进程之外,和其他应用通信其实也是在不经意中做了跨进程通信的事情。
Service 多进程
1 2 3 4 5
| <service android:name=".ipc.messenger.MessengerService" android:enabled="true" android:process=":remote" android:exported="false" />
|
Activity 多进程
1 2 3 4 5 6
| <activity android:name=".ui.behavior.lifecycle.ActivityB" android:process="com.engineer.android.mini.remote" /> <activity android:name=".ui.behavior.lifecycle.ActivityC" android:process=":remote" />
|
以上两种 process 属性的实现下,
- ActivityB 的进程名即为: com.engineer.android.mini.remote, 同时此类进程属于全局进程,其他应用通过 ShareUID 的方式可以和他运行在同一个进程中。
- ActivityC 的进程名为:{pacakage}:remote,同时此类进程属于当前应用的私有进程。
Android 跨进程的几种方式
Bundle
Activity/Service/Receiver 都可以通过 Intent 传递数据,同时 Intent.putExtras(Bundle bundle) 方法支持传递 Bundle,通过 Bundle 我们可以封装细碎的数据,比如基本类似,实现了 Parcelable 接口的对象和 Android 支持的一些特殊的对象。
使用文件共享
并入 A 进程写入,B 进程进行读操作。当然,需要考虑并发读写的问题。SharedPerference 不支持多进程。
Messenger
Messenger 其实就是对 AIDL 的一层封装,是一种轻量级的 IPC。
1 2 3 4 5 6 7 8 9 10 11 12 13
| public class MessengerService extends Service { private static final String TAG = "MessengerService";
public MessengerService() { }
private final Messenger messenger = MessengerDelegate.provideMessenger();
@Override public IBinder onBind(Intent intent) { return messenger.getBinder(); } }
|
1 2 3 4 5
| <service android:name=".ipc.messenger.MessengerService" android:enabled="true" android:process=":remote" android:exported="false" />
|
Service 在启动之后,在 onBind 中就可以通过 Messenger 获取到 IBinder 了。
客户端启动 Service
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| private Messenger mRepliedMessenger = MessengerDelegate.provideMessenger();
private ServiceConnection mConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { Messenger messenger = new Messenger(service); Message message = Message.obtain(null, IPCConstants.MESSAGE_FROM_CLIENT); Bundle bundle = new Bundle(); bundle.putString("msg", "this is from client"); message.setData(bundle); message.replyTo = mRepliedMessenger; try { messenger.send(message); } catch (RemoteException e) { e.printStackTrace(); } }
@Override public void onServiceDisconnected(ComponentName name) {
} };
Intent intent = new Intent(IpcActivity.this, MessengerService.class); bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
|
在 onServiceConnected 中,通过服务端返回的 IBinder 对象,我们创建了本地的 Messenger 对象。同时创建了一个 Message 通过 Messenger.send(Message) 的方式,将一些数据发送到服务端去。**同时设定 Message 的 replayTo 属性为我们在本地创建的另一个 Messenger;mRepliedMessenger 。下面看看 Messenger 是如何处理消息的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| public class MessengerDelegate { private static final String TAG = "MessengerDelegate";
public static Messenger provideMessenger() { return new Messenger(new MessengerHandler(Looper.myLooper())); }
private static class MessengerHandler extends Handler { public MessengerHandler(Looper looper) { super(looper); }
@Override public void handleMessage(@NonNull Message msg) { super.handleMessage(msg); switch (msg.what) { case IPCConstants.MESSAGE_FROM_CLIENT: Bundle data = msg.getData(); String result = data.getString("msg");
Log.e(TAG, "handleMessage: data = " + data); Log.e(TAG, "handleMessage: result = " + result);
Messenger client = msg.replyTo; Message reply = Message.obtain(null, IPCConstants.MESSAGE_FROM_SERVER); Bundle bundle = new Bundle(); bundle.putString("reply", "server got message, and replied with happy"); reply.setData(bundle); try { client.send(reply); } catch (RemoteException e) { e.printStackTrace(); } break; case IPCConstants.MESSAGE_FROM_SERVER: Bundle data1 = msg.getData(); String result1 = data1.getString("reply");
Log.e(TAG, "handleMessage: data = " + data1); Log.e(TAG, "handleMessage: result = " + result1); break; default: super.handleMessage(msg); } } } }
|
简单总结 ;
- 服务端收到客户端发送的消息后,通过 message.replyTo 获取到客户端要接收消息的 Messenger 对象。然后从服务端发送了新的消息去往客户端。
- 客户端接收消息也是,也是通过本地创建的 Messenger;mRepliedMessenger 的接收信息。
- 就服务端和客户端来说,他们本地的 Messenger 对象都是通过 Handler 创建的,客户端在启动服务端之后,为了向服务端发送消息,创建 Messenger 是通过服务端返回的 IBinder 对象实现的。
可以看到 Messenger 主要是串行的在服务端和客户端之间进行消息的传递。
AIDL
准备
- 创建实现了 Parcelable 接口的类,以便用于在进程间通信
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| package com.engineer.android.mini.ipc.aidl;
public class Book implements Parcelable {
public int bookId; public String bookName;
public Book(int bookId, String bookName) { this.bookId = bookId; this.bookName = bookName; }
@Override public int describeContents() { return 0; }
@Override public void writeToParcel(Parcel dest, int flags) { dest.writeInt(bookId); dest.writeString(bookName); } public static final Parcelable.Creator<Book> CREATOR = new Parcelable.Creator<Book>() {
@Override public Book createFromParcel(Parcel source) { return new Book(source); }
@Override public Book[] newArray(int size) { return new Book[size]; } };
private Book(Parcel in) { bookId = in.readInt(); bookName = in.readString(); } }
|
1 2 3
| // Book.aidl package com.engineer.android.mini.ipc.aidl; parcelable Book;
|
1 2 3 4 5 6 7 8 9 10 11 12
| // IBookInterface.aidl package com.engineer.android.mini.ipc.aidl; import com.engineer.android.mini.ipc.aidl.Book;
interface IBookInterface {
void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString); // List<Book> getBookList(); void addBook(in Book book); }
|