Android aidl

509 阅读3分钟

1、什么是aidl

Aidl 全称Android Interface Definition Language,Android接口定义语言,用于定义进程之间通信协议。

2、进程通信

Android中系统提供了很多服务,例如AlarmManager,NotificationManager等,这些服务都在system server进程中,Android中应用有自己的进程,如下图:application所在进获取服务时需要跟system server进程进程通信。

在这里插入图片描述

当应用想要获取AlarmManger服务时可以通过:

val alarmManager=context.getSystemService(ALARM_SERVICE)

如下图,通过context.getSystemService(ALARM_SERVICE)获取alarmManager服务,其实是从system service进程中获取服务,system service 进程中会使用SystemServiceRegistry来注册服务。

在这里插入图片描述

在SystemServiceRegistry中有静态代码块如下会进行service的注册: 在这里插入图片描述

private static <T> void registerService(@NonNull String serviceName,
        @NonNull Class<T> serviceClass, @NonNull ServiceFetcher<T> serviceFetcher) {
    SYSTEM_SERVICE_NAMES.put(serviceClass, serviceName);
    SYSTEM_SERVICE_FETCHERS.put(serviceName, serviceFetcher);
    SYSTEM_SERVICE_CLASS_NAMES.put(serviceName, serviceClass.getSimpleName());
}

3、IPC

ipc全称Inter-Process Communication,进程通信,在Android中使用binder进行ipc通信,application与system server是两个不同的进程,在application中要获取system service 中的manager服务,需要使用binder进行进程通信如下:

在这里插入图片描述

在manager和service中间其实还有添加了一个proxy代理类和stub,这样manager只需要跟proxy交互,具体的通信逻辑交给proxy,在system server中也是提供了一个stub类。

在这里插入图片描述

4、AIDL

由上面可知应用进程和系统进程的通信方法,aidl就是用来定义通信协议的,在下图中框出来部分就属于aidl。

在这里插入图片描述

具体到AlarmManager中如下:

5、AIDL使用

在main目录下创建一个aidl目录,然后在aidl目录下新建一个aidl文件:

在这里插入图片描述

默认文件名为IMyAidlInterface.aidl,在IMyAidlInterface中定义所需要的方法

interface IMyAidlInterface {
        String getMessage();

}

创建完成IMyAidlInterface后,选择rebuild项目,Android studio会在build/generated/aidl_source_output_dir下自动生成IMyAidlInterface的java类

在这里插入图片描述

这个类中生成一个stub类和一个proxy的内部类,如下:

在这里插入图片描述

stub类

public static abstract class Stub extends android.os.Binder implements com.example.aidld.IMyAidlInterface
{
  private static final java.lang.String DESCRIPTOR = "com.example.aidld.IMyAidlInterface";
  /** Construct the stub at attach it to the interface. */
public Stub()
  {
    this.attachInterface(this, DESCRIPTOR);
  }
  /**
* Cast an IBinder object into an com.example.aidld.IMyAidlInterface interface,
* generating a proxy if needed.
*/
public static com.example.aidld.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.aidld.IMyAidlInterface))) {
      return ((com.example.aidld.IMyAidlInterface)iin);
    }
    return new com.example.aidld.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
  {
    java.lang.String descriptor = DESCRIPTOR;
    switch (code)
    {
      case INTERFACE_TRANSACTION:
      {
        reply.writeString(descriptor);
        return true;
      }
      case TRANSACTION_getMessage:
      {
        data.enforceInterface(descriptor);
        java.lang.String _result = this.getMessage();
        reply.writeNoException();
        reply.writeString(_result);
        return true;
      }
      default:
      {
        return super.onTransact(code, data, reply, flags);
      }
    }
  }

proxy类

private static class Proxy implements com.example.aidld.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;
  }
  /**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/ //    void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
  //            double aDouble, String aString);

  @Override public java.lang.String getMessage() 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);
      boolean _status = mRemote.transact(Stub.TRANSACTION_getMessage, _data, _reply, 0);
      if (!_status && getDefaultImpl() != null) {
        return getDefaultImpl().getMessage();
      }
      _reply.readException();
      _result = _reply.readString();
    }
    finally {
      _reply.recycle();
      _data.recycle();
    }
    return _result;
  }
  public static com.example.aidld.IMyAidlInterface sDefaultImpl;
}

创建stub实现类

public class MyImplementor extends IMyAidlInterface.Stub {
    @Override
    public String getMessage() {
        return "hello world this good";
    }

}

创建BoundService

class BoundService : Service() {
    private val TAG: String = "BoundService"
    private var binder: Binder = MyImplementor()
    override fun onBind(intent: Intent?): IBinder {
        return binder
    }
   }

在activity中获取service的binder数据

private var aidlInterface: IMyAidlInterface? = null
private fun createConnect() {
    connect = object : ServiceConnection {
        override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
            //connect
            aidlInterface = IMyAidlInterface.Stub.asInterface(service)
            Log.d(TAG, "onServiceConnected ${aidlInterface?.message}")
            slogin.text = aidlInterface?.message

}

        override fun onServiceDisconnected(name: ComponentName?) {
            //disconnect
            Log.d(TAG, "onServiceDisconnected")
            aidlInterface = null

        }
    }
}

由上可以看到IBinder转换调用了 IMyAidlInterface.Stub.asInterface(service)其中Stub的asInterface调用了Proxy的方法如下:

public static com.example.aidld.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.aidld.IMyAidlInterface))) {
    return ((com.example.aidld.IMyAidlInterface)iin);
  }
  return new com.example.aidld.IMyAidlInterface.Stub.Proxy(obj);
}

参考

1、developer.android.com/guide/compo…