aidl通訊試所有的對象都得實現Parcelable 接口
onTransact() Binder 驅動執行完畢時需要回調的方法
Proxy 移動端IPC通訊的時候,消息都是通過Binder 進行傳遞的。
這個代理可以理解爲:IPC機制中,Android代碼 跟底層對應IPC的Binder驅動 之間進行通訊時的代理
asInterface() 查詢本地所有的aidl 接口,判斷該Binder對象是否爲一個本地的 Binder引用
然後bindService的時候,需要傳遞一個 ServiceConnection的內部類實現,在ServiceConnection內部類實現中
bindService(intent, conn, BIND_AUTO_CREATE);
ServiceConnection conn=new ServiceConnection() {
//aidl鏈接失敗回調
@Override
public void onServiceDisconnected(ComponentName name) {
}
//aidl連接成功回調
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//在系統內部將執行一下邏輯行爲
/*public static com.aidl.lxcay.MyAidlInterface asInterface(android.os.IBinder obj) {
* if ((obj == null)) {
* return null;
* }
* 查詢本地所有的aidl 的描述,判斷該Binder對象是否爲一個本地的 Binder引用
* android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
* if (((iin != null) && (iin instanceof com.aidl.lxcay.MyAidlInterface))) {
* 返回定義好的代理接口
* return ((com.aidl.lxcay.MyAidlInterface) iin);
* }
* 返回默認代理
* return new com.aidl.lxcay.MyAidlInterface.Stub.Proxy(obj);
* }
*/
//這個localInterface 就是aidl裏面規定好的接口引用,即Binder 引用
localInterface = Stub.asInterface(service);
//在客戶端可以通過點擊事件執行這個引用裏對應的函數,如果執行成功,會在相應的Service裏面執行相應的 函數;
//下面給出一個demo
}
};
eg:
//客戶端
public void click(View v) throws RemoteException{
Log.i(TAG, localInterface.login("24", 24)+"");
Log.i(TAG, localInterface.sayHello(new Person("lxcay", 24))+"");
}
//服務端
public class MyServices extends Service {
@Override
public IBinder onBind(Intent intent) {
return new MyBind();
}
// class MyBind 繼承 Stub接口,爲什麼會重寫一下2個回調方法,是因爲在aidl文件對應的java代碼裏面有這句代碼
/*
* public static abstract class Stub extends android.os.Binder implements com.aidl.lxcay.MyAidlInterface {}
* 在我自己定義的接口描述文件裏面就有
* interface MyAidlInterface {
* boolean login(String name,int age);
* String sayHello(in Person p);
* }
*/
class MyBind extends Stub{
@Override
public boolean login(String name, int age) throws RemoteException {
return !name.equals(age);
}
@Override
public String sayHello(Person p) throws RemoteException {
return "lxcay hello world, hello aidl~";
}
}
}
然後在客戶端跟服務端交互的時候,我們可以通過看 aidl對應系統生成的java類中的描述,來擼清楚來龍去脈
/*
* This file is auto-generated. DO NOT MODIFY.
* Original file: D:\\SCode\\SogouGameSDKSample\\src\\com\\intfs\\MyAidlInterface.aidl
*/
package com.aidl.lxcay;
public interface MyAidlInterface extends android.os.IInterface {
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements com.aidl.lxcay.MyAidlInterface {
private static final java.lang.String DESCRIPTOR = "com.aidl.lxcay.MyAidlInterface";
/** Construct the stub at attach it to the interface. */
public Stub() {
this.attachInterface(this, DESCRIPTOR);
}
/**
* Cast an IBinder object into an com.aidl.lxcay.MyAidlInterface interface,
* generating a proxy if needed.
*/
public static com.aidl.lxcay.MyAidlInterface asInterface(android.os.IBinder obj) {
if ((obj == null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin != null) && (iin instanceof com.aidl.lxcay.MyAidlInterface))) {
return ((com.aidl.lxcay.MyAidlInterface) iin);
}
return new com.aidl.lxcay.MyAidlInterface.Stub.Proxy(obj);
}
//這個被重寫是因爲,咱們的com.aidl.lxcay.MyAidlInterface類extends android.os.IInterface 所以需要提供一個 asBinder 對象
@Override
public android.os.IBinder asBinder() {
return this;
}
//這個是提供給Binder驅動在接受到消息的時候,回調的方法。裏面對應的就是aidl接口描述文件裏面的固定格式
@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_login: {
data.enforceInterface(DESCRIPTOR);
java.lang.String _arg0;
_arg0 = data.readString();
int _arg1;
_arg1 = data.readInt();
//---------------->>
boolean _result = this.login(_arg0, _arg1);
reply.writeNoException();
reply.writeInt(((_result) ? (1) : (0)));
return true;
}
case TRANSACTION_sayHello: {
data.enforceInterface(DESCRIPTOR);
com.aidl.lxcay.Person _arg0;
if ((0 != data.readInt())) {
_arg0 = com.aidl.lxcay.Person.CREATOR.createFromParcel(data);
} else {
_arg0 = null;
}
////------------------------>>
java.lang.String _result = this.sayHello(_arg0);
reply.writeNoException();
reply.writeString(_result);
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
//這個代理類,是客戶端跟服務端之間的一個橋樑,通過閱讀以下代碼 ①方法 跟②方法,我們可以大致知道他們之間是怎麼通訊的。
private static class Proxy implements com.aidl.lxcay.MyAidlInterface {
//mRemote 爲 Binder的引用
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote) {
//在Binder 的驅動中 mRemote 也重載了transact() 函數
mRemote = remote;
}
@Override
public android.os.IBinder asBinder() {
return mRemote;
}
public java.lang.String getInterfaceDescriptor() {
return DESCRIPTOR;
}
//①方法
@Override
public boolean login(java.lang.String name, int age) throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
boolean _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeString(name);
_data.writeInt(age);
//在向Binder通訊的時候,執行以下一句代碼,驅動執行完畢之後成功,最後會回調 上面的
//public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags)方法
mRemote.transact(Stub.TRANSACTION_login, _data, _reply, 0);
_reply.readException();
_result = (0 != _reply.readInt());
} finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
//②方法
@Override
public java.lang.String sayHello(com.aidl.lxcay.Person p) throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
java.lang.String _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
if ((p != null)) {
_data.writeInt(1);
p.writeToParcel(_data, 0);
} else {
_data.writeInt(0);
}
mRemote.transact(Stub.TRANSACTION_sayHello, _data, _reply, 0);
_reply.readException();
_result = _reply.readString();
} finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
}
static final int TRANSACTION_login = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
static final int TRANSACTION_sayHello = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
}
public boolean login(java.lang.String name, int age) throws android.os.RemoteException;
public java.lang.String sayHello(com.aidl.lxcay.Person p) throws android.os.RemoteException;
}
ServiceManager 可以得到android系統的各個 ServiceManger對象,而每一個ServiceManger對象,又持有着各自對應的Binder 引用。
所以說,ServiceManager是Binder 驅動的一個引子,在IPC中 是客戶端和服務端進行通信的媒介