Binder的使用方法和源码解析

标签: 通信 server
907人阅读 评论(0) 收藏 举报
分类:

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>  
查看评论

Binder机制-简单用法(一)

Binder算是android里面比较难懂的部分了,但是非常重要,基本上,当我们深入到进程交互的阶段,Binder都是一个绕不开的槛,所以我也希望帮助大家更浅显地了解到这个知识点。笔者想通过3篇博文简...
  • cjh94520
  • cjh94520
  • 2017-05-07 22:10:13
  • 486

Android使用binder访问service的方式(一)

binder机制是贯穿整个android系统的进程间访问机制,经常被用来访问service,我们结合代码看一下binder在访问service的情形下是怎么具体使用的。 service 你可...
  • xinfuqizao
  • xinfuqizao
  • 2012-07-13 09:39:15
  • 37107

Binder详解

最近在阅读源码时屡屡被Binder给绕进去了,感觉这玩意好像特别的重要,所以就单独的抽出来仔细的研究下,本文主要是从java层面来分析,对于底层内核的Binder驱动就不做深入探讨了,由于本文是以AI...
  • u012481172
  • u012481172
  • 2016-04-26 16:59:43
  • 3037

Binder简单实例

Binder通信是Android用的比较多的一种通信机制,它是一种client-server的通信结构。Binder通信具有以下特点:1、用驱动程序来推进进程间的通信;2、可以通过共享内存的方式来提供...
  • bsxiaomage
  • bsxiaomage
  • 2016-05-31 19:57:00
  • 2678

Android IPC机制(三):浅谈Binder的使用

从源码角度分析AIDL的工作原理
  • a553181867
  • a553181867
  • 2016-04-11 20:19:54
  • 2574

Binder使用示例

BInder方面的资料虽然感觉看的比较多,但是真正用的时候才发现有很多地方模棱两棵的,所以,打算用一个实例再来巩固一下binder的使用方法 首先看下目录结构: leaves@leaves-d...
  • new_abc
  • new_abc
  • 2012-10-22 14:02:28
  • 8069

如何在Android下使用Binder

1概述 Binder是基于OpenBinder,在Android系统上使用的进程间通信机制。 Binder基于Client-Server通信模式,本质上可以理解为它实现了Client对Se...
  • yueliangniao1
  • yueliangniao1
  • 2012-01-09 21:44:33
  • 7853

对Binder的浅显分析及AIDL的使用

IInterface接口是所有涉及到Binder接口的基类,通常情况下,当我们定义一个继承了Binder类的子类的时候,该子类一定要实现一个继承了IInterface接口的接口(有的时候也可以直接用子...
  • qq_25722767
  • qq_25722767
  • 2016-07-13 17:11:25
  • 2715

Binder的使用

Binder的使用标签(空格分隔): Android开发Binder实现了IBinder接口,通常我们不会直接去实现Binder,而是通过aidl工具来定义接口,自动生成相应的Binder的子类。从A...
  • zxc637841323
  • zxc637841323
  • 2017-05-09 22:00:22
  • 145

Binder源码解析(从客户端到服务端代码流程)

Binder 解析首先从一个例子开始 服务端代码:public class WeatherService extends Service{ IWeatherInterface.Stub stu...
  • u011291205
  • u011291205
  • 2017-05-01 22:16:08
  • 4085
    个人资料
    专栏达人 持之以恒
    等级:
    访问量: 12万+
    积分: 3313
    排名: 1万+
    博客专栏
    最新评论