Android中的IPC机制
介绍Android中多进程开发模式中序列化机制binder AIDL
- Android IPC简介
- 多进程的由来
- Android多进程模式
- Android多进程的运行机制
- Binder
- Android IPC的方式
IPC简介
IPC 是inter Process Communication 的缩写 含义为进程间通信或者跨进程通信,是指的两个进程之间进行数据交换,说起进程通信我们首先想到的是什么是进程,进程跟线程是两个不同的概念 按照操作系统中的描述线程是CPU单元调度的最小的单元,同时线程是一种有限的系统资源,而进程一般指的是执行单元
在PC或者移动设备上指一个程序或者一个应用,当然一个应用也可能包含多个进程,进程与线程的关系是包含于被包含的概念
通过Binder 可以进行进程之间的通信,除了binder Android还支持socket Socket也可以实现任意两个终端之间的通信,
多进程的由来
只有面对多进程才会考虑进程之间的通信,多进程的情况分两种,第一种情况是一个应用因为某种原因自身需要采用多进程的模式来实现,原因可能有很多,比如有些模块由于特殊的原因需要运行在单独的进程中,又或者是为了加大一个应用可使用的内存所以需要多进程来获取多分内存空间Android系统对单个应用所使用的最大的内存做了限制,早期的版本是16M 不同设备之间可能不同, 第二种情况是当前应用需要向其他的应用获取数据,由于是两个应用 所以必须采用跨进程通信的方式来获取数据,甚至我们通过系统提供的ContentProvider 去查询数据的时候其实也是一种进程之间的通信,
开启多进程
在Android中使用多进程只有一种方式就是四大组件(Activity,Service,Receiver,ContentProvider)在AndroidMenifest.xml中指定android:process 属性,除此之外没有其他的方法(可以使用JNO fork一个进程) 创建多进程示例:
<application
android:name=".MyApplication"
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:configChanges="orientation|screenSize"
android:label="@string/app_name"
android:launchMode="standard" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
</intent-filter>
</activity>
<activity
android:name=".SecondActivity"
android:configChanges="screenLayout"
android:label="@string/app_name"
android:process=":remote" />
<activity
android:name=".ThirdActivity"
android:configChanges="screenLayout"
android:label="@string/app_name"
android:process="com.ryg.chapter_2.remote" />
<activity
android:name=".aidl.BookManagerActivity"
android:label="@string/title_activity_book_manager" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category._LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".messenger.MessengerActivity"
android:label="@string/title_activity_messenger" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
</intent-filter>
</activity>
<service
android:name=".messenger.MessengerService"
android:process=":remote" >
<intent-filter>
<action android:name="com.ryg.MessengerService.launch" />
</intent-filter>
</service>
<service
android:name=".aidl.BookManagerService"
android:process=":remote" >
</service>
<activity
android:name=".provider.ProviderActivity"
android:label="@string/title_activity_provider" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category._LAUNCHER" />
</intent-filter>
</activity>
<provider
android:name=".provider.BookProvider"
android:authorities="com.ryg.chapter_2.book.provider"
android:permission="com.ryg.PROVIDER"
android:process=":provider" >
</provider>
<service
android:name=".socket.TCPServerService"
android:process=":remote" />
<activity
android:name=".socket.TCPClientActivity"
android:label="@string/title_activity_tcpclient"
android:windowSoftInputMode="adjustResize" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category._LAUNCHER" />
</intent-filter>
</activity>
<service
android:name=".binderpool.BinderPoolService"
android:process=":remote" />
<activity
android:name=".binderpool.BinderPoolActivity"
android:label="@string/title_activity_binder_pool" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
SecondActivity 与ThirdActivity 分别指定了Activity的Process属性,并且他们指定的属性不同,这意味着当前应用又增加了两个新进程,SecondActivity 创建的进程名字应该是com.ryg.chapter_2:remote ThirdActivity 创建的进程名字应该是 com.rrg.chapter_2.remote 默认的MainActivity 的进程应该是应用的包名:com.ryg.chapter_2
第二个进程与第三个进程之间的区别
首先“:”的含义是指要在当前的进程名字前面附加上当前的包名,这是一种简单的写法,thirdActivity 是一种完成的进程的命名方式,不会附加上包名信息,其次以”:”开头的进程属于当前进程的私有进程,其他应用组件不可以和他跑在同一个进程中,而全局进程名字的进程,其他应用可以通过ShareUID方式和他跑在一个进程中 条件是两个APK的签名必须相同,同时有相同的ShareUID 就可以访问私有的目录,譬如访问data信息,组件信息,甚至是内存数据共享
多进程中间存在的问题
1.静态成员和单例模式完全无效
2.线程同步机制会完全无效
3.SharedPrefrences的可靠性下降
4.Application 会多次创建
序列化操作
serializable:使用简单序列化与反序列化 但是会有大量的IO操作
Pracelable :效率高但是不利于网络传输
Messenger
Messenger通过它可以在不同的进程中传递Message 对象,在Message中放入我们需要传递的数据,就可以轻松的实现数据的进程间的传递,Messenger就是一种轻量级的IPC方案,它的底层就是AIDL。
Messenger中进行数据传递必须要放入Message中,而Messenger 跟Message 都实现了Paracelable 因此可以进行跨进程数据访问, Message中的数据载体只有what arg1,arg2,Bundle 以及replayTo Message中的另一个字段Object 在同一个进程中还是很实用的,但是在进程间通信的时候在Android 2.2以前Object 字段不支持跨进程传输,
Binder意外死亡
Binder是可能意外死亡的,这往往是由于服务端进程意外停止了, 这是我们需要重新连接服务,有两种方法,
1.一种是给Binder 设置DeathRecipient监听,当Binder死亡时候,我们会接收到binderDied 方法的回调,我在binderDied 方法中我们可以重新连接远程服务,
2.在onServerDisconnected 中重连远程服务
两种方法的区别是onServerDisconnected 在客户端的UI线程中在回调,而binderDied 在客户端的Binder 线程池中被回调,也就是说,bindDied不能访问我们的UI线程,这就是他们的区别,
ContentProvider的介绍
ContentProvider 是Android中提供专门用于不同应用之间进行数据共享的方式,从这一点看来ContentProvider 天生就适合进程之间的通信,ContentProvider 底层是Binder,系统内置的ContentProvider 很多,通讯录信息,日程表信息,要跨进程访问这些信息只要通过ContentResolver的query,update,insert,delete,方法即可,