Android+Binder机制

本文主要从进程间大致通信原理来讲,能力有限,本着对学术认真负责的态度,如有偏差,欢迎留言纠正。

在讲解Binder前先了解以下知识

(1)IBinder 接口:  实现了该接口表示具有跨进程通信能力。Binder就实现了IBinder。

(2)IInterface:通信的功能,就是AIDL中定义的接口。

(3)ServiceManager 存储服务。

(4)Binder驱动:   是通信的核心,负责进程间Binder的建立,通信,以及进程间数据的传递。

1:Binder是一种进程间通信机制( IPC)。Android系统是Linux内核,Linux 提供的 IPC通信方式有,Socket,管道、消息队列、共享内存。而Socket效率低,管道、消息队列则发送数据到接受数据需要拷贝2次。共享内存比较难以控制。所以采用了Binder。

2:Binder采用采用内存映射机制,在发送数据进程到接受数据进程,数据只需要拷贝一次,及copy_from_user到Binder驱动。

3:内存映射。将server进程内存映射到内核空间,对内核空间server的操作,相当于操作server进程。这样在单次通信,数据只需要从客户端进程将数据拷贝到共享内核空间一次。而server进程对客户端数据操作,则反映在内核空间,操作完数据,则将内核空间将数据拷贝到客户端进程。

下面使用AIDL实现跨进程间的简单通信
1:客户端与服务端需要建立相同的AIDL路径与名称。

interface IMyAidlInterface {
    void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
            double aDouble, String aString);
    int sum(int a,int b);
}

2:AndroidStudio会自动生成IMyAidlInterface.java文件
 

以下是生成的Java代码:
 

public interface IMyAidlInterface extends android.os.IInterface {
    //Stub是IMyAidlInterface内部抽象类
    public static abstract class Stub extends android.os.Binder implements comy.server.IMyAidlInterface {
        private static final java.lang.String DESCRIPTOR = "comy.server.IMyAidlInterface";

        public Stub() {
            this.attachInterface(this, DESCRIPTOR);
        }
        //该方法表示如果是当前进程的Binder,则直接返回当前进程的IMyAidlInterface,否则创建Proxy代理返回
        public static comy.server.IMyAidlInterface asInterface(android.os.IBinder obj) {
            if ((obj == null)) {
                return null;
            }
            android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
            if (((iin != null) && (iin instanceof comy.server.IMyAidlInterface))) {
                return ((comy.server.IMyAidlInterface) iin);
            }
            return new comy.server.IMyAidlInterface.Stub.Proxy(obj);//返回IMyAidlInterface代理
        }
        @Override
        public android.os.IBinder asBinder() {
            return this;
        }

        /**
         * 该方法在客户端调用transact后,会回调该方法
         * @param code  方法标识,对应IMyAidlInterface中的方法
         * @param data
         * @param reply
         * @param flags
         * @return
         * @throws android.os.RemoteException
         */
        @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_basicTypes: {
                    data.enforceInterface(descriptor);
                    int _arg0;
                    _arg0 = data.readInt();
                    long _arg1;
                    _arg1 = data.readLong();
                    boolean _arg2;
                    _arg2 = (0 != data.readInt());
                    float _arg3;
                    _arg3 = data.readFloat();
                    double _arg4;
                    _arg4 = data.readDouble();
                    java.lang.String _arg5;
                    _arg5 = data.readString();
                    this.basicTypes(_arg0, _arg1, _arg2, _arg3, _arg4, _arg5);
                    reply.writeNoException();
                    return true;
                }
                case TRANSACTION_sum: {
                    data.enforceInterface(descriptor);
                    int _arg0;
                    _arg0 = data.readInt();
                    int _arg1;
                    _arg1 = data.readInt();
                    int _result = this.sum(_arg0, _arg1);//调用IMyAidlInterface实现类MyService中的sum方法
                    reply.writeNoException();
                    reply.writeInt(_result);  //将计算接口写到到本地,内存映射到内核空间
                    return true;
                }
                default: {
                    return super.onTransact(code, data, reply, flags);
                }
            }
        }
        //当走到该类,则说明不是当前进程Binder
        private static class Proxy implements comy.server.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;
            }
            @Override
            public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, java.lang.String aString) 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(anInt);
                    _data.writeLong(aLong);
                    _data.writeInt(((aBoolean) ? (1) : (0)));
                    _data.writeFloat(aFloat);
                    _data.writeDouble(aDouble);
                    _data.writeString(aString);
                    mRemote.transact(Stub.TRANSACTION_basicTypes, _data, _reply, 0);
                    _reply.readException();
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
            }
/
            @Override
            public int sum(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);
                    //调用server进程,将数据拷贝到内核空间,此时Binder只是server进程的代理对象。
                    mRemote.transact(Stub.TRANSACTION_sum, _data, _reply, 0);
                    _reply.readException();
                    //读取计算结果,从内核空间拷贝来的数据。
                    _result = _reply.readInt();
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
                //返回结果
                return _result;
            }
        }
        static final int TRANSACTION_basicTypes = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
        static final int TRANSACTION_sum = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
    }
    public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, java.lang.String aString) throws android.os.RemoteException;
    public int sum(int a, int b) throws android.os.RemoteException;
}

3:以下是Client进程代码

public class MainActivity extends AppCompatActivity {
    String action = "comy.server.IMyAidlInterface";
    IMyAidlInterface iMyAidlInterface; 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Intent intent = new Intent(getApplicationContext(), IMyAidlInterface.class);
        intent.setAction(action);
        intent.setComponent(new ComponentName("comy.server", "comy.server.MyService"));
        bindService(intent, conn, BIND_AUTO_CREATE);
    }

 
    private ServiceConnection conn = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            iMyAidlInterface = IMyAidlInterface.Stub.asInterface(iBinder);
            try {
                int data = iMyAidlInterface.sum(5, 6);
                Log.e(":MainActivity:", ":onServiceConnected: = " + data);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        @Override
        public void onServiceDisconnected(ComponentName componentName) {
        }
    };
    @Override
    protected void onDestroy() {
        super.onDestroy();
        unbindService(conn);
    }
}

4:以下是server进程代码

public class MainActivity extends AppCompatActivity {
    String action = "comy.server.IMyAidlInterface";
    Intent intent;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        intent = new Intent(getApplicationContext(), MyService.class);
        intent.setAction(action);
        intent.setComponent(new ComponentName("comy.server", "comy.server.MyService"));
        startService(intent);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        stopService(intent);
    }
}
public class MyService extends Service {
    IMyAidlInterface.Stub binderStub = new IMyAidlInterface.Stub() {
        @Override
        public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {
        }

        @Override
        public int sum(int a, int b) throws RemoteException {
            return a + b;
        }
    };

    @Override
    public IBinder onBind(Intent intent) {
        Log.e(":MyService:",":onBind: [*********]=");
        return binderStub;
    }
}

在AndroidManifest注册MyService

<service
    android:name="comy.server.MyService"
    android:enabled="true"
    android:exported="true">
</service>

此时就可以实现跨进程通信,当客户端调用 iMyAidlInterface.sum(5, 6);时,此时客户端进程被挂起,知道server进程处理结束后才被唤醒,也就是说,使用Binder实现跨进程通信则是进程间同步的。

源码下载

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值