AIDL 的理解&源码分析

本文详细探讨了AIDL(Android Interface Definition Language)在移动端IPC通信中的作用,讲解了对象如何实现Parcelable接口,以及Binder驱动在通信过程中的角色。重点阐述了Proxy作为IPC通讯的代理,asInterface()方法在查找本地接口中的应用,以及在bindService时ServiceConnection的使用。同时,文章提到了ServiceManager如何作为Binder驱动的入口,服务于客户端和服务端之间的通信。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

aidl通讯试所有的对象都得实现Parcelable 接口

onTransact() Binder 驱动执行完毕时需要回调的方法

Proxy 移动端IPC通讯的时候,消息都是通过Binder 进行传递的。
这个代理可以理解为:IPC机制中,Android代码 跟底层对应IPC的Binder驱动 之间进行通讯时的代理

asInterface() 查询本地所有的aidl 接口,判断该Binder对象是否为一个本地的 Binder引用

然后bindService的时候,需要传递一个 ServiceConnection的内部类实现,在ServiceConnection内部类实现中
bindService(intent, conn, BIND_AUTO_CREATE);


    ServiceConnection conn=new ServiceConnection() {    
        //aidl链接失败回调
        @Override
        public void onServiceDisconnected(ComponentName name) {
        }
        //aidl连接成功回调
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            //在系统内部将执行一下逻辑行为
            /*public static com.aidl.lxcay.MyAidlInterface asInterface(android.os.IBinder obj) {
            * if ((obj == null)) {
            *   return null;
            * }
            * 查询本地所有的aidl 的描述,判断该Binder对象是否为一个本地的 Binder引用
            * android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
            * if (((iin != null) && (iin instanceof com.aidl.lxcay.MyAidlInterface))) {
            * 返回定义好的代理接口
            * return ((com.aidl.lxcay.MyAidlInterface) iin);
            * }
            * 返回默认代理
            * return new com.aidl.lxcay.MyAidlInterface.Stub.Proxy(obj);
            * }
            */
            //这个localInterface 就是aidl里面规定好的接口引用,即Binder 引用
            localInterface = Stub.asInterface(service);
            //在客户端可以通过点击事件执行这个引用里对应的函数,如果执行成功,会在相应的Service里面执行相应的 函数;
            //下面给出一个demo
        }
    };
    eg:
    //客户端
    public void click(View v) throws RemoteException{
        Log.i(TAG, localInterface.login("24", 24)+"");

        Log.i(TAG, localInterface.sayHello(new Person("lxcay", 24))+"");
    }
    //服务端
    public class MyServices extends Service {
        @Override
        public IBinder onBind(Intent intent) {

            return new MyBind();
        }
        // class MyBind 继承 Stub接口,为什么会重写一下2个回调方法,是因为在aidl文件对应的java代码里面有这句代码
        /*
         * public static abstract class Stub extends android.os.Binder implements com.aidl.lxcay.MyAidlInterface {}
         * 在我自己定义的接口描述文件里面就有 
         * interface MyAidlInterface {
         *      boolean login(String name,int age);
         *      String sayHello(in Person p);
         * }
         */
        class MyBind extends Stub{

            @Override
            public boolean login(String name, int age) throws RemoteException {

                return !name.equals(age);
            }

            @Override
            public String sayHello(Person p) throws RemoteException {
                return "lxcay hello world, hello aidl~";
            }
        }
    }

然后在客户端跟服务端交互的时候,我们可以通过看 aidl对应系统生成的java类中的描述,来撸清楚来龙去脉

/*
 * This file is auto-generated.  DO NOT MODIFY.
 * Original file: D:\\SCode\\SogouGameSDKSample\\src\\com\\intfs\\MyAidlInterface.aidl
 */
package com.aidl.lxcay;

public interface MyAidlInterface extends android.os.IInterface {
    /** Local-side IPC implementation stub class. */
    public static abstract class Stub extends android.os.Binder implements com.aidl.lxcay.MyAidlInterface {
        private static final java.lang.String DESCRIPTOR = "com.aidl.lxcay.MyAidlInterface";

        /** Construct the stub at attach it to the interface. */
        public Stub() {
            this.attachInterface(this, DESCRIPTOR);
        }

        /**
         * Cast an IBinder object into an com.aidl.lxcay.MyAidlInterface interface,
         * generating a proxy if needed.
         */
        public static com.aidl.lxcay.MyAidlInterface asInterface(android.os.IBinder obj) {
            if ((obj == null)) {
                return null;
            }
            android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
            if (((iin != null) && (iin instanceof com.aidl.lxcay.MyAidlInterface))) {
                return ((com.aidl.lxcay.MyAidlInterface) iin);
            }
            return new com.aidl.lxcay.MyAidlInterface.Stub.Proxy(obj);
        }
        //这个被重写是因为,咱们的com.aidl.lxcay.MyAidlInterface类extends android.os.IInterface 所以需要提供一个 asBinder 对象
        @Override
        public android.os.IBinder asBinder() {
            return this;
        }
        //这个是提供给Binder驱动在接受到消息的时候,回调的方法。里面对应的就是aidl接口描述文件里面的固定格式
        @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_login: {
                data.enforceInterface(DESCRIPTOR);
                java.lang.String _arg0;
                _arg0 = data.readString();
                int _arg1;
                _arg1 = data.readInt();
                //---------------->>
                boolean _result = this.login(_arg0, _arg1);
                reply.writeNoException();
                reply.writeInt(((_result) ? (1) : (0)));
                return true;
            }
            case TRANSACTION_sayHello: {
                data.enforceInterface(DESCRIPTOR);
                com.aidl.lxcay.Person _arg0;
                if ((0 != data.readInt())) {
                    _arg0 = com.aidl.lxcay.Person.CREATOR.createFromParcel(data);
                } else {
                    _arg0 = null;
                }
                ////------------------------>>
                java.lang.String _result = this.sayHello(_arg0);
                reply.writeNoException();
                reply.writeString(_result);
                return true;
            }
            }
            return super.onTransact(code, data, reply, flags);
        }
        //这个代理类,是客户端跟服务端之间的一个桥梁,通过阅读以下代码 ①方法 跟②方法,我们可以大致知道他们之间是怎么通讯的。
        private static class Proxy implements com.aidl.lxcay.MyAidlInterface {
            //mRemote 为 Binder的引用
            private android.os.IBinder mRemote;

            Proxy(android.os.IBinder remote) {
                //在Binder 的驱动中 mRemote 也重载了transact() 函数
                mRemote = remote;
            }

            @Override
            public android.os.IBinder asBinder() {
                return mRemote;
            }

            public java.lang.String getInterfaceDescriptor() {
                return DESCRIPTOR;
            }
            //①方法
            @Override
            public boolean login(java.lang.String name, int age) throws android.os.RemoteException {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                boolean _result;
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    _data.writeString(name);
                    _data.writeInt(age);

                    //在向Binder通讯的时候,执行以下一句代码,驱动执行完毕之后成功,最后会回调 上面的
                    //public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags)方法
                    mRemote.transact(Stub.TRANSACTION_login, _data, _reply, 0);

                    _reply.readException();
                    _result = (0 != _reply.readInt());
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
                return _result;
            }
            //②方法
            @Override
            public java.lang.String sayHello(com.aidl.lxcay.Person p) 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);
                    if ((p != null)) {
                        _data.writeInt(1);
                        p.writeToParcel(_data, 0);
                    } else {
                        _data.writeInt(0);
                    }
                    mRemote.transact(Stub.TRANSACTION_sayHello, _data, _reply, 0);
                    _reply.readException();
                    _result = _reply.readString();
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
                return _result;
            }
        }

        static final int TRANSACTION_login = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
        static final int TRANSACTION_sayHello = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
    }

    public boolean login(java.lang.String name, int age) throws android.os.RemoteException;

    public java.lang.String sayHello(com.aidl.lxcay.Person p) throws android.os.RemoteException;
}

ServiceManager 可以得到android系统的各个 ServiceManger对象,而每一个ServiceManger对象,又持有着各自对应的Binder 引用。
所以说,ServiceManager是Binder 驱动的一个引子,在IPC中 是客户端和服务端进行通信的媒介

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值