Binder的底层通信(Java层)

一、客户端调用服务端的方法。

1、客户端绑定服务端Service。

Intent intent = new Intent();
intent.setComponent(
new ComponentName("com.example.servicetest","com.example.servicetest.TestService"));
bindService(intent, conn, Context.BIND_AUTO_CREATE);

2、客户端在绑定服务端的回调方法中直接调用服务端的方法。

ServiceConnection conn = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {

        try {
            Parcel data = Parcel.obtain();
            Parcel reply = Parcel.obtain();
            // 这个校验Token是可选的,建议添加
            data.writeInterfaceToken("com.example.service.test");
            final int ADD = 1;
            int a = 1;
            int b = 2;
            data.writeInt(a);
            data.writeInt(b);
            // 发起Binder事务,调用服务端add方法
            service.transact(ADD, data, reply, 0);

            // 获取服务端是否发生异常
            reply.readException();
            // 获取add方法调用的返回值
            int result = reply.readInt();
            Log.i("MainActivity", "result = " + result);
        } catch (RemoteException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {}
};

3、服务端Service的实现如下:

public class TestService extends Service {

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return new TestBinder();
    }

    class TestBinder extends Binder {
        final static int ADD = 1;
        @Override
        protected boolean onTransact(int code, @NonNull Parcel data, @Nullable Parcel reply, int flags) throws RemoteException {
            switch (code) {
                case ADD:
                    // 校验客户端的Token,如果校验错误会抛异常
                    data.enforceInterface("com.example.service.test");
                    int a = data.readInt();
                    int b = data.readInt();

                    // 调用add方法进行计算
                    int result = add(a, b);
                    // 写入没有异常产生
                    reply.writeNoException();
                    // 写入add方法调用的返回值
                    reply.writeInt(result);
                    return true;
                default:
                    return super.onTransact(code, data, reply, flags);
            }
        }

        public int add(int a, int b) {
            return a + b;
        }
    }
}

4、如果打印"result = 3",则说明客户端调用服务端的方法成功。

二、服务端调用客户端的方法。

假如服务端的add比较耗时(5秒),我们可以采用回调的方式,将计算结果上报。下面是具体实现。

1、客户端添加一个继承Binder的类,用于接收服务端的回调。

class MyBinder extends Binder {
    final static int NOTIFY_RESULT = 10;
    @Override
    protected boolean onTransact(int code, @NonNull Parcel data, @Nullable Parcel reply, int flags) throws RemoteException {
        switch (code) {
            case NOTIFY_RESULT:
                data.readException();
                int result = data.readInt();
                notifyResult(result);
                return true;
            default:
                return super.onTransact(code, data, reply, flags);
        }
    }

    public void notifyResult(int result) {
        Log.i("MainActivity", "result = " + result);
    }
}

2、客户端绑定服务端的回调方法修改如下:

ServiceConnection conn = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {

        try {
            Parcel data = Parcel.obtain();
            Parcel reply = Parcel.obtain();
            // 这个校验Token是可选的,建议添加
            data.writeInterfaceToken("com.example.service.test");
            final int ADD = 1;
            int a = 1;
            int b = 2;
            data.writeInt(a);
            data.writeInt(b);
            // 将客户端用于接收服务端回调的Binder传递过去
            data.writeStrongBinder(new MyBinder());
            // 发起Binder事务
            service.transact(ADD, data, reply, 0);
        } catch (RemoteException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {}
};

3、服务端TestBinder类修改如下:

class TestBinder extends Binder {
    final static int ADD = 1;

    @Override
    protected boolean onTransact(int code, @NonNull Parcel data, @Nullable Parcel reply, int flags) throws RemoteException {
        switch (code) {
            case ADD:
                // 校验客户端的Token,如果校验错误会抛异常
                data.enforceInterface("com.example.service.test");
                int a = data.readInt();
                int b = data.readInt();
                IBinder binder = data.readStrongBinder();

                new Thread(()->{
                    try {
                        final int NOTIFY_RESULT = 10;
                        Parcel _data = Parcel.obtain();
                        Parcel _reply = Parcel.obtain();
                        // 调用add方法
                        int result = add(a, b);
                        _data.writeNoException();
                        _data.writeInt(result);
                        binder.transact(NOTIFY_RESULT, _data, _reply, 0);
                    } catch (RemoteException e) {
                        throw new RuntimeException(e);
                    }
                }).start();
                return true;
            default:
                return super.onTransact(code, data, reply, flags);
        }
    }

    public int add(int a, int b) {
        SystemClock.sleep(5000);
        return a + b;
    }
}

4、如果打印"result = 3",则说明服务端调用客户端的方法成功。

  • 8
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Binder通信原理是Android中一种跨进程通信机制。它通过Binder驱动和Binder服务来实现进程间的通信。具体实现方式可以参考。 在Binder通信原理中,有三个关键的组件:Binder驱动、Binder服务和Binder客户端。Binder驱动是操作系统提供的内核模块,它负责在进程间传递消息。而Binder服务是一个独立的进程,用于管理和提供跨进程通信的能力。Binder客户端则是调用Binder服务的进程。 在通信过程中,首先需要调用binder_open函数打开Binder设备,然后使用mmap函数进行内存映射,将用户空间的内存映射到内核空间。接下来,通过ioctl函数进行实际的通信操作。 Android中的四大组件(Activity、Service、BroadcastReceiver和ContentProvider)的启动原理也与Binder IPC机制有关。其中,ActivityManagerService、PackageManagerService、WindowManagerService、PowerManagerService等服务的调用也与Binder IPC机制有关。 综上所述,Binder通信原理是Android中一种跨进程通信机制,通过Binder驱动和Binder服务来实现进程间的通信。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [Binder通信机制原理解析](https://blog.csdn.net/Awenyini/article/details/78806893)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [Binder通信原理](https://blog.csdn.net/z1804362542/article/details/127959348)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值