Android AIDL 初步探索

        在Android 应用开发过程中涉及到进程间通信的场景不多,但是随着进程化开发的实现,单APP多进程的情况也越来越多。这就涉及到IPC进程间通信,而Binder 就是其中的一种,Android中很多情况 IPC 通信都是通过 Binder 实现的,其底层相对复杂,在应用层,我们可以理解Binder 就是一个Java 类,在进程间通信的 client -> service 结构中数据的传递是通过Binder 来实现的。而Android 为了方便我们实现这一功能 提供了AIDL 文件   Android Interface Definition Language(安卓接口定义语言)

       要实现进程间通信我们需要创建 service 端和 client 端

1.创建AIDL 文件 

// IServiceInterface.aidl
package com.fyh.aidl;

// Declare any non-default types here with import statements

interface IServiceInterface {
    /**
     * 这边默认生成的一个方法 可以不用管,这里写个getData() 方法获取数据
     */
   String getData();
}

当创建好AIDL文件 编译后,会自动生成一个 对应名称的Java 接口类 

public interface IServiceInterface extends android.os.IInterface

2.创建 service 

public class AIDLService extends Service {
    public AIDLService() {
    }

    
    @Override
    
    public IBinder onBind(Intent intent) {
        return stub;
    }
    
    //这里 Stub 是一个继承 IBinder 的抽象类,所以 IServiceInterface.Stub 是我们对 IBinder
    //的具体实现,而我们实现的方法就是服务端提供一个方法传递数据"{'data':'AIDLServiceTest'}
    IServiceInterface.Stub stub = new IServiceInterface.Stub() {
        @Override
        public String getData() throws RemoteException {

            String s = "{'data':'AIDLServiceTest'}";
            return s;
        }
    };
}

3.创建 client 端

 //创建service 链接 
 private ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            iServiceInterface = IServiceInterface.Stub.asInterface(service);
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            iServiceInterface = null;
        }
    };
    //绑定
    public void bindService(Context context) {
        Intent intent = new Intent();
        intent.setAction("com.fyh.aidl");
        intent.setPackage("com.fyh.aidl.service");
        context.bindService(intent, connection, Context.BIND_AUTO_CREATE);
    }
    //解绑

    public void unbindService(Context context) {
        if (null == iServiceInterface) {
            return;
        }
        context.unbindService(connection);
        iServiceInterface = null;
    }
    //请求服务端数据
    public String requestData() {
        if (null == iServiceInterface) {
            return null;
        }
        try {
            String data = iServiceInterface.getData();
            return data;
        } catch (RemoteException e) {
            e.printStackTrace();
        }
        return null;
    }

输出的结果 

 通过使用 AIDL 我们会非常方便的实现进程间的通讯 同时我们可以看看自动生成的 IServiceInterface.java 文件是什么样的结构。

package com.fyh.aidl;


public interface IServiceInterface extends android.os.IInterface{
  
  public static class Default implements com.fyh.aidl.IServiceInterface{
    
    @Override 
    public java.lang.String getData() throws android.os.RemoteException{
      return null;
    }
    @Override
    public android.os.IBinder asBinder() {
      return null;
    }
  }
  
  public static abstract class Stub extends android.os.Binder implements com.fyh.aidl.IServiceInterface{

    private static final java.lang.String DESCRIPTOR = "com.fyh.aidl.IServiceInterface";

    
    public Stub(){
      this.attachInterface(this, DESCRIPTOR);
    }
    
    public static com.fyh.aidl.IServiceInterface asInterface(android.os.IBinder obj){
      if ((obj==null)) {
        return null;
      }
      android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
      if (((iin!=null)&&(iin instanceof com.fyh.aidl.IServiceInterface))) {
        return ((com.fyh.aidl.IServiceInterface)iin);
      }
      return new com.fyh.aidl.IServiceInterface.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_getData:
        {
          data.enforceInterface(descriptor);
          java.lang.String _result = this.getData();
          reply.writeNoException();
          reply.writeString(_result);
          return true;
        }
        default:
        {
          return super.onTransact(code, data, reply, flags);
        }
      }
    }
    private static class Proxy implements com.fyh.aidl.IServiceInterface
    {
      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 java.lang.String getData() 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_getData, _data, _reply, 0);
          if (!_status && getDefaultImpl() != null) {
            return getDefaultImpl().getData();
          }
          _reply.readException();
          _result = _reply.readString();
        }
        finally {
          _reply.recycle();
          _data.recycle();
        }
        return _result;
      }
      public static com.fyh.aidl.IServiceInterface sDefaultImpl;
    }
    static final int TRANSACTION_getData = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
    public static boolean setDefaultImpl(com.fyh.aidl.IServiceInterface impl) {
      if (Stub.Proxy.sDefaultImpl == null && impl != null) {
        Stub.Proxy.sDefaultImpl = impl;
        return true;
      }
      return false;
    }
    public static com.fyh.aidl.IServiceInterface getDefaultImpl() {
      return Stub.Proxy.sDefaultImpl;
    }
  }
  /**
       * Demonstrates some basic types that you can use as parameters
       * and return values in AIDL.
       */
  public java.lang.String getData() throws android.os.RemoteException;
}

在这个类中 实现了 com.fyh.aidl.IServiceInterface 接口的 情况有三种  Default   Stub   Proxy 。当default 的时候 返回的是null。

我们在 service 中实现的 是IServiceInterface.Stub stub = new IServiceInterface.Stub() 。从代码中我们可以看出 Stub 是一个继承了IBinder 实现了IServiceInterface 的抽象静态内部类,而具体的实现实在  AIDLService 中进行的。而这个 具体 的IBinder 时间对象 stub 会在客户端绑定的时候返回给客户端 。客户端会调用Stub中的静态方法asInterface,stub作为参数,最后拿到IServiceInterface接口对象 iServiceInterface 。

然后 if (((iin!=null)&&(iin instanceof com.fyh.aidl.IServiceInterface))) 判断客户端和服务端是否在同一个进程下,如果在同一进程那么asInterface()将返回Stub对象本身,因为此时根本不需要跨进称通信,那么直接调用Stub对象的接口就可以了。否则返回Stub.Proxy代理对象。该对象持有着远程的Binder引用,因为现在需要跨进程通信。

好了介绍的比较简单,文章主要是AIDL 的简单实现,顺便看看Android 为我们自动生成的类里面是什么样子的。如果要深入了解,还需要等深入的学习。

demo 地址 : https://github.com/fyhsgsgssg/AIDLTest

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章