IPC (Interprocess Communication) 即进程间通信,需要用到 IPC 主要有以下原因:
应用内自身原因需要采用多进程,比如,大应用模块多,需要的内存大,而 Android 对单进程内存有大小限制,所以需要多进程获取更多的内存空间; 
当前应用需要获取其他应用数据。 
 
Android 多进程模式 开启多进程模式 Android 中开启多进程有两种方式:
给四大组件在 AndroidManifest 中指定 android:process 属性 
通过 JNI 在 native 层 fork 子进程(属于Linux处理方式) 
 
1 2 3 4 5 6 7 8 9 10 11 <activity       android:name =".FirstActivity"      android:label ="FirstActivity"  /> <activity       android:name =".SecondActivity"      android:label ="SecondActivity"      android:process =":remote"  /> <activity      android:name =".ThirdActivity"      android:label ="ThirdActivity"      android:process ="com.github.tianma8023.ipclearn.remote"  /> 
这里,应用程序的包名是 com.github.tianma8023.ipclearn,其中 FirstActivity 运行在以包名为进程名的默认进程中;而SecondActivity 在启动时,会运行在名为 com.github.tianma8023.ipclearn:remote 的进程中;ThirdActivity 在启动时,会运行在名为 com.github.tianma8023.ipclearn.remote 的进程中。: 开头的进程是当前应用的私有进程,其他应用程序的四大组件不会和它跑在同一个进程中;不以 : 开头的进程是全局进程,其他应用可以通过 ShareUID 的方式和其跑在同一个进程中。
多进程模式弊端 多进程模式会造成如下问题:
静态成员变量以及单例模式失效: 
线程同步机制失效: 
SharedPreferences 可靠性降低SharedPreferences 底层通过读写 XML 文件来实现,在不同进程中并发读写是会产生同步问题的。Application 会多次创建:Application 对象 
从以上信息可以得出:位于不同进程的四大组件之间,但凡通过内从共享数据、变量的,都会共享失败。
Android 中的 IPC 方式 Bundle Activity, Service, BroadcastReceiver 都支持在 Intent 中传递 Bundle 数据,而因为 Bundle 实现了 Parcelable 接口,所以可以在不同的进程间传输,也就是进行了进程间单向通信。
共享文件 既然共享内存会失效,那就通过共享文件的方式,但是也会存在并发读写的问题,所以文件共享方式适合对数据同步要求不高的进程间通信。SharedPreferences 本质是文件读写,但由于 Android 系统对其有缓存策略,即在内存中也会持有 SharedPreferences 的缓存,因此进程间通信不宜用 SharedPreferences。
AIDL AIDL(Android Interface Definition Language) 的进程间通信方式主要依靠 Binder 实现。
定义一个实体类 Book:
1 2 3 4 5 6 7 8 9 10 11 package  com.github.tianma8023.ipclearn.aidl;public  class  Book  implements  Parcelable      public  int  bookId;     public  String bookName;           } 
创建 Book.aidl:
1 2 3 4 5 package  com.github.tianma8023.ipclearn.aidl;parcelable Book; 
创建 IBookManager.aidl 欲实现对 Book 的管理操作:
1 2 3 4 5 6 7 8 9 10 package  com.github.tianma8023.ipclearn.aidl;import  com.github.tianma8023.ipclearn.aidl.Book;interface  IBookManager      List<Book> getBookList ()  ;     void  addBook (in Book book)  } 
AIDL 中仅支持一下几种数据类型:
基本数据类型(int, long, char, boolean, double 等); 
String 和 CharSequence; 
List:只支持 ArrayList,且 List 中的每个元素必须是 AIDL 支持的数据类型; 
Map:只支持 HashMap,且 Map 中的每个元素都必须是 AIDL 支持的数据类型; 
Parcelable:实现了Parcelable的对象; 
AIDL:所有的 AIDL 接口本身也可以在其他 AIDL 文件中使用。 
 
需要注意:
自定义的 Parcelable 对象 和 AIDL 对象必须显式的 import 进来,无论它们是否在同一个包内。 
如果 AIDL 文件中引用了自定义的 Parcelable 对象,则该 Parcelable 对象必须创建一个与它同名的 AIDL 文件,并在其中声明它为 parcelable 类型 
AIDL 文件中除了基本数据类型之外,其他类型参数都需标上:in(输入型参数), out(输出型参数) 或者 inout(输入输出型参数)。因为不同标识的参数底层开销不一样,所以最好别滥用 inout 
之后 build 操作,Android Studio 会在模块 /build 目录下面生成对应的 IBookManager.java 文件,大致内容如下:
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 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68  package  com.github.tianma8023.ipclearn.aidl;  public  interface  IBookManager  extends  android .os .IInterface            public  static  abstract  class  Stub  extends  android .os .Binder  implements  com .github .tianma8023 .ipclearn .aidl .IBookManager           private  static  final  java.lang.String DESCRIPTOR = "com.github.tianma8023.ipclearn.aidl.IBookManager" ;                  public  Stub ()                        }                  public  static  com.github.tianma8023.ipclearn.aidl.IBookManager asInterface (android.os.IBinader obj)   {                  }         @Override          public  android.os.IBinder asBinder ()   {             return  this ;         }         @Override          public  boolean  onTransact (int  code, android.os.Parcel data, android.os.Parcel reply, int  flags)                        }         private  static  class  Proxy  implements  com .github .tianma8023 .ipclearn .aidl .IBookManager               private  android.os.IBinder mRemote;             Proxy(android.os.IBinder remote) {                              }                      @Override              public  android.os.IBinder asBinder ()   {                 return  mRemote;             }             public  java.lang.String getInterfaceDescriptor ()   {                 return  DESCRIPTOR:             }             @Override              public  java.util.List<com.github.tianma8023.ipclearn.aidl.Book> getBookList() throws  android.os.RemoteException {                              }             @Override              public  void  addBook (com.github.tianma8023.ipclearn.aidl.Book book)  throws  android.os.RemoteException                               }         }     }     public  java.util.List<com.github.tianma8023.ipclearn.aidl.Book> getBookList() throws  android.os.RemoteException;     public  void  addBook (com.github.tianma8023.ipclearn.aidl.Book book)  throws  android.os.RemoteException } 
 AS 自动生成的 aidl 对应的 java 类,可以很好的了解 Binder 的工作机制,所以有必要读一读这里的源码。  这里大致介绍下各个字段及方法的含义:
Stub#DESCRIPTOR: Binder 的唯一标识Stub#asInterface(android.os.IBinader obj):服务端  的 Binder 对象转化成 客户端  所需要的 AIDL 接口类型的对象。当服务端和客户端位于同一进程中时,此方法返回的就是服务端对象本身。当它们不在同一个进程中时,返回的是由系统封装后的 Stub.Proxy 对象(也就是需要转换)Stub#asBinder(): 返回当前 Binder 对象Stub#onTransact(int code, Parcel data, Parcel reply, int flags):服务端 的 Binder 线程池中。客户端发起的跨进程请求会通过系统底层封装后交由此方法处理。服务端通过 code 参数确认接下来调用执行的目标方法。Proxy#getBookList():客户端 。客户端使用此方法进行跨进程调用时,会转化为让服务端(远端)的 Binder 执行 transact 方法,与此同时客户端线程挂起,并最终调用服务端的 onTransact,即调用上一条的 Stub#onTransact() 方法,当服务端相应方法执行完毕后返回结果后,客户端当前线程结束挂起,继续执行,并取出服务端返回的结果。Proxy#addBook():与上述的 Proxy#getBookList() 类似 
Binder 的工作机制图:
当客户端发起远程请求时,客户端当前线程会被挂起,等待服务端进程返回结果,所以,如果服务端进程很耗时,则不能在 UI 线程中发起远程请求。
远程服务端实现 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 30 31 32 33 public  class  BookManagerService  extends  Service      private  static  final  String TAG = "BookManagerService" ;     private  CopyOnWriteArrayList<Book> mBookList = new  CopyOnWriteArrayList<Book>();     private  Binder mBinder = new  IBookManager.Stub() {         @Override          public  List<Book> getBookList ()  throws  RemoteException              return  mBookList;         }         @Override          public  void  addBook (Book book)  throws  RemoteException              mBookList.add(book);         }     };     public  BookManagerService ()       }     @Override      public  IBinder onBind (Intent intent)           return  mBinder;     }     @Override      public  void  onCreate ()           super .onCreate();         mBookList.add(new  Book(1 , "Think In Java" ));         mBookList.add(new  Book(2 , "Android Programing" ));     } } 
在 AndroidManifest 中将 BookManagerService 置于独立进程中,实现对进程间通信的模拟:
1 2 3 <service       android:name =".aidl.BookManagerService"      android:process =":remote"  /> 
因为 IBookManager.Stub 类是 Binder 的一个抽象子类,所以在 Serivce 中实现 IBookManager.Stub 即可在 onBind() 中返回相应的 Binder 对象。 
考虑到 AIDL 中的方法是在服务端的 Binder 线程池中执行的,所以考虑同步就使用了 CopyOnWriteArrayList。注意到 CopyOnWriteArrayList 并不是 ArrayList 的子类,但其实现的最基本的底层原理和 ArrayList 一致(基于数组,可以通过下标 index 进行访问等)。虽然服务端返回的是 CopyOnWriteArrayList,但 Binder 可以通过相同的机理去访问 CopyOnWriteArrayList 中的数据并最终形成新的 ArrayList 返回给客户端。这就与之前提到的 AIDL支持的 List 只有 ArrayList 并不冲突了。 
 
客户端跟绑定普通服务的客户端一致,比较简单:
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 public  class  BookManagerActivity  extends  Activity      private  static  final  String TAG = "BookManagerActivity" ;     private  ServiceConnection mConnection = new  ServiceConnection() {         @Override          public  void  onServiceConnected (ComponentName name, IBinder service)               IBookManager bookManager = IBookManager.Stub.asInterface(service);             try  {                                  List<Book> bookList = bookManager.getBookList();                 Log.i(TAG, "book list type: "  + bookList.getClass().getCanonicalName());                 Log.i(TAG, "query book list: "  + bookList);             } catch (RemoteException e) {                 e.printStackTrace();             }         }         public  void  onServiceDisconnected (ComponentName name)           }     };     @Override      protected  void  onCreate (Bundle savedInstanceState)           super .onCreate(savedInstanceState);         setContentView(R.layout.activity_book_manager);         Intent intent = new  Intent(this , BookManagerService.class);         bindService(intent, mConnection, Context.BIND_AUTO_CREATE);     }     @Override      protected  void  onDestroy ()           unbindService(mConnection);         super .onDestroy();     } } 
以上是 AIDL 的基本用法,进阶用法请参考 Android 笔记:AIDL进阶 
Messenger 使用 Messenger 可以在不同的进程之间传递 Message 对象,实现进程间数据交互通信。
Messenger 的构造函数:
1 2 3 4 5 6 7 public  Messenger (Handler target)      mTarget = target.getIMessenger(); } public  Messenger (IBinder target)      mTarget = IMessenger.Stub.asInterface(target); } 
通过第二个构造函数可以看出来,Messegner 的底层就是 AIDL。
Messenger 对 AIDL 做了封装,由于 Messenger 机制一次只能处理一个请求,因此在服务端不需要考虑线程同步。
Messenger 远程服务端 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 30 31 32 33 34 35 public  class  MessengerServerService  extends  Service      private  static  final  String TAG = "MessengerServerService" ;     private  final  Messenger mMessenger = new  Messenger(new  MessengerHandler());     private  static  class  MessengerHandler  extends  Handler           @Override          public   void  handleMessage (Message msg)               switch (msg.what) {                 case  TConstants.MSG_FROM_CLIENT:                                          Log.i(TAG, "msg from client: "  + msg.getData().get(TConstants.KEY_MSG));                                          Messenger client = msg.replyTo;                     Bundle replyBundle = new  Bundle();                     replyBundle.putString(TConstants.KEY_SERVER, "Okay, I'm server, your message has been received." );                     Message replyMsg = Message.obtain(null , TConstants.MSG_FROM_SERVER);                     replyMsg.setData(replyBundle);                     try  {                         client.send(replyMsg);                     } catch  (RemoteException e) {                         e.printStackTrace();                     }                     break ;             }             super .handleMessage(msg);         }     }     @Override      public  IBinder onBind (Intent intent)           return  mMessenger.getBinder();     } } 
注册 Service 运行在单独进程中:
1 2 3 <service       android:name =".messenger.MessengerServerService"      android:process =":remote"  /> 
Messenger 客户端 Activity :
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 48 49 50 51 52 53 54 55 56 57 58 59 60 public  class  MessengerClientActivity  extends  Activity      private  static  final  String TAG = "MessengerClientActivity" ;          private  Messenger mMessenger;     private  ServiceConnection mConnection = new  ServiceConnection() {         @Override          public  void  onServiceConnected (ComponentName name, IBinder service)                            mMessenger = new  Messenger(service);             Message msg = Message.obtain(null , TConstants.MSG_FROM_CLIENT);             Bundle data = new  Bundle();             data.putString(TConstants.KEY_MSG, "Hello, this is client." );             msg.setData(data);                          msg.replyTo = mGetReplyMessenger;             try  {                 mMessenger.send(msg);             } catch  (RemoteException e) {                 e.printStackTrace();             }         }         @Override          public  void  onServiceDisconnected (ComponentName name)                        }     }          private  Messenger mGetReplyMessenger = new  Messenger(new  MessengerHandler());     private  static  class  MessengerHandler  extends  Handler           @Override          public  void  handleMessage (Message msg)               switch  (msg.what) {                 case  TConstants.MSG_FROM_SERVER:                     Log.i(TAG, "msg from server: "  + msg.getData().getString(TConstants.KEY_REPLY));                     break ;             }             super .handleMessage(msg);         }     }     @Override      protected  void  onCreate (Bundle savedInstanceState)           super .onCreate(savedInstanceState);         setContentView(R.layout.activity_messenger_client);         Intent intent = new  Intent(this , MessengerServerService.class);         bindService(intent, mConnection, Context.BIND_AUTO_CREATE);     }     @Override      protected  void  onDestroy ()           unbindService(mConnection);         super .onDestroy();     } } 
注意:  Message 的 obj 字段,在 Android 2.0 以前不支持跨进程传输,在 Android 2.0 以后也仅仅在系统提供的实现了 Parcelable 接口的对象上才能支持跨进程传输。
ContentProvider ContentProvider 底层也是由 AIDL 实现,其主要有6个抽象方法:onCreate, getType, query, update, insert, delete, 其中除了 onCreate 由系统调用运行在主线程之外,其他的都由外界回调运行在 Binder 线程池中。
注意,ContentProvider 底层依赖的数据存储没有要求,可以用 SQLite 数据库,也可以用普通文件,亦可以用 SharedPreferences,不过通常情况下底层存储都是依赖的数据库。
在客户端要观察 ContentProvider 中的数据变化情况,可以通过 ContentResolver#registerContentObserver 方法来注册观察者,ContentResolver#unregisterContentObserver 取消注册。
Socket Socket 也可以实现进程间通信,可以凭借 TCP 或者 UDP 的套接字来实现。与一般的 Socket 编程没有太大区别,主要是在 Android 编程中需要考虑在主线程上更新UI,在子线程发起 Socket 请求即可。
各个 IPC 方式对比 
名称 
优点 
缺点 
适用场景 
 
 
Bundle 
简单 
只能传输Bundle支持的数据 
四大组件间的进程间通信 
 
文件共享 
简单易用 
不适合并发场景,无法做到进程间即时通信 
无并发访问的情景,交换简单的数据,实时性要求不高的场景 
 
AIDL 
功能强大,支持一对多并发通信,支持即时通信 
使用稍复杂,需要处理线程同步 
一对多通信,有RPC需求 
 
Messenger 
功能一般,支持一对多串行通信,支持即时通信 
不适用于高并发场景,数据只能通过Message进行传输,只能传输Bundle支持的数据类型 
适用于低并发的一对多的即时通信,无RPC需求,或者不需要返回结果的PRC需求 
 
ContentProvider 
在数据源访问方面功能强大,支持一对多并发数据共享,可以通过Call扩展其他方法操作 
受约束的AIDL,主要提供数据源的CRUD操作 
一对多进程间的数据共享 
 
Socket 
功能强大,可以通过网络传输字节流,支持一对多并发即时通信 
实现起来稍微麻烦,不支持直接的RPC 
网络数据交换 
 
代码参考 IPCLearn