android之binder关于RemoteCallbackList的使用

[复制链接]
发表于 2026-1-28 03:57:38 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
简述

在android关于binder的简朴通讯过程的根本上添加关于RemoteCallbackList的使用,client端对server端举行register与unregister的过程,然后server主动给client端回调处置惩罚。
aidl文件修改

1.在IOnTestDataListener.aidl文件中加入register与unregister的方法
  1. package com.example.test;
  2. import com.example.test.IOnTestDataCallback;
  3. // Declare any non-default types here with import statements
  4. interface IOnTestDataListener {
  5.     void registerCallback(in IOnTestDataCallback callback);
  6.     oneway void sendData(String str, in byte[] bytes,in IOnTestDataCallback callback);
  7.     void unRegisterCallback(in IOnTestDataCallback callback);
  8. }
复制代码
此中registerCallback与unRegisterCallback是新增的方法。
2.在IOnTestDataCallback.aidl中加入server主动触发远程回调的方法
  1. // IOnTestDataCallback.aidl
  2. package com.example.test;
  3. import com.example.test.TestDataBean;
  4. // Declare any non-default types here with import statements
  5. interface IOnTestDataCallback {
  6.     void onCallback(in TestDataBean dataBean);
  7.     void onDealRegisterCbData(String name,int number);
  8. }
复制代码
此中onDealRegisterCbData是新增的方法
服务端

重要实今世码如下所示
  1. package com.tencent.wemeet.testwhitelist;
  2. import android.app.Service;
  3. import android.content.Intent;
  4. import android.os.IBinder;
  5. import android.os.RemoteCallbackList;
  6. import android.os.RemoteException;
  7. import android.util.Log;
  8. import androidx.annotation.Nullable;
  9. import com.example.test.IOnTestDataCallback;
  10. import com.example.test.IOnTestDataListener;
  11. import com.example.test.TestDataBean;
  12. import java.util.Arrays;
  13. public class TestBinderService extends Service {
  14.     private static final String TAG = "TestBinderService";
  15.     private final RemoteCallbackList<IOnTestDataCallback> remoteCallbackList = new RemoteCallbackList<>();
  16.     @Nullable
  17.     @Override
  18.     public IBinder onBind(Intent intent) {
  19.         return new IOnTestDataListener.Stub() {
  20.             @Override
  21.             public void registerCallback(IOnTestDataCallback callback) throws RemoteException {
  22.                 boolean register = remoteCallbackList.register(callback);
  23.                 Log.d(TAG, "register:" + register + ",remoteCallbackList :" + remoteCallbackList);
  24.             }
  25.             @Override
  26.             public void sendData(String str, byte[] bytes, IOnTestDataCallback callback) throws RemoteException {
  27.                 Log.d(TAG, "str = " + str + ",bytes = " + Arrays.toString(bytes));
  28.                 TestDataBean bean = new TestDataBean();
  29.                 bean.setName("zhangsan");
  30.                 bean.setNumber(20);
  31.                 try {
  32.                     Thread.sleep(5000);
  33.                     callback.onCallback(bean);
  34.                     // callback register data
  35.                     int num = remoteCallbackList.beginBroadcast();
  36.                     for (int i = 0; i < num; i++) {
  37.                         IOnTestDataCallback broadcastItem = remoteCallbackList.getBroadcastItem(i);
  38.                         broadcastItem.onDealRegisterCbData("xiaoming", i);
  39.                     }
  40.                     remoteCallbackList.finishBroadcast();
  41.                 } catch (InterruptedException e) {
  42.                     throw new RuntimeException(e);
  43.                 }
  44.             }
  45.             @Override
  46.             public void unRegisterCallback(IOnTestDataCallback callback) throws RemoteException {
  47.                 boolean unregister = remoteCallbackList.unregister(callback);
  48.                 Log.d(TAG, "unregister:" + unregister + ",remoteCallbackList :" + remoteCallbackList);
  49.             }
  50.         };
  51.     }
  52.     @Override
  53.     public void onCreate() {
  54.         super.onCreate();
  55.         Log.d(TAG, "onCreate");
  56.     }
  57. }
复制代码
从上代码可以看出多了registerCallback与unRegisterCallback的方法的实现,同时在sendData中模拟了server端给client端的回调实现方式。代码实现如截图中的赤色框所示,其目的是给每个register的client端转达数据。

客户端

重要实今世码如下所示
  1. package com.example.test;
  2. import android.content.ComponentName;
  3. import android.content.Context;
  4. import android.content.Intent;
  5. import android.content.ServiceConnection;
  6. import android.os.Bundle;
  7. import android.os.IBinder;
  8. import android.os.RemoteException;
  9. import android.util.Log;
  10. import android.view.View;
  11. import androidx.annotation.Nullable;
  12. import androidx.appcompat.app.AppCompatActivity;
  13. public class TestBinderActivity extends AppCompatActivity {
  14.     public static final String TAG = "TestBinderActivity";
  15.     private boolean isBinder;
  16.     private IOnTestDataListener binder;
  17.     @Override
  18.     protected void onCreate(@Nullable Bundle savedInstanceState) {
  19.         super.onCreate(savedInstanceState);
  20.         setContentView(R.layout.activity_binder_test);
  21.         // 实现一个带有回调的aidl通信  其中有parcel参数的传递
  22.         Intent intent = new Intent();
  23.         intent.setAction("com.binder.test.service");
  24.         intent.setPackage("com.tencent.wemeet.testwhitelist");
  25.         isBinder = bindService(intent, connection, Context.BIND_AUTO_CREATE);
  26.         IOnTestDataCallback callback1 = new IOnTestDataCallback.Stub() {
  27.             @Override
  28.             public void onCallback(TestDataBean dataBean) throws RemoteException {
  29.             }
  30.             @Override
  31.             public void onDealRegisterCbData(String name, int number) throws RemoteException {
  32.                 Log.d(TAG, "11111 name = " + name + ",number = " + number);
  33.             }
  34.         };
  35.         IOnTestDataCallback callback2 = new IOnTestDataCallback.Stub() {
  36.             @Override
  37.             public void onCallback(TestDataBean dataBean) throws RemoteException {
  38.             }
  39.             @Override
  40.             public void onDealRegisterCbData(String name, int number) throws RemoteException {
  41.                 Log.d(TAG, "22222 name = " + name + ",number = " + number);
  42.             }
  43.         };
  44.         findViewById(R.id.btn_register).setOnClickListener(new View.OnClickListener() {
  45.             @Override
  46.             public void onClick(View v) {
  47.                 if (binder == null) {
  48.                     return;
  49.                 }
  50.                 try {
  51.                     binder.registerCallback(callback1);
  52.                     binder.registerCallback(callback2);
  53.                 } catch (RemoteException e) {
  54.                     throw new RuntimeException(e);
  55.                 }
  56.             }
  57.         });
  58.         findViewById(R.id.btn_unregister).setOnClickListener(new View.OnClickListener() {
  59.             @Override
  60.             public void onClick(View v) {
  61.                 try {
  62.                     binder.unRegisterCallback(callback2);
  63.                     binder.unRegisterCallback(callback1);
  64.                 } catch (RemoteException e) {
  65.                     throw new RuntimeException(e);
  66.                 }
  67.             }
  68.         });
  69.         findViewById(R.id.btn_test).setOnClickListener(new View.OnClickListener() {
  70.             @Override
  71.             public void onClick(View v) {
  72.                 if (binder == null) {
  73.                     Log.d(TAG, "binder is null");
  74.                     return;
  75.                 }
  76.                 Log.d(TAG, "begin");
  77.                 try {
  78.                     binder.sendData("123", new byte[]{1, 2, 3}, new IOnTestDataCallback.Stub() {
  79.                         @Override
  80.                         public void onCallback(TestDataBean dataBean) throws RemoteException {
  81.                             Log.d(TAG, "name = " + dataBean.getName() + ",number = " + dataBean.getNumber());
  82.                         }
  83.                         @Override
  84.                         public void onDealRegisterCbData(String name, int number) throws RemoteException {
  85.                             Log.d(TAG, "333333 name = " + name + ",number = " + number);
  86.                         }
  87.                     });
  88.                 } catch (RemoteException e) {
  89.                     Log.d(TAG, "sendData RemoteException");
  90.                     throw new RuntimeException(e);
  91.                 }
  92.                 Log.d(TAG, "end");
  93.             }
  94.         });
  95.     }
  96.     @Override
  97.     protected void onDestroy() {
  98.         super.onDestroy();
  99.         if (isBinder) {
  100.             isBinder = false;
  101.             unbindService(connection);
  102.             connection = null;
  103.             binder = null;
  104.         }
  105.     }
  106.     private ServiceConnection connection = new ServiceConnection() {
  107.         @Override
  108.         public void onServiceConnected(ComponentName name, IBinder service) {
  109.             Log.d(TAG, "onServiceConnected");
  110.             binder = IOnTestDataListener.Stub.asInterface(service);
  111.         }
  112.         @Override
  113.         public void onServiceDisconnected(ComponentName name) {
  114.             Log.d(TAG, "onServiceDisconnected");
  115.         }
  116.     };
  117. }
复制代码
重要调用流程

1.注册

此处我们注册两个IOnTestDataCallback对象,如上面的callback1、callback2所示,
注册是调用如下实现
  1.    binder.registerCallback(callback1);
  2.    binder.registerCallback(callback2);
复制代码
点击注册的按钮时,日志日志打印如下所示,日志日志泉源于服务端输出信息
  1. 2024-09-04 14:02:44.192  4794-4815  TestBinderService       com.tencent.wemeet.testwhitelist     D  register:true,remoteCallbackList :android.os.RemoteCallbackList@825eba6
  2. 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的远程回调的具体实现
  1. binder.sendData()
复制代码
调用发送按钮时,client端的日志日志打印如下所示,从日志中可以看出客户端注册的回调中的callback1与callback2的onDealRegisterCbData方法被分别调用了。
  1. 2024-09-04 14:05:32.087  2900-2900  TestBinderActivity      com.example.test                     D  begin
  2. 2024-09-04 14:05:32.088  2900-2900  TestBinderActivity      com.example.test                     D  end
  3. 2024-09-04 14:05:37.092  2900-2956  TestBinderActivity      com.example.test                     D  name = zhangsan,number = 20
  4. 2024-09-04 14:05:37.096  2900-2956  TestBinderActivity      com.example.test                     D  11111 name = xiaoming,number = 0
  5. 2024-09-04 14:05:37.101  2900-2956  TestBinderActivity      com.example.test                     D  22222 name = xiaoming,number = 1
复制代码
3.反注册

反注册时调用如下实现
  1.    binder.unRegisterCallback(callback2);
  2.    binder.unRegisterCallback(callback1);
复制代码
此时调用unRegister的按钮时,服务端的打印如下所示
  1. 2024-09-04 14:10:26.456  4794-4815  TestBinderService       com.tencent.wemeet.testwhitelist     D  unregister:true,remoteCallbackList :android.os.RemoteCallbackList@825eba6
  2. 2024-09-04 14:10:26.458  4794-4815  TestBinderService       com.tencent.wemeet.testwhitelist     D  unregister:true,remoteCallbackList :android.os.RemoteCallbackList@825eba6
复制代码
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表