什么是IPC機制
IPC為Inter-Process Communication的縮寫,含義為進程間的通信或者跨進程通信尼斧。
為什么使用IPC機制
- 獲取到更多的內(nèi)存
在Android系統(tǒng)中一個應用默認只有一個進程孤钦,每個進程都有自己獨立的資源和內(nèi)存空間扭勉,其它進程不能任意訪問當前進程的內(nèi)存和資源痘括,系統(tǒng)給每個進程分配的內(nèi)存會有限制姓蜂。如果一個進程占用內(nèi)存超過了這個內(nèi)存限制萎羔,就會報OOM的問題液走,很多涉及到大圖片的頻繁操作或者需要讀取一大段數(shù)據(jù)在內(nèi)存中使用時,很容易報OOM的問題贾陷。
- 實現(xiàn)數(shù)據(jù)的共享
Android中常見的IPC方式
- Bundle:使用Intent傳遞Bundle數(shù)據(jù)
- 文件共享:兩個進程通過讀/寫同一個文件來交換數(shù)據(jù)
- Messager:在不同進程中傳遞Message對象缘眶,將數(shù)據(jù)存放在Message對象中
- AIDL:一種IDL語言,用于生成Android設(shè)備上兩個進程之間通信的代碼
- ContentProvider:Android中提供的專用于不同應用間進行數(shù)據(jù)共享的方式
- Socket:通過Socket實現(xiàn)進程之間的通信
如何使用AIDL實現(xiàn)IPC
- 創(chuàng)建AIDL接口:
// IMyAidlInterface.aidl
package com.example.lq.ipcdemo;
interface IMyAidlInterface {
int findFactorialService(int x);
}
- 創(chuàng)建客戶端:
private ServiceConnection serviceConnection;
private IMyAidlInterface iMyAidlInterface;
//創(chuàng)建服務(wù)連接
serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//獲取到IMyAidlInterface實例對象
iMyAidlInterface = IMyAidlInterface.Stub.asInterface(service);
//調(diào)用iMyAidlInterface中的方法
int result = iMyAidlInterface.findFactorialService(10);
}
@Override
public void onServiceDisconnected(ComponentName name) {
iMyAidlInterface = null;
}
};
- 創(chuàng)建服務(wù)端:
public class MyService extends Service {
//創(chuàng)建IBinder對象
private IBinder binder = new IMyAidlInterface.Stub(){
@Override
public int findFactorialService(int x) throws RemoteException {
int fact = 1;
for (int i = 1; i <= x; i ++){
fact = fact * i;
}
return fact;
}
};
@Nullable
@Override
public IBinder onBind(Intent intent) {
return binder; //返回IBinder對象
}
}
IPC通信方式:Binder機制
簡而言之髓废,Binder機制就是Android中的一種跨進程通信方式巷懈。
AIDL自動生成的Java文件類
public interface IMyAidlInterface extends android.os.IInterface {
public static abstract class Stub extends android.os.Binder implements com.example.lq.ipcdemo.IMyAidlInterface {
private static final java.lang.String DESCRIPTOR = "com.example.lq.ipcdemo.IMyAidlInterface";
public Stub() {
this.attachInterface(this, DESCRIPTOR);
}
public static com.example.lq.ipcdemo.IMyAidlInterface asInterface(android.os.IBinder obj) {
if ((obj == null)) {
return null;
}
//判斷服務(wù)端與客戶端是否在同一進程
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin != null) && (iin instanceof com.example.lq.ipcdemo.IMyAidlInterface))) {
return ((com.example.lq.ipcdemo.IMyAidlInterface) iin);
}
//跨進程通信,交給Proxy代理類處理
return new com.example.lq.ipcdemo.IMyAidlInterface.Stub.Proxy(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) throws android.os.RemoteException {
switch (code) {
case INTERFACE_TRANSACTION: {
reply.writeString(DESCRIPTOR);
return true;
}
case TRANSACTION_findFactorialService: {
data.enforceInterface(DESCRIPTOR);
int _arg0;
//解析獲取參數(shù)
_arg0 = data.readInt();
//調(diào)用實現(xiàn)方法
int _result = this.findFactorialService(_arg0);
//寫入結(jié)果到reply中
reply.writeNoException();
reply.writeInt(_result);
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
private static class Proxy implements com.example.lq.ipcdemo.IMyAidlInterface {
//返回一個Proxy對象
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote) {
mRemote = remote;
}
@Override
public android.os.IBinder asBinder() {
return mRemote;
}
public java.lang.String getInterfaceDescriptor() {
return DESCRIPTOR;
}
@Override
public int findFactorialService(int x) throws android.os.RemoteException {
//獲取到Parcel對象
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
int _result;
try {
//將描述符和參數(shù)寫入_data中
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeInt(x);
//調(diào)用底層的transact方法將結(jié)果寫入_reply
mRemote.transact(Stub.TRANSACTION_findFactorialService, _data, _reply, 0);
//解析并返回結(jié)果
_reply.readException();
_result = _reply.readInt();
} finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
}
static final int TRANSACTION_findFactorialService = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
}
public int findFactorialService(int x) throws android.os.RemoteException;
}
實際上慌洪,其內(nèi)部主要含有兩個核心內(nèi)部類Stub和Proxy顶燕。若客戶端和服務(wù)端位于同一進程凑保,則返回服務(wù)端的Stub對象本身,否則返回的是系統(tǒng)封裝后的Stub.Proxy對象涌攻。
transact:客戶端發(fā)送跨進程請求欧引,將參數(shù)傳遞進去
onTransact:監(jiān)聽到客戶端的請求,服務(wù)端會通過系統(tǒng)封裝后交由方法處理恳谎,傳入data參數(shù)芝此,獲取到reply結(jié)果。
transact與onTransact之間的關(guān)系:
客戶端調(diào)用服務(wù)端方法流程圖:
實現(xiàn)AIDL雙向通信:服務(wù)端定時向客戶端發(fā)送消息
- 接口類
interface IServiceCallback {
void notifyClient(String msg);
}
import com.example.lq.ipcdemo.IServiceCallback;
interface IMyAidlInterface {
int findFactorialService(int x);
void registerCallback(IServiceCallback callback);
void unregisterCallback(IServiceCallback callback);
}
- 服務(wù)端類
public class MyService extends Service {
//創(chuàng)建RemoteCallbackList列表
private RemoteCallbackList<IServiceCallback> mCallbacks = new RemoteCallbackList<>();
private IBinder binder = new IMyAidlInterface.Stub(){
@Override
public int findFactorialService(int x) throws RemoteException {
int fact = 1;
for (int i = 1; i <= x; i ++){
fact = fact * i;
}
return fact;
}
//注冊
@Override
public void registerCallback(IServiceCallback callback) throws RemoteException {
mCallbacks.register(callback);
}
//注銷
@Override
public void unregisterCallback(IServiceCallback callback) throws RemoteException {
mCallbacks.unregister(callback);
}
};
//通知所有連接服務(wù)的客戶端
private void notifyMessage(String msg){
final int len = mCallbacks.beginBroadcast();
for (int i = 0; i < len; i ++){
try {
mCallbacks.getBroadcastItem(i).notifyClient(msg);
} catch (RemoteException e) {
e.printStackTrace();
}
}
mCallbacks.finishBroadcast();
}
@Override
public void onCreate() {
super.onCreate();
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
notifyMessage("Hello,Client!");
}
}, 10000, 1000);
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return binder;
}
}
- 客戶端類
IServiceCallback callback = new IServiceCallback.Stub(){
@Override
public void notifyClient(String msg) throws RemoteException {
showToast(msg);
}
};
serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
iMyAidlInterface = IMyAidlInterface.Stub.asInterface(service);
try {
iMyAidlInterface.registerCallback(callback);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
try {
iMyAidlInterface.unregisterCallback(callback);
} catch (RemoteException e) {
e.printStackTrace();
}
iMyAidlInterface = null;
}
};
ContentProvider的Binder實現(xiàn)
ContentProvider是Android中提供的專門用于不同應用之間進行數(shù)據(jù)共享的方式因痛,系統(tǒng)預制了許多ContentProvider婚苹,比如通信錄信息,日程表信息等鸵膏。
ContentProvider的query操作:
getContentResolver().query(uri, projection, selection, selectionArgs, sortOrder);
對應的transact方法:
public Cursor query(String callingPkg, Uri url, String[] projection, String selection,
String[] selectionArgs, String sortOrder, ICancellationSignal cancellationSignal)
throws RemoteException {
//實例化BulkCursorToCursorAdaptor對象
BulkCursorToCursorAdaptor adaptor = new BulkCursorToCursorAdaptor();
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
try {
data.writeInterfaceToken(IContentProvider.descriptor);
data.writeString(callingPkg);
url.writeToParcel(data, 0);
int length = 0;
if (projection != null) {
length = projection.length;
}
data.writeInt(length);
for (int i = 0; i < length; i++) {
data.writeString(projection[i]);
}
data.writeString(selection);
if (selectionArgs != null) {
length = selectionArgs.length;
} else {
length = 0;
}
data.writeInt(length);
for (int i = 0; i < length; i++) {
data.writeString(selectionArgs[i]);
}
data.writeString(sortOrder);
data.writeStrongBinder(adaptor.getObserver().asBinder());
data.writeStrongBinder(cancellationSignal != null ? cancellationSignal.asBinder() : null);
//發(fā)送給Binder服務(wù)端
mRemote.transact(IContentProvider.QUERY_TRANSACTION, data, reply, 0);
DatabaseUtils.readExceptionFromParcel(reply);
if (reply.readInt() != 0) {
BulkCursorDescriptor d = BulkCursorDescriptor.CREATOR.createFromParcel(reply);
adaptor.initialize(d);
} else {
adaptor.close();
adaptor = null;
}
return adaptor;
} catch (RemoteException ex) {
adaptor.close();
throw ex;
} catch (RuntimeException ex) {
adaptor.close();
throw ex;
} finally {
data.recycle();
reply.recycle();
}
}
對應的onTranct方法:
public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
throws RemoteException {
switch (code) {
case QUERY_TRANSACTION:{
data.enforceInterface(IContentProvider.descriptor);
String callingPkg = data.readString();
Uri url = Uri.CREATOR.createFromParcel(data);
int num = data.readInt();
String[] projection = null;
if (num > 0) {
projection = new String[num];
for (int i = 0; i < num; i++) {
projection[i] = data.readString();
}
}
String selection = data.readString();
num = data.readInt();
String[] selectionArgs = null;
if (num > 0) {
selectionArgs = new String[num];
for (int i = 0; i < num; i++) {
selectionArgs[i] = data.readString();
}
}
String sortOrder = data.readString();
IContentObserver observer = IContentObserver.Stub.asInterface(
data.readStrongBinder());
ICancellationSignal cancellationSignal = ICancellationSignal.Stub.asInterface(
data.readStrongBinder());
//調(diào)用服務(wù)端實現(xiàn)的query方法
Cursor cursor = query(callingPkg, url, projection, selection, selectionArgs,
sortOrder, cancellationSignal);
if (cursor != null) {
CursorToBulkCursorAdaptor adaptor = null;
try {
//創(chuàng)建CursorToBulkCursorAdaptor對象
adaptor = new CursorToBulkCursorAdaptor(cursor, observer,
getProviderName());
cursor = null;
BulkCursorDescriptor d = adaptor.getBulkCursorDescriptor();
adaptor = null;
reply.writeNoException();
reply.writeInt(1);
d.writeToParcel(reply, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
} finally {
if (adaptor != null) {
adaptor.close();
}
if (cursor != null) {
cursor.close();
}
}
} else {
reply.writeNoException();
reply.writeInt(0);
}
return true;
}
...
}
}