1.AIDL的簡(jiǎn)介
AIDL (Android Interface Definition Language) 是一種接口定義語言,用于生成可以在Android設(shè)備上兩個(gè)進(jìn)程之間進(jìn)行進(jìn)程間通信(Interprocess Communication, IPC)的代碼。如果在一個(gè)進(jìn)程中(例如Activity)要調(diào)用另一個(gè)進(jìn)程中(例如Service)對(duì)象的操作杰妓,就可以使用AIDL生成可序列化的參數(shù)摆昧,來完成進(jìn)程間通信苫拍。
AIDL能夠?qū)崿F(xiàn)進(jìn)程間通信,其內(nèi)部是通過Binder機(jī)制來實(shí)現(xiàn)的
AIDL支持的數(shù)據(jù)類型:
- Java 編程語言中的所有基本數(shù)據(jù)類型(如 int鳍咱、long、char食呻、boolean 等等)
- String和CharSequence
- Parcelable:實(shí)現(xiàn)了Parcelable接口的對(duì)象
- List:其中的元素需要被AIDL支持流炕,另一端實(shí)際接收的具體類始終是
- ArrayList,但生成的方法使用的是 List 接口
- Map:其中的元素需要被AIDL支持仅胞,包括key和value每辟,另一端實(shí)際接收的具體類始終 是 HashMap,但生成的方法使用的是 Map 接口
其他注意事項(xiàng):
- 在AIDL中傳遞的對(duì)象干旧,必須實(shí)現(xiàn)Parcelable序列化接口渠欺;
- 在AIDL中傳遞的對(duì)象,需要在類文件相同路徑下椎眯,創(chuàng)建同名挠将、但是后綴為.aidl的文件胳岂,并在文件中使用parcelable關(guān)鍵字聲明這個(gè)類;
- 跟普通接口的區(qū)別:只能聲明方法舔稀,不能聲明變量乳丰;
- 所有非基礎(chǔ)數(shù)據(jù)類型參數(shù)都需要標(biāo)出數(shù)據(jù)走向的方向標(biāo)記∧谥可以是 in产园、out 或 inout,基礎(chǔ)數(shù)據(jù)類型默認(rèn)只能是 in夜郁,不能是其他方向什燕。
2.AIDL的使用
下面是項(xiàng)目的目錄結(jié)構(gòu)
image
其中在aidl文件下創(chuàng)建相同的包結(jié)構(gòu),在bean目錄下創(chuàng)建和實(shí)體類一樣的aidl文件,并用 parcelable關(guān)鍵字聲明這個(gè)類
package com.kx.studyview.aidl.bean;
parcelable MessageModel ;
MessageReceiver,用于實(shí)現(xiàn)服務(wù)端傳遞給客戶端消息的監(jiān)聽,類似接口回調(diào)的方式。
package com.kx.studyview.aidl;
import com.kx.studyview.aidl.bean.MessageModel ;
interface MessageReceiver {
void onMessageReceived(in MessageModel receivedMessage);
}
MessageSender,主要用于實(shí)現(xiàn)客戶端與服務(wù)端的交互
// MessageSender.aidl
package com.kx.studyview.aidl;
import com.kx.studyview.aidl.bean.MessageModel ;
import com.kx.studyview.aidl.MessageReceiver ;
interface MessageSender {
void sendMessage(in MessageModel messageModel);
void registerReceiveListener(MessageReceiver messageReceiver);
void unregisterReceiveListener(MessageReceiver messageReceiver);
}
在Build之后,系統(tǒng)會(huì)為我們生成MessageSender.java文件
public interface MessageSender extends android.os.IInterface {
/**
* Local-side IPC implementation stub class.
*/
public static abstract class Stub extends android.os.Binder implements com.kx.studyview.aidl.MessageSender {
// 代表當(dāng)前Binder的唯一標(biāo)識(shí)竞端,一般為完整路徑
private static final java.lang.String DESCRIPTOR = "com.kx.studyview.aidl.MessageSender";
/**
* Construct the stub at attach it to the interface.
*/
public Stub() {
this.attachInterface(this, DESCRIPTOR);
}
將服務(wù)端的Binder對(duì)象轉(zhuǎn)換為客戶端所需要的的AIDL接口類型對(duì)象屎即,如果客戶端和服務(wù)端位于同一進(jìn)
程,則返回服務(wù)端的Stub對(duì)象本身事富,當(dāng)兩者處于不同進(jìn)程時(shí)技俐,返回的是系統(tǒng)封裝后的Stub.proxy對(duì)象
public static com.kx.studyview.aidl.MessageSender asInterface(android.os.IBinder obj) {
if ((obj == null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin != null) && (iin instanceof com.kx.studyview.aidl.MessageSender))) {
return ((com.kx.studyview.aidl.MessageSender) iin);
}
return new com.kx.studyview.aidl.MessageSender.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_sendMessage: {
data.enforceInterface(DESCRIPTOR);
com.kx.studyview.aidl.bean.MessageModel _arg0;
if ((0 != data.readInt())) {
_arg0 = com.kx.studyview.aidl.bean.MessageModel.CREATOR.createFromParcel(data);
} else {
_arg0 = null;
}
this.sendMessage(_arg0);
reply.writeNoException();
return true;
}
case TRANSACTION_registerReceiveListener: {
data.enforceInterface(DESCRIPTOR);
com.kx.studyview.aidl.MessageReceiver _arg0;
_arg0 = com.kx.studyview.aidl.MessageReceiver.Stub.asInterface(data.readStrongBinder());
this.registerReceiveListener(_arg0);
reply.writeNoException();
return true;
}
case TRANSACTION_unregisterReceiveListener: {
data.enforceInterface(DESCRIPTOR);
com.kx.studyview.aidl.MessageReceiver _arg0;
_arg0 = com.kx.studyview.aidl.MessageReceiver.Stub.asInterface(data.readStrongBinder());
this.unregisterReceiveListener(_arg0);
reply.writeNoException();
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
不在一個(gè)進(jìn)程時(shí)返回的代理
private static class Proxy implements com.kx.studyview.aidl.MessageSender {
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 void sendMessage(com.kx.studyview.aidl.bean.MessageModel messageModel) throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
if ((messageModel != null)) {
_data.writeInt(1);
messageModel.writeToParcel(_data, 0);
} else {
_data.writeInt(0);
}
mRemote.transact(Stub.TRANSACTION_sendMessage, _data, _reply, 0);
_reply.readException();
} finally {
_reply.recycle();
_data.recycle();
}
}
@Override
public void registerReceiveListener(com.kx.studyview.aidl.MessageReceiver messageReceiver) throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeStrongBinder((((messageReceiver != null)) ? (messageReceiver.asBinder()) : (null)));
mRemote.transact(Stub.TRANSACTION_registerReceiveListener, _data, _reply, 0);
_reply.readException();
} finally {
_reply.recycle();
_data.recycle();
}
}
@Override
public void unregisterReceiveListener(com.kx.studyview.aidl.MessageReceiver messageReceiver) throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeStrongBinder((((messageReceiver != null)) ? (messageReceiver.asBinder()) : (null)));
mRemote.transact(Stub.TRANSACTION_unregisterReceiveListener, _data, _reply, 0);
_reply.readException();
} finally {
_reply.recycle();
_data.recycle();
}
}
}
用于區(qū)分不同方法名的 code
static final int TRANSACTION_sendMessage = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
static final int TRANSACTION_registerReceiveListener = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
static final int TRANSACTION_unregisterReceiveListener = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2);
}
public void sendMessage(com.kx.studyview.aidl.bean.MessageModel messageModel) throws android.os.RemoteException;
public void registerReceiveListener(com.kx.studyview.aidl.MessageReceiver messageReceiver) throws android.os.RemoteException;
public void unregisterReceiveListener(com.kx.studyview.aidl.MessageReceiver messageReceiver) throws android.os.RemoteException;
}
其中Stub 的 onTransact() 運(yùn)行在服務(wù)端的Binder線程池中,當(dāng)客戶端發(fā)起請(qǐng)求時(shí)赵颅,服務(wù)端根據(jù)code可以確定客戶端所請(qǐng)求的目標(biāo)方法時(shí)什么虽另。
Proxy#sendMessage
@Override
public void sendMessage(com.kx.studyview.aidl.bean.MessageModel messageModel) throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
if ((messageModel != null)) {
_data.writeInt(1);
messageModel.writeToParcel(_data, 0);
} else {
_data.writeInt(0);
}
mRemote.transact(Stub.TRANSACTION_sendMessage, _data, _reply, 0);
_reply.readException();
} finally {
_reply.recycle();
_data.recycle();
}
}
首先創(chuàng)建此方法的所需的輸入型對(duì)象_data 和輸出型對(duì)象_reply,然后將messageModel信息序列化寫入_data中(如果messageModel不為空), _data.writeInt(1)和_data.writeInt(0)用于在Stub 的 onTransact()方法中判斷是否進(jìn)行反序列化饺谬。接著調(diào)用transact方法來發(fā)起RPC(遠(yuǎn)程過程調(diào)用)請(qǐng)求,同時(shí)當(dāng)前線程掛起谣拣。
mRemote.transact(Stub.TRANSACTION_sendMessage, _data, _reply, 0);
然后服務(wù)端的onTransact方法會(huì)被調(diào)用募寨。根據(jù)不同的code區(qū)分不同的方法,
case TRANSACTION_sendMessage: {
data.enforceInterface(DESCRIPTOR);
com.kx.studyview.aidl.bean.MessageModel _arg0;
if ((0 != data.readInt())) {
_arg0 = com.kx.studyview.aidl.bean.MessageModel.CREATOR.createFromParcel(data);
} else {
_arg0 = null;
}
this.sendMessage(_arg0);
reply.writeNoException();
return true;
}
當(dāng) data.writeInt(1)時(shí)森缠,進(jìn)行反序列化操作,生成與客戶端發(fā)送消息內(nèi)容一樣的對(duì)象(不同的對(duì)象拔鹰,內(nèi)容一樣),data.writeInt(0)時(shí)贵涵,返回空列肢,代表客戶端發(fā)送的是null。
_arg0 = com.kx.studyview.aidl.bean.MessageModel.CREATOR.createFromParcel(data);
反序列化完成后宾茂,調(diào)用sendMessage方法瓷马,這個(gè)方法的實(shí)現(xiàn)是在服務(wù)端
this.sendMessage(_arg0);
在定義接口方法時(shí),主要的執(zhí)行過程都是一樣的跨晴,只不過區(qū)別在于定義的方法是否有返回值欧聘,是否有參數(shù)之分。當(dāng)有返回值的時(shí)候端盆,就會(huì)向onTransact參數(shù)中的reply對(duì)象寫入返回值怀骤。有參數(shù)的時(shí)候费封,就會(huì)從data中的取出目標(biāo)所需的參數(shù)。
void sendMessage(in MessageModel messageModel);
void registerReceiveListener(MessageReceiver messageReceiver);
void unregisterReceiveListener(MessageReceiver messageReceiver);
如果onTransact方法返回false蒋伦,則客戶端的請(qǐng)求就會(huì)失敗弓摘,我們可以利用這個(gè)特性來做權(quán)限驗(yàn)證,因?yàn)槲覀円膊幌MS便一個(gè)進(jìn)程都能遠(yuǎn)程調(diào)用我們的服務(wù)痕届。
包名驗(yàn)證
/**
* 包名驗(yàn)證方式
*/
String packageName = null;
String[] packages = getPackageManager().getPackagesForUid(getCallingUid());
if (packages != null && packages.length > 0) {
packageName = packages[0];
}
if (packageName == null || !packageName.startsWith("com.kx.studyview.aidl")) {
LogUtils.e("MessageService 進(jìn)程onTransact " + "拒絕調(diào)用:" + packageName);
return false;
}
權(quán)限驗(yàn)證
// 在AndroidManifest中自定義的權(quán)限
<permission
android:name="com.kx.studyview.aidl.permission.REMOTE_SERVICE_PERMISSION"
android:protectionLevel="normal" />
<uses-permission android:name="com.kx.studyview.aidl.permission.REMOTE_SERVICE_PERMISSION" />
if(checkCallingOrSelfPermission("com.kx.studyview.aidl.permission.REMOTE_SERVICE_PERMISSION") == PackageManager.PERMISSION_DENIED) {
return false;
}