如何将第三方Android/iOS SDK集成到KMM并封装为通用模块?
在KMM中封装双端第三方SDK(以Zego SDK为例)
针对你用KMM开发交友App,需要集成仅支持Android/iOS的第三方SDK的场景,核心方案是利用KMM的expect/actual机制封装平台特定实现,在Common层提供统一接口供业务逻辑调用。以下是具体步骤:
一、在Common模块定义统一接口
先在commonMain下定义expect类和业务所需的核心接口,对齐两端SDK的API设计(因为你提到两端API基本一致,所以接口可以完全统一):
// commonMain/kotlin/com/yourapp/ZegoService.kt expect class ZegoService { // 初始化SDK fun initialize(appId: Long, appSign: String) // 登录房间(异步转为协程) suspend fun loginRoom(roomId: String, userId: String): Boolean // 发送房间消息 fun sendMessage(roomId: String, message: String) // 设置消息监听 fun setMessageListener(listener: ZegoMessageListener) // 可选:销毁SDK实例 fun destroy() } // 消息回调接口 interface ZegoMessageListener { fun onMessageReceived(roomId: String, userId: String, message: String) }
二、Android端实现Actual类
- 先在Android模块的
build.gradle.kts中添加Zego Android SDK依赖:
// androidApp/build.gradle.kts dependencies { implementation("im.zego:zego-express-engine:latest.release") }
- 在
androidMain下实现actual类,直接调用Android SDK的API,注意将回调转为Kotlin协程:
// androidMain/kotlin/com/yourapp/ZegoService.kt import im.zego.zegoexpress.ZegoExpressEngine import im.zego.zegoexpress.callback.ZegoRoomCallback import im.zego.zegoexpress.callback.ZegoRoomMessageListener import im.zego.zegoexpress.entity.ZegoScenario import im.zego.zegoexpress.entity.ZegoUser import kotlinx.coroutines.suspendCancellableCoroutine actual class ZegoService { private var engine: ZegoExpressEngine? = null actual fun initialize(appId: Long, appSign: String) { engine = ZegoExpressEngine.createEngine(appId, appSign, true, ZegoScenario.GENERAL, null) } actual suspend fun loginRoom(roomId: String, userId: String): Boolean { return suspendCancellableCoroutine { cont -> val user = ZegoUser(userId) engine?.loginRoom(roomId, user, object : ZegoRoomCallback { override fun onRoomLoginSuccess() { cont.resume(true) } override fun onRoomLoginError(errorCode: Int, message: String?) { cont.resume(false) } }) ?: cont.resume(false) } } actual fun sendMessage(roomId: String, message: String) { engine?.sendRoomMessage(roomId, message) { errorCode, _, _ -> // 可在这里处理发送结果,比如通知业务层 } } actual fun setMessageListener(listener: ZegoMessageListener) { engine?.setRoomMessageListener(object : ZegoRoomMessageListener { override fun onRoomMessageReceived(roomId: String, messages: MutableList<*>?) { @Suppress("UNCHECKED_CAST") (messages as? List<im.zego.zegoexpress.entity.ZegoRoomMessage>)?.forEach { msg -> listener.onMessageReceived(roomId, msg.user.userID, msg.message) } } }) } actual fun destroy() { ZegoExpressEngine.destroyEngine(null) engine = null } }
三、iOS端实现Actual类
- 在iOS模块的
Podfile中添加Zego iOS SDK依赖,然后执行pod install:
# iosApp/Podfile target 'iosApp' do use_frameworks! pod 'ZegoExpressEngine' end
- 在
iosMain下实现actual类,调用iOS SDK的API,同样处理协程和回调转换:
// iosMain/kotlin/com/yourapp/ZegoService.kt import kotlinx.coroutines.suspendCancellableCoroutine import platform.ZegoExpressEngine.ZegoExpressEngine import platform.ZegoExpressEngine.ZegoRoomMessageDelegateProtocol import platform.ZegoExpressEngine.ZegoScenario import platform.ZegoExpressEngine.ZegoUser actual class ZegoService { private var engine: ZegoExpressEngine? = null actual fun initialize(appId: Long, appSign: String) { engine = ZegoExpressEngine.createEngineWithAppID( appID = appId.toULong(), appSign = appSign, isTestEnv = true, scenario = ZegoScenario.ZegoScenarioGeneral, delegate = null ) } actual suspend fun loginRoom(roomId: String, userId: String): Boolean { return suspendCancellableCoroutine { cont -> val user = ZegoUser.userWithUserID(userId, userName = userId) engine?.loginRoom(roomId, user = user, config = null) { error, _ -> cont.resume(error == 0) } ?: cont.resume(false) } } actual fun sendMessage(roomId: String, message: String) { engine?.sendRoomMessage(roomId, message) { error, _ -> // 处理发送结果 } } actual fun setMessageListener(listener: ZegoMessageListener) { engine?.setRoomMessageDelegate(object : ZegoRoomMessageDelegateProtocol { override fun onRoomMessageReceived(roomID: String, messages: List<*>?) { @Suppress("UNCHECKED_CAST") (messages as? List<platform.ZegoExpressEngine.ZegoRoomMessage>)?.forEach { msg -> listener.onMessageReceived(roomID, msg.user.userID, msg.message) } } }) } actual fun destroy() { ZegoExpressEngine.destroyEngine(null) engine = null } }
四、在业务逻辑中统一调用
封装完成后,你可以在Common层或业务模块中直接使用ZegoService,完全不用关心平台差异:
// commonMain/kotlin/com/yourapp/chat/ChatHandler.kt class ChatHandler(private val zegoService: ZegoService) { fun setupZego(appId: Long, appSign: String) { zegoService.initialize(appId, appSign) zegoService.setMessageListener(object : ZegoMessageListener { override fun onMessageReceived(roomId: String, userId: String, message: String) { // 处理收到的消息,比如更新UI或存入本地数据库 } }) } suspend fun joinRoom(roomId: String, userId: String): Boolean { return zegoService.loginRoom(roomId, userId) } fun sendChatMessage(roomId: String, content: String) { zegoService.sendMessage(roomId, content) } fun cleanup() { zegoService.destroy() } }
关键注意事项
- 协程转换:平台SDK的异步回调必须用
suspendCancellableCoroutine转为Kotlin协程,保证Common层的代码风格统一,同时处理取消逻辑。 - 类型转换:注意Kotlin与Android/iOS平台的类型差异,比如
Long转iOS的ULong,集合的类型强转(需添加@Suppress消除警告)。 - 权限处理:Android端需在
AndroidManifest.xml声明必要权限(如麦克风、网络);iOS端需在Info.plist添加权限描述(如NSMicrophoneUsageDescription)。 - 生命周期绑定:SDK的初始化和销毁建议与App生命周期绑定,比如Android在
Application的onCreate/onTerminate,iOS在AppDelegate的对应方法中调用。
内容的提问来源于stack exchange,提问作者laram
相关产品推荐
相关产品推荐

