Binder的使用方法和源码解析

版权声明:允许转载,只要标注转载地址即可 https://blog.csdn.net/z979451341/article/details/68941459

1.BInder驱动机制说明

首先Binder是用于进程间通讯,这个我们都知道,但是它是基于Binder驱动来完成进程间通讯的。Binder驱动是一个驱动程序,而这个驱动程序存在于Linux内核层,Linux内核层又可以说是操作系统层,是进程的管理者。

一个进程A要调用进程B的一个方法,这个进程A就需要获取进程B的Binder代理对象,这个BInder代理对象就是进程B的BInder本地对象。当然这个Binder本地对象需要我们在进程B去实现在Service里面,实现的同时还要实现进程A想要调用方法。而在进程A里也要实现Binder代理对象。 进程A调用Binder代理对象时会通知Binder驱动,Binder驱动又会去调用进程B实现的Binder本地对象到实现的方法。

这里要注意为何BInder驱动能够知道进程A和进程B的所在,首先进程也可以看做内存里的一个地址,然后无论是BInder代理对象和Binder本地对象都会实现IBinder接口,都会在ServiceManager里注册地址通过所在的Service的名字(比如:Action)注册的,这样一来双方通过像是访问Service就可以访问对方的IBinder实现类。首先要注意无论是注册还是传递数据、回调数据都是通过Binder驱动实现,具体Binder驱动如何实现我们不需要知道,我们所能做的就是实现BInder本地对象和Binder代理对象。

2.BInder的使用方法

Server端负责实现Binder本地对象,Client负责实现Binder代理对象,实现Client端要调用Server完成两个不同计算函数。这里既然要调用两个函数,我们就要教两者学会如何分辨,就像使用handler一样,通过数字来分辨,毕竟占用字节少。

mPlusBinder.transact(0x110, _data, _reply, 0);

因为调用函数会有返回值,所以我们在使用Binder代理对象调用函数时需要首先传输数据过去,然后在接收数据。

                _data.writeInterfaceToken("CalcPlusService");
                _data.writeInt(36);
                _data.writeInt(12);
                mPlusBinder.transact(0x111, _data, _reply, 0);
                _reply.readException();
                _result = _reply.readInt();

同时Server端需要首先接收函数,进过计算再返回值

                    data.enforceInterface(DESCRIPTOR);
                    int _arg0;
                    _arg0 = data.readInt();
                    int _arg1;
                    _arg1 = data.readInt();
                    int _result = _arg0 * _arg1;
                    reply.writeNoException();
                    reply.writeInt(_result);

完整实例代码如下

BinderServer的代码

public class CalcPlusService extends Service
{
    private static final String DESCRIPTOR = "CalcPlusService";
    private static final String TAG = "CalcPlusService";

    public void onCreate()
    {
        Log.e(TAG, "onCreate");
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId)
    {
        Log.e(TAG, "onStartCommand");
        return super.onStartCommand(intent, flags, startId);
    }

    public IBinder onBind(Intent t)
    {
        Log.e(TAG, "onBind");
        return mBinder;
    }

    public void onDestroy()
    {
        Log.e(TAG, "onDestroy");
        super.onDestroy();
    }

    public boolean onUnbind(Intent intent)
    {
        Log.e(TAG, "onUnbind");
        return super.onUnbind(intent);
    }

    public void onRebind(Intent intent)
    {
        Log.e(TAG, "onRebind");
        super.onRebind(intent);
    }

    private MyBinder mBinder = new MyBinder();

    private class MyBinder extends Binder
    {
        @Override
        protected boolean onTransact(int code, Parcel data, Parcel reply,
                                     int flags) throws RemoteException
        {
            switch (code)
            {
                case 0x110:
                {
                    data.enforceInterface(DESCRIPTOR);
                    int _arg0;
                    _arg0 = data.readInt();
                    int _arg1;
                    _arg1 = data.readInt();
                    int _result = _arg0 * _arg1;
                    reply.writeNoException();
                    reply.writeInt(_result);
                    return true;
                }
                case 0x111:
                {
                    data.enforceInterface(DESCRIPTOR);
                    int _arg0;
                    _arg0 = data.readInt();
                    int _arg1;
                    _arg1 = data.readInt();
                    int _result = _arg0 / _arg1;
                    reply.writeNoException();
                    reply.writeInt(_result);
                    return true;
                }
            }
            return super.onTransact(code, data, reply, flags);
        }

    };

}  


<service android:name="com.example.zhy_binder.CalcPlusService" >
    <intent-filter>
        <action android:name="com.zhy.aidl.calcplus" />
        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</service>

BinderClient

public class MainActivity extends Activity
{

    private IBinder mPlusBinder;
    private ServiceConnection mServiceConnPlus = new ServiceConnection()
    {
        @Override
        public void onServiceDisconnected(ComponentName name)
        {
            Log.e("client", "mServiceConnPlus onServiceDisconnected");
        }

        @Override
        public void onServiceConnected(ComponentName name, IBinder service)
        {

            Log.e("client", " mServiceConnPlus onServiceConnected");
            mPlusBinder = service;
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

    }

    public void bindService(View view)
    {
        Intent intentPlus = new Intent();
        intentPlus.setAction("com.zhy.aidl.calcplus");
        boolean plus = bindService(intentPlus, mServiceConnPlus,
                Context.BIND_AUTO_CREATE);
        Log.e("plus", plus + "");
    }

    public void unbindService(View view)
    {
        unbindService(mServiceConnPlus);
    }

    public void mulInvoked(View view)
    {

        if (mPlusBinder == null)
        {
            Toast.makeText(this, "未连接服务端或服务端被异常杀死", Toast.LENGTH_SHORT).show();
        } else
        {
            android.os.Parcel _data = android.os.Parcel.obtain();
            android.os.Parcel _reply = android.os.Parcel.obtain();
            int _result;
            try
            {
                _data.writeInterfaceToken("CalcPlusService");
                _data.writeInt(50);
                _data.writeInt(12);
                mPlusBinder.transact(0x110, _data, _reply, 0);
                _reply.readException();
                _result = _reply.readInt();
                Toast.makeText(this, _result + "", Toast.LENGTH_SHORT).show();

            } catch (RemoteException e)
            {
                e.printStackTrace();
            } finally
            {
                _reply.recycle();
                _data.recycle();
            }
        }

    }

    public void divInvoked(View view)
    {

        if (mPlusBinder == null)
        {
            Toast.makeText(this, "未连接服务端或服务端被异常杀死", Toast.LENGTH_SHORT).show();
        } else
        {
            android.os.Parcel _data = android.os.Parcel.obtain();
            android.os.Parcel _reply = android.os.Parcel.obtain();
            int _result;
            try
            {
                _data.writeInterfaceToken("CalcPlusService");
                _data.writeInt(36);
                _data.writeInt(12);
                mPlusBinder.transact(0x111, _data, _reply, 0);
                _reply.readException();
                _result = _reply.readInt();
                Toast.makeText(this, _result + "", Toast.LENGTH_SHORT).show();

            } catch (RemoteException e)
            {
                e.printStackTrace();
            } finally
            {
                _reply.recycle();
                _data.recycle();
            }
        }

    }
}


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <Button
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:onClick="bindService"
        android:text="BindService" />

    <Button
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:onClick="unbindService"
        android:text="UnbindService" />

    <Button
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:onClick="mulInvoked"
        android:text="50*12" />

    <Button
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:onClick="divInvoked"
        android:text="36/12" />

</LinearLayout>  
阅读更多
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页