首先的说明,本篇博客是从AIDL生产java代码这方面入手说明的,而且使用的是上一篇博客的项目做示范项目,所以我在本篇博客我只会贴出部分关键代码,其他代码请看上一篇博客。

我在com.example.aidlserver路径创建一个AIDL文件

interface IRemote
{
   int multi(int a, int b);

}

然后点击Make Project,以下图片路径找到这个AIDL生成的java代码

java生成的AI图不清晰怎么修改 aidl生成的java文件_Server

生成Java代码内容如下(明明AIDL写的这么少,生成的代码这么多,还都是向左靠齐,但是不要慌,经过我一顿tab整理)

/*
 * This file is auto-generated.  DO NOT MODIFY.
 * Original file: /Users/longzhenhao/Desktop/Server/app/src/main/aidl/com/example/aidlserver/IRemote.aidl
 */
package com.example.aidlserver;
// Declare any non-default types here with import statements

public interface IRemote extends android.os.IInterface
{
/** Local-side IPC implementation stub class. */
    public static abstract class Stub extends android.os.Binder implements com.example.aidlserver.IRemote
    {
       private static final java.lang.String DESCRIPTOR = "com.example.aidlserver.IRemote";
    /** Construct the stub at attach it to the interface. */
       public Stub()
       {
          this.attachInterface(this, DESCRIPTOR);
       }
    /**
     * Cast an IBinder object into an com.example.aidlserver.IRemote interface,
     * generating a proxy if needed.
     */
        public static com.example.aidlserver.IRemote asInterface(android.os.IBinder obj)
        {
            if ((obj==null)) {
                return null;
            }
            android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
            if (((iin!=null)&&(iin instanceof com.example.aidlserver.IRemote))) {
                return ((com.example.aidlserver.IRemote)iin);
            }
            return new com.example.aidlserver.IRemote.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_multi:
            {
                data.enforceInterface(DESCRIPTOR);
                int _arg0;
                _arg0 = data.readInt();
                int _arg1;
                _arg1 = data.readInt();
                int _result = this.multi(_arg0, _arg1);
                reply.writeNoException();
                reply.writeInt(_result);
                return true;
            }
        }
            return super.onTransact(code, data, reply, flags);
        }
        private static class Proxy implements com.example.aidlserver.IRemote
        {
            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 int multi(int a, int b) throws android.os.RemoteException
            {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                int _result;
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    _data.writeInt(a);
                    _data.writeInt(b);
                    mRemote.transact(Stub.TRANSACTION_multi, _data, _reply, 0);
                    _reply.readException();
                    _result = _reply.readInt();
                }
                finally {
                    _reply.recycle();
                    _data.recycle();
                }
                return _result;
            }
        }
        static final int TRANSACTION_multi = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
    }
    public int multi(int a, int b) throws android.os.RemoteException;
}

关于Binder机制,我有过一篇博客说明,这一次重点放在AIDL生成的Java代码规范上

首先IRemote实现了IInterface接口,如果是Server端调用这个Stub函数会得到Binder本地对象,如果是Client端会得到Binder代理对象

private static final java.lang.String DESCRIPTOR = "com.example.aidlserver.IRemote";
/** Construct the stub at attach it to the interface. */
public Stub()
{
this.attachInterface(this, DESCRIPTOR);
}

我们首先说一下IRemote的代码结构,实现了IInterface接口、有一个内部类Stub,这个内部类还有一个内部类Proxy,然后就是multi函数(没有实现,这是在Service里继承实现的)。

然后这个Stub是引入了IRemote接口和继承了BInder类,说白了Stub才是IRemote真正的实现者,

我们需要注意这个Stub构造函数,因为在Server端的Service里我们需要通过这个Stub对象来实现multi函数的功能,他的意思是将Stub对象也就是Binder本地对象与这个字符串绑定了

private static final java.lang.String DESCRIPTOR = "com.example.aidlserver.IRemote";
       public Stub()
       {
          this.attachInterface(this, DESCRIPTOR);
       }

在Client端通过ServiceConnection获取Binder对象,并且使用asInterface获取Binder代理对象(如果实在Server通过这种方式获得的是BInder本地对象),

public static com.example.aidlserver.IRemote asInterface(android.os.IBinder obj)
        {
            if ((obj==null)) {
                return null;
            }
            android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
            if (((iin!=null)&&(iin instanceof com.example.aidlserver.IRemote))) {
                return ((com.example.aidlserver.IRemote)iin);
            }
            return new com.example.aidlserver.IRemote.Stub.Proxy(obj);
        }

然后Client端使用这个Binder代理对象调用multi函数,调用的代码如下

@Override public int multi(int a, int b) throws android.os.RemoteException
            {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                int _result;
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    _data.writeInt(a);
                    _data.writeInt(b);
                    mRemote.transact(Stub.TRANSACTION_multi, _data, _reply, 0);
                    _reply.readException();
                    _result = _reply.readInt();
                }
                finally {
                    _reply.recycle();
                    _data.recycle();
                }
                return _result;
            }

这里要注意mRemote是什么,是Binder本地对象,因为当初创建Proxy对象的时候把Stub对象传过去了

new com.example.aidlserver.IRemote.Stub.Proxy(obj);

这个transact函数对应着onTransact函数,我们在看看Stub的onTransact函数,这里可以看到他调用了multi函数并返回值(注意multi函数在Server端的Service里实现了)

@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_multi:
                {
                    data.enforceInterface(DESCRIPTOR);
                    int _arg0;
                    _arg0 = data.readInt();
                    int _arg1;
                    _arg1 = data.readInt();
                    int _result = this.multi(_arg0, _arg1);
                    reply.writeNoException();
                    reply.writeInt(_result);
                    return true;
                }
            }
            return super.onTransact(code, data, reply, flags);
        }

最后就是要注意在Client端数据的传递和获取数据的返回值的顺序不能改,因为在Server端数据的接收和返回值的传送的顺序是一定的,从代码上可以看得出。

总结:AIDL生成的java代码包含Stub(BInder本地对象)、Proxy(BInder代理对象),Server端的Service实现了AIDL函数的真正功能,并重写onBind函数使其他进程可以获取它实现的Stub对象,在Client端通过ServiceConnection获取的是Proxy对象,而Proxy对象持有Stub对象,所以通过使用Proxy来调用Stub的函数就是使用的代理模式。在Client端数据传递过去,在Server端获取数据经过调用函数返回结果,在Client端获取返回值