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
相关推荐
幻雨様4 小时前
UE5多人MOBA+GAS 45、制作冲刺技能
android·ue5
Jerry说前后端5 小时前
Android 数据可视化开发:从技术选型到性能优化
android·信息可视化·性能优化
Meteors.6 小时前
Android约束布局(ConstraintLayout)常用属性
android
alexhilton7 小时前
玩转Shader之学会如何变形画布
android·kotlin·android jetpack
whysqwhw11 小时前
安卓图片性能优化技巧
android
风往哪边走11 小时前
自定义底部筛选弹框
android
Yyyy48212 小时前
MyCAT基础概念
android
Android轮子哥12 小时前
尝试解决 Android 适配最后一公里
android
雨白13 小时前
OkHttp 源码解析:enqueue 非同步流程与 Dispatcher 调度
android
风往哪边走14 小时前
自定义仿日历组件弹框
android