AIDL是Android中IPC方式中的一種。
AIDL的使用
創(chuàng)建aidl后綴的文件赂弓,服務(wù)端和客戶端各保存一份探越,包名路徑必須一致
interface IMyAidlInterface {
void getName();
}
創(chuàng)建遠(yuǎn)端服務(wù)
public class RemoteService extends Service {
@Override
public IBinder onBind(Intent intent) {
return new ServiceBinder();
}
private class ServiceBinder extends IMyAidlInterface.Stub {
@Override
public void getName() {
Log.i("RemoteService", "getName");
}
}
}
客戶端綁定服務(wù)
public class MainActivity extends AppCompatActivity {
private IMyAidlInterface myAidlInterface;
ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
myAidlInterface = IMyAidlInterface.Stub.asInterface(service);
myAidlInterface.getName();
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent serviceIntent = new Intent("com.example.application.RemoteService");
bindService(serviceIntent, connection, Context.BIND_AUTO_CREATE);
}
}
AIDL生成的文件
aidl的后綴文件是Android studio的簡化處理,IMyAidlInterface具體實(shí)現(xiàn)
public interface IMyAidlInterface extends android.os.IInterface
{
public static abstract class Stub extends android.os.Binder implements com.example.application.IMyAidlInterface
{
private static final java.lang.String DESCRIPTOR = "com.example.application.IMyAidlInterface";
public Stub()
{
this.attachInterface(this, DESCRIPTOR);
}
public static com.example.application.IMyAidlInterface asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof com.example.application.IMyAidlInterface))) {
return ((com.example.application.IMyAidlInterface)iin);
}
return new com.example.application.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_getName:
{
data.enforceInterface(DESCRIPTOR);
this.getName();
reply.writeNoException();
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
private static class Proxy implements com.example.application.IMyAidlInterface
{
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 getName() throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
mRemote.transact(Stub.TRANSACTION_getName, _data, _reply, 0);
_reply.readException();
}
finally {
_reply.recycle();
_data.recycle();
}
}
}
static final int TRANSACTION_getName = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
}
public void getName() throws android.os.RemoteException;
}
- IMyAidlInterface繼承android.os.IInterface钞它,包含了一個(gè)靜態(tài)內(nèi)部類Stub拜银。
- Stub繼承了android.os.Binder實(shí)現(xiàn)IMyAidlInterface接口殊鞭。
Stub是本地服務(wù)的抽象類遭垛。 - Proxy同樣實(shí)現(xiàn)了接口IMyAidlInterface,是Stub的靜態(tài)內(nèi)部類
Proxy是遠(yuǎn)端服務(wù)在本地的代理
Stub-proxy的工作流程
- RemoteService中的IBinder對(duì)象是Stub的具體實(shí)現(xiàn)操灿,在RemoteService被綁定的時(shí)候返回(onServiceConnected)
- 客戶端會(huì)調(diào)用Stub中的靜態(tài)方法Stub.asInterface(IBinder)锯仪,拿到遠(yuǎn)端服務(wù)接口IMyAidlInterface
- 在asInterface方法中首先會(huì)判斷Binder是否處在當(dāng)前進(jìn)程,如果是不同進(jìn)程構(gòu)造Proxy返回趾盐,否則返回Stub庶喜。構(gòu)造Proxy時(shí),把mServiceBinder賦值給mRemote救鲤,Proxy中實(shí)現(xiàn)的接口getName會(huì)調(diào)用mRemote的transact方法久窟,而Binder的通信是靠transact和onTransact實(shí)現(xiàn)的,最后會(huì)走到Stub的onTransact本缠,完成對(duì)mServiceBinder的調(diào)用
aidl通信體現(xiàn)著代理模式的設(shè)計(jì)思想斥扛,RemoteService具體實(shí)現(xiàn)了Stub,Proxy是Stub在本地的代理對(duì)象丹锹,Proxy與Stub依靠transact和onTransact通信稀颁,Proxy與Stub的封裝設(shè)計(jì)最終很方便地完成了本地與服務(wù)跨進(jìn)程通信
判斷是否是同個(gè)進(jìn)程
通過Stub.asInterface(iBinder) 判斷Binder是否處在當(dāng)前進(jìn)程
- DESCRIPTOR是當(dāng)前類接口描述符,為類的全路徑楣黍,這也是我們?cè)谑褂胊idl 的時(shí)候服務(wù)端和客戶端必須要保證相同路徑下的原因匾灶,因?yàn)樗槐4嫦聛碜鳛閰?shù)用于比對(duì)當(dāng)前類是否是本地類還是遠(yuǎn)程。
- 我們調(diào)用IMyAidlInterface.Stub.asInterface 來獲取一個(gè) IMyAidlInterface 類型的類租漂,這個(gè)Stub 是客戶端本地的Stub
- 之后會(huì)調(diào)用queryLocalInterface 通過 DESCRIPTOR 獲取接口對(duì)象阶女,這個(gè)方法是用來查詢本地接口的颊糜,有說明是同個(gè)進(jìn)程則直接返回,沒有就返回null秃踩。這個(gè)obj 是binder 代理芭析,因?yàn)槲覀兊姆?wù)在遠(yuǎn)程所以其類型是一個(gè)BinderProxy ,調(diào)用的是BinderProxy 的 queryLocalInterface
public static abstract class Stub extends android.os.Binder implements com.example.application.IMyAidlInterface
{
private static final java.lang.String DESCRIPTOR = "com.example.application.IMyAidlInterface";
public static com.example.application.IMyAidlInterface asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof com.example.application.IMyAidlInterface))) {
return ((com.example.application.IMyAidlInterface)iin);
}
return new com.example.application.IMyAidlInterface.Stub.Proxy(obj);
}
queryLocalInterface返回null吞瞪,也就是asInterface 中iin為null 所以返回了一個(gè)IMyAidlInterface.Stub.Proxy(obj) 馁启,也就是 IMyAidlInterface 的代理對(duì)象,我們可以通過這個(gè)代理接口調(diào)用遠(yuǎn)程服務(wù)
public final class BinderProxy implements IBinder {
public @Nullable IInterface queryLocalInterface( String descriptor) {
return null;
}
}
如果是一個(gè)本地Binder芍秆,執(zhí)行的是Binder 中的queryLocalInterface 方法
這里mDescriptor 就是上邊說的本地Binder 初始化時(shí)保存的接口描述符惯疙,這里兩個(gè)進(jìn)行對(duì)比,如果一樣妖啥,就返回本地接口對(duì)象
然后返回本地久接口實(shí)例霉颠,這樣就不走binder跨進(jìn)程通信 ,走本地通信就可以了。
public class Binder implements IBinder {
public @Nullable IInterface queryLocalInterface(@NonNull String descriptor) {
if (mDescriptor != null && mDescriptor.equals(descriptor)) {
return mOwner;
}
return null;
}
}