android之binder关于RemoteCallbackList的使用

文章目录

简述

android关于binder的简单通信过程的基础上添加关于RemoteCallbackList的使用,client端对server端进行register与unregister的过程,然后server主动给client端回调处理。

aidl文件修改

1.在IOnTestDataListener.aidl文件中加入register与unregister的方法

java 复制代码
package com.example.test;
import com.example.test.IOnTestDataCallback;
// Declare any non-default types here with import statements

interface IOnTestDataListener {
    void registerCallback(in IOnTestDataCallback callback);
    oneway void sendData(String str, in byte[] bytes,in IOnTestDataCallback callback);
    void unRegisterCallback(in IOnTestDataCallback callback);
}

其中registerCallback与unRegisterCallback是新增的方法。

2.在IOnTestDataCallback.aidl中加入server主动触发远程回调的方法

java 复制代码
// IOnTestDataCallback.aidl
package com.example.test;
import com.example.test.TestDataBean;

// Declare any non-default types here with import statements

interface IOnTestDataCallback {
    void onCallback(in TestDataBean dataBean);
    void onDealRegisterCbData(String name,int number);
}

其中onDealRegisterCbData是新增的方法

服务端

主要实现代码如下所示

java 复制代码
package com.tencent.wemeet.testwhitelist;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.util.Log;

import androidx.annotation.Nullable;

import com.example.test.IOnTestDataCallback;
import com.example.test.IOnTestDataListener;
import com.example.test.TestDataBean;

import java.util.Arrays;

public class TestBinderService extends Service {

    private static final String TAG = "TestBinderService";
    private final RemoteCallbackList<IOnTestDataCallback> remoteCallbackList = new RemoteCallbackList<>();

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return new IOnTestDataListener.Stub() {
            @Override
            public void registerCallback(IOnTestDataCallback callback) throws RemoteException {
                boolean register = remoteCallbackList.register(callback);
                Log.d(TAG, "register:" + register + ",remoteCallbackList :" + remoteCallbackList);
            }

            @Override
            public void sendData(String str, byte[] bytes, IOnTestDataCallback callback) throws RemoteException {
                Log.d(TAG, "str = " + str + ",bytes = " + Arrays.toString(bytes));
                TestDataBean bean = new TestDataBean();
                bean.setName("zhangsan");
                bean.setNumber(20);
                try {
                    Thread.sleep(5000);
                    callback.onCallback(bean);
                    // callback register data
                    int num = remoteCallbackList.beginBroadcast();
                    for (int i = 0; i < num; i++) {
                        IOnTestDataCallback broadcastItem = remoteCallbackList.getBroadcastItem(i);
                        broadcastItem.onDealRegisterCbData("xiaoming", i);
                    }
                    remoteCallbackList.finishBroadcast();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }

            @Override
            public void unRegisterCallback(IOnTestDataCallback callback) throws RemoteException {
                boolean unregister = remoteCallbackList.unregister(callback);
                Log.d(TAG, "unregister:" + unregister + ",remoteCallbackList :" + remoteCallbackList);
            }
        };
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.d(TAG, "onCreate");
    }
}

从上代码可以看出多了registerCallback与unRegisterCallback的方法的实现,同时在sendData中模拟了server端给client端的回调实现方式。代码实现如截图中的红色框所示,其目的是给每个register的client端传递数据。

客户端

主要实现代码如下所示

java 复制代码
package com.example.test;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import android.view.View;

import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;

public class TestBinderActivity extends AppCompatActivity {

    public static final String TAG = "TestBinderActivity";
    private boolean isBinder;
    private IOnTestDataListener binder;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_binder_test);
        // 实现一个带有回调的aidl通信  其中有parcel参数的传递

        Intent intent = new Intent();
        intent.setAction("com.binder.test.service");
        intent.setPackage("com.tencent.wemeet.testwhitelist");
        isBinder = bindService(intent, connection, Context.BIND_AUTO_CREATE);

        IOnTestDataCallback callback1 = new IOnTestDataCallback.Stub() {
            @Override
            public void onCallback(TestDataBean dataBean) throws RemoteException {

            }

            @Override
            public void onDealRegisterCbData(String name, int number) throws RemoteException {
                Log.d(TAG, "11111 name = " + name + ",number = " + number);
            }
        };


        IOnTestDataCallback callback2 = new IOnTestDataCallback.Stub() {
            @Override
            public void onCallback(TestDataBean dataBean) throws RemoteException {

            }

            @Override
            public void onDealRegisterCbData(String name, int number) throws RemoteException {
                Log.d(TAG, "22222 name = " + name + ",number = " + number);
            }
        };

        findViewById(R.id.btn_register).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (binder == null) {
                    return;
                }
                try {
                    binder.registerCallback(callback1);
                    binder.registerCallback(callback2);
                } catch (RemoteException e) {
                    throw new RuntimeException(e);
                }
            }
        });

        findViewById(R.id.btn_unregister).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                try {
                    binder.unRegisterCallback(callback2);
                    binder.unRegisterCallback(callback1);
                } catch (RemoteException e) {
                    throw new RuntimeException(e);
                }

            }
        });


        findViewById(R.id.btn_test).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (binder == null) {
                    Log.d(TAG, "binder is null");
                    return;
                }
                Log.d(TAG, "begin");
                try {
                    binder.sendData("123", new byte[]{1, 2, 3}, new IOnTestDataCallback.Stub() {
                        @Override
                        public void onCallback(TestDataBean dataBean) throws RemoteException {
                            Log.d(TAG, "name = " + dataBean.getName() + ",number = " + dataBean.getNumber());
                        }

                        @Override
                        public void onDealRegisterCbData(String name, int number) throws RemoteException {
                            Log.d(TAG, "333333 name = " + name + ",number = " + number);
                        }
                    });
                } catch (RemoteException e) {
                    Log.d(TAG, "sendData RemoteException");
                    throw new RuntimeException(e);
                }

                Log.d(TAG, "end");
            }
        });


    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (isBinder) {
            isBinder = false;
            unbindService(connection);
            connection = null;
            binder = null;
        }
    }

    private ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.d(TAG, "onServiceConnected");
            binder = IOnTestDataListener.Stub.asInterface(service);

        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.d(TAG, "onServiceDisconnected");
        }
    };
}

主要调用流程

1.注册

此处我们注册两个IOnTestDataCallback对象,如上面的callback1、callback2所示,

注册是调用如下实现

java 复制代码
   binder.registerCallback(callback1);
   binder.registerCallback(callback2);

点击注册的按钮时,日志打印如下所示,日志来源于服务端输出信息

java 复制代码
2024-09-04 14:02:44.192  4794-4815  TestBinderService       com.tencent.wemeet.testwhitelist     D  register:true,remoteCallbackList :android.os.RemoteCallbackList@825eba6
2024-09-04 14:02:44.193  4794-4815  TestBinderService       com.tencent.wemeet.testwhitelist     D  register:true,remoteCallbackList :android.os.RemoteCallbackList@825eba6

2.发送调用

当进行验证时是调用sendData方法,因为服务端针对此方法内部处理了RemoteCallbackList的远程回调的具体实现

java 复制代码
binder.sendData()

调用发送按钮时,client端的日志打印如下所示,从日志中可以看出客户端注册的回调中的callback1与callback2的onDealRegisterCbData方法被分别调用了。

java 复制代码
2024-09-04 14:05:32.087  2900-2900  TestBinderActivity      com.example.test                     D  begin
2024-09-04 14:05:32.088  2900-2900  TestBinderActivity      com.example.test                     D  end
2024-09-04 14:05:37.092  2900-2956  TestBinderActivity      com.example.test                     D  name = zhangsan,number = 20
2024-09-04 14:05:37.096  2900-2956  TestBinderActivity      com.example.test                     D  11111 name = xiaoming,number = 0
2024-09-04 14:05:37.101  2900-2956  TestBinderActivity      com.example.test                     D  22222 name = xiaoming,number = 1

3.反注册

反注册时调用如下实现

java 复制代码
   binder.unRegisterCallback(callback2);
   binder.unRegisterCallback(callback1);

此时调用unRegister的按钮时,服务端的打印如下所示

java 复制代码
2024-09-04 14:10:26.456  4794-4815  TestBinderService       com.tencent.wemeet.testwhitelist     D  unregister:true,remoteCallbackList :android.os.RemoteCallbackList@825eba6
2024-09-04 14:10:26.458  4794-4815  TestBinderService       com.tencent.wemeet.testwhitelist     D  unregister:true,remoteCallbackList :android.os.RemoteCallbackList@825eba6
相关推荐
帅得不敢出门8 小时前
安卓设备adb执行AT指令控制电话卡
android·adb·sim卡·at指令·电话卡
我又来搬代码了10 小时前
【Android】使用productFlavors构建多个变体
android
德育处主任11 小时前
Mac和安卓手机互传文件(ADB)
android·macos
芦半山11 小时前
Android“引用们”的底层原理
android·java
迃-幵12 小时前
力扣:225 用队列实现栈
android·javascript·leetcode
大风起兮云飞扬丶12 小时前
Android——从相机/相册获取图片
android
Rverdoser13 小时前
Android Studio 多工程公用module引用
android·ide·android studio
aaajj13 小时前
[Android]从FLAG_SECURE禁止截屏看surface
android
@OuYang13 小时前
android10 蓝牙(二)配对源码解析
android
Liknana13 小时前
Android 网易游戏面经
android·面试