aidl 流程
为了方便理解,先将binder看做是一个黑盒子 aidl的流程图如下
 
 demo连接添加链接描述
Androidstudio 会帮我们生成emotionAidlService,具体目录在n\build\generated\aidl_source_output_dir\debug\out\com\example\emotion\emotionAidlService.java
emotionAidlService.java 代码讲解:
其中核心代码:
stub内部类里面有两个关键函数:
1、asInterface
    {
      if ((obj==null)) {
        return null;
      }
      android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
      if (((iin!=null)&&(iin instanceof com.example.emotion.emotionAidlService))) {
        return ((com.example.emotion.emotionAidlService)iin);
      }
      return new com.example.emotion.emotionAidlService.Stub.Proxy(obj);   //核心代码1
    }
该核心代码就是创建一个Proxy对象,同时将IBinder对象的obj传递给Proxy
 2,onTransact()
@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_RobotLookUp:
        {
          data.enforceInterface(descriptor);
          int _arg0;
          _arg0 = data.readInt();
          int _arg1;
          _arg1 = data.readInt();
          this.RobotLookUp(_arg0, _arg1);    //核心代码2
          reply.writeNoException();
          return true;
        }
        case TRANSACTION_RobotWarning:
        {
          data.enforceInterface(descriptor);
          this.RobotWarning();
          reply.writeNoException();
          return true;
        }
        default:
        {
          return super.onTransact(code, data, reply, flags);
        }
      }
    }
onTransact函数功能主要是接收来自binder底层的调用,通过binder底层onTransact函数,将函数执行到核心代码2中
Prox类里面的关键函数 RobotLookUp
   @Override public void RobotLookUp(int y, int p) 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.writeInt(y);
          _data.writeInt(p);
          boolean _status = mRemote.transact(Stub.TRANSACTION_RobotLookUp, _data, _reply, 0);  //核心代码
          if (!_status && getDefaultImpl() != null) {
            getDefaultImpl().RobotLookUp(y, p);
            return;
          }
          _reply.readException();
        }
        finally {
          _reply.recycle();
          _data.recycle();
        }
      }
这个函数是和aidl文件里面定义的函数名字是一样的,后面进行跨进程通信会引用到则个函数,这个的功能是创建一个parcel数据_data
 ,为什么必须是Parcel数据了,因为Android跨进程传递的数据必须序列化,而序列化所采用的方式就是parcel。parcel序列化,主要实现
 是在native层,而binder 通信主要的部分是在nativee层。另外,如果跨进程的调用RobotLookUp有返回值,那么这个返回值将以_replay来存储和传递
emotionAidlService的类结构图:

总结
binder基于AIDL的通信流程图如下:
 Client端:MainActivity;
 Server端:Service;
 Service的对外aidl接口如上面的案例所示,
 MainActivity已经通过BindService拿到了Service的IBinder对象。
 
 aidl通信的基本步骤如下:
- Client通过ServiceConnection获取到Server的Binder,并且封装成一个Proxy。
- 通过Proxy来同步调用IPC方法(testFunction),同时通过Parcel将参数传给Binder,最终触发Binder的
 transact方法。
- Binder的transact方法最终会触发到Server上Stub的onTransact方法。
- Server上Stub的onTransact方法中,会先从Parcel中解析中参数,然后将参数带入真正的方法中执行,然后将
 结果写入Parcel后传回。
- 请注意:Client的Ipc方法中,执行Binder的transact时,是阻塞等待的,一直到Server逻辑执行结束后才会继
 续执行。当然,如果IPC方法是oneWay的方式,那么就是非阻塞的等待。
- 当Server返回结果后,Client从Parcel中取出返回值,于是实现了一次IPC调用。
Aidl是同步调用还是异步调用?
经过上述分析:aidl的的调用过程是同步调用的。
 当我们需要服务端做耗时操作时,肯定是不能使用同步调用的,否则轻者影响用户体验,重者直接 ANR 或者应用崩溃。那么如何使 AIDL 的调用过程是异步的呢?
 只需要把调用放到非 UI 线程即可,如果要对调用的返回做 UI 更新的话,再通过 Handler 处理即可。或者通过回调去更新UI
AIDL通信出现DeadObjectException解决方法
1、这个方案比较简单粗暴,就是在多有调用跨进程接口的地方,都加一个Binder是否存活的判断。
   mEmotionAidlService.asBinder().isBinderAlive();
2、监听Binder死亡通知
 先初始化一个DeathRecipient,用来监听死亡通知
   IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() {
        @Override
        public void binderDied() {
            // 解绑当前监听,重新启动服务
            mEmotionAidlService.asBinder().unlinkToDeath(mDeathRecipient, 0);
            if (mEmotionAidlService != null){
               bindService(intent, serviceConnection, BIND_AUTO_CREATE);
            }
        }
    };```
在onServiceConnected方法中,注册死亡监听:
```go
 serviceConnection=new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                Log.i(TAG,"onServiceConnected");
                 mEmotionAidlService =  emotionAidlService.Stub.asInterface(service);
//                mEmotionAidlService.asBinder().isBinderAlive();
                if(mEmotionAidlService != null){
                    try {
                        mEmotionAidlService.asBinder().linkToDeath(mDeathRecipient,0);
                    } catch (RemoteException e) {
                        throw new RuntimeException(e);
                    }  
                }
            }
            @Override
            public void onServiceDisconnected(ComponentName name) {
                Log.i(TAG,"onServiceDisconnected");
                mEmotionAidlService=null;
            }
        };
















![[Android JNI] --- JNIEnv和JavaVM](https://img-blog.csdnimg.cn/cf330806f65e44e682c2a95e1be8e599.png)


