【Binder】Android 进程间通信的利器:RemoteCallbackList 在 AIDL 中的应用

我就在想,在学习Binder时怎么会跑出来这么个玩意儿------RemoteCallbackList

顾名思义,RemoteCallbackList就是一个“回调列表”,它用于在不同的组件之间传递消息或执行特定的操作。举个例子,假设我们有一个服务(Service),而其他的组件(比如Activity)需要与这个服务进行通信。我们就可以使用RemoteCallbackList,可以在服务中注册回调方法,然后其他组件可以通过这个列表将自己的回调方法添加到服务中。

注:Binder的面试为啥会出现这么一个奇怪的类,不知道细心的同学们有没有发现,我们在使用aidl进行进程间通信时,经常是客户端APP调用服务端APP代码让服务端干活。那服务端干完活了之后怎么通知我们客户端呢,就要用到RemoteCallbackList来回调啦。

也就是说当在 Android 中使用AIDL进行进程间通信时,AIDL 允许我们定义接口,并在客户端和服务端之间进行调用。在某些情况下,我们需要在服务端执行某个操作后通知客户端,这时可以使用 RemoteCallbackList。

RemoteCallbackList 是 Android 提供的一个用于管理回调接口的类,特别适用于在服务端向多个客户端发送通知。它解决了在跨进程通信中传递接口对象的问题,确保客户端能够正确接收服务端的回调。

直接上代码

步骤 1: 定义 AIDL 接口
创建一个 AIDL 接口文件 CameraService.aidl,定义客户端与服务端之间的通信接口:

// CameraService.aidl
interface CameraService {
    void openCamera();
    void registerCallback(ICameraCallback callback);
    void unregisterCallback(ICameraCallback callback);
}

创建一个 AIDL 接口文件 ICameraCallback.aidl,定义用于客户端回调的接口:

// ICameraCallback.aidl
interface ICameraCallback {
    void onCameraOpened();
}

步骤 2: 实现 AIDL 接口
在服务端(远程服务)中,创建一个继承自 Service 的服务类 CameraService,实现上述定义的 AIDL 接口:

// CameraService.kt
class CameraService : Service() {

    private val callbackList = RemoteCallbackList<ICameraCallback>()

    override fun onBind(intent: Intent): IBinder? {
        return cameraService
    }

    private val cameraService = object : CameraService.Stub() {
        override fun openCamera() {
            // 打开摄像头的逻辑
            
            // 通知所有注册的客户端摄像头已打开
            val count = callbackList.beginBroadcast()
            for (i in 0 until count) {
                val callback = callbackList.getBroadcastItem(i)
                try {
                    callback?.onCameraOpened()
                } catch (e: RemoteException) {
                    // 处理异常
                }
            }
            callbackList.finishBroadcast()
        }

        override fun registerCallback(callback: ICameraCallback?) {
            callback?.let { callbackList.register(it) }
        }

        override fun unregisterCallback(callback: ICameraCallback?) {
            callback?.let { callbackList.unregister(it) }
        }
    }
}

步骤 3: 客户端回调注册与接收
在客户端中,创建一个 Activity:

// MainActivity.kt
class MainActivity : AppCompatActivity() {

    private var cameraService: CameraService? = null
    private var cameraCallback: ICameraCallback? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // 绑定服务
        val intent = Intent(this, CameraService::class.java)
        bindService(intent, connection, Context.BIND_AUTO_CREATE)

        // 设置按钮点击事件
        button.setOnClickListener {
            // 使用协程在后台线程发送消息给服务端
            lifecycleScope.launch(Dispatchers.IO) {
                cameraService?.openCamera()
            }
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        // 解绑服务
        unbindService(connection)
    }

    private val connection = object : ServiceConnection {
        override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
            cameraService = CameraService.Stub.asInterface(service)

            // 创建回调对象
            cameraCallback = object : ICameraCallback.Stub() {
                override fun onCameraOpened() {
                    // 在 UI 线程中处理回调
                    runOnUiThread {
                        // 摄像头已打开的处理逻辑
                        // ...
                    }
                }
            }

            // 注册回调
            cameraService?.registerCallback(cameraCallback)
        }

        override fun onServiceDisconnected(name: ComponentName?) {
            cameraService = null
            cameraCallback = null
        }
    }
}

记得在 AndroidManifest.xml 文件中声明服务和权限:

<manifest>
    <uses-permission android:name="android.permission.CAMERA" />
```xml
<application>
        <service android:name=".CameraService" android:process=":remote" />
    </application>
</manifest>

在客户端的 MainActivity 中,我们绑定了服务并在按钮的点击事件中使用协程调用 AIDL 接口的 openCamera 方法发送消息给服务端。同时,我们创建了一个 ServiceConnection 对象,以便在与服务建立或断开连接时获取服务的实例。

服务端的 CameraService 类实现了 AIDL 接口,并在 openCamera 方法中执行打开摄像头的逻辑。在摄像头成功打开后,使用 RemoteCallbackList 通知所有注册的客户端。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: Android 进程间通信(IPC)有以下几种方式: 1. Binder:是 Android 系统最常用的 IPC 机制,它是一种高效、稳定、安全的跨进程通信方式,常用于 Service 和 Activity 之间通信。 2. Messenger:基于 Binder 实现的跨进程通信方式,可以向其他进程发送 Message。 3. AIDL:也是基于 Binder 实现的跨进程通信方式,使用 AIDL 定义接口,然后在客户端和服务端之间传递数据。 4. ContentProvider:提供了一种在多个应用程序之间共享数据的方式,其他应用程序可以通过 ContentResolver 访问 ContentProvider 的数据。 5. Socket:通过套接字进行进程间通信,常用于网络通信和本地进程通信。 6. BroadcastReceiver:通过 Intent 进行跨进程通信,可以在不同的应用程序之间传递消息。 以上是 Android 常见的进程间通信方式,不同的场景可以选择不同的方式来实现进程间通信。 ### 回答2: Android进程间通信的方式有以下几种: 1. 使用Bundle:Bundle是一种存储数据的容器,在Android可以用于进程间通信。通过将数据存储在Bundle对象,然后在不同的进程间传递Bundle对象来实现通信。 2. 使用Intent:Intent是一种在Android用于传递消息和数据的对象。通过在不同的进程间发送Intent来实现进程间通信。 3. 使用AIDLAndroid Interface Definition Language):AIDL是一种用于定义跨进程接口的语言。通过在服务端定义AIDL接口,然后在客户端通过AIDL来调用服务端提供的接口,实现进程间通信。 4. 使用Messenger:Messenger是一种轻量级的进程间通信机制,它基于HandlerBinder机制。通过在不同的进程间传递Messenger对象,实现进程间通信。 5. 使用ContentProvider:ContentProvider是一种用于在不同应用程序之间共享数据的组件。通过在ContentProvider实现数据的读写操作,其他应用程序可以通过ContentResolver来访问和共享这些数据,实现进程间通信。 通过以上几种方式,Android应用程序可以实现不同进程间的通信,以满足不同的需求和场景。 ### 回答3: Android进程间通信有以下几种方式: 1. Binder机制:BinderAndroid一种高效的进程间通信机制,它是基于C/S架构的,通过将服务以Binder驱动的方式注册到系统Service Manager,实现一对多或多对多的进程间通信。 2. AIDLAndroid Interface Definition Language):AIDLAndroid进程间通信接口定义语言,通过定义接口及数据类型,在服务端和客户端之间进行通信。AIDL框架提供了支持跨程序的IPC(Inter-Process Communication)功能。 3. Messenger:Messenger是基于AIDL封装的一种进程间通信方式。通过Messenger可以实现进程间的消息传递,但是一次只能传递一个消息,不能进行数据的交互操作。 4. ContentProvider:ContentProviderAndroid提供的一种进程间通信方式,它通过对外共享数据的方式实现进程间的数据交换。ContentProvider可以对外提供访问数据库等共享数据的接口,并通过URI进行数据的增删改查操作。 5. Broadcast Receiver:广播接收器是一种全局的事件通知机制,可以在不同进程之间进行消息的发送和接收。通过广播接收器可以实现简单的进程间通信,但是通信的内容只能是Intent对象。 6. Socket:Socket是一种传统的网络通信方式,通过网络套接字进行进程间通信。在Android,可以使用Socket实现不同进程之间的通信,但是相对于其他方式,Socket的效率较低。 以上是常见的Android进程间通信的方式,根据具体的需求和场景选择适合的方式可以有效实现进程间的数据交换和消息传递。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

jiet_h

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值