You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Kotlin Multiplatform中正确调用AppDelegate获取APNs设备令牌

在Compose Multiplatform中实现iOS APNs令牌获取并关联AppDelegate

问题场景

你使用Compose Multiplatform开发移动应用,需要在iOS端获取APNs令牌并提交到服务器。目前已编写Kotlin版AppDelegate和注册远程通知的代码,但AppDelegate的回调未触发,同时需要将NSData类型的设备令牌转换为标准十六进制字符串。

解决步骤

1. 关联SwiftUI App入口与自定义AppDelegate

由于你用SwiftUI的@main App结构体作为iOS入口,默认不会自动加载自定义AppDelegate,需通过UIApplicationDelegateAdaptor关联两者。修改iOS端Swift代码:

@main
struct iOSApp: App {
    // 关联自定义AppDelegate
    @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
    
    init() {
        HelperKt.doInitKoin()
    }
    
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}

2. 修正Kotlin AppDelegate的令牌解析与回调逻辑

将回调参数类型改为Data(对应Swift的Data),按Swift逻辑转换为十六进制字符串,并通过全局回调传递给业务层:

// 全局回调变量,用于接收令牌并传递给业务层
var notifyTokenCallback: ((String) -> Unit)? = null

class AppDelegate : UIResponder(), UIApplicationDelegateProtocol {
    override fun application(application: UIApplication, didFinishLaunchingWithOptions: Map<Any?, *>?): Boolean {
        // 启动时请求通知权限,需用户授权才能获取令牌
        UNUserNotificationCenter.current().requestAuthorization(
            UNAuthorizationOptions.Alert or UNAuthorizationOptions.Badge or UNAuthorizationOptions.Sound
        ) { granted, error ->
            if (granted) {
                application.registerForRemoteNotifications()
            }
        }
        return true
    }

    override fun application(
        application: UIApplication,
        didRegisterForRemoteNotificationsWithDeviceToken: Data
    ) {
        // 把Data转换为标准十六进制字符串,和Swift逻辑一致
        val token = didRegisterForRemoteNotificationsWithDeviceToken.map {
            String.format("%02.2hhx", it)
        }.joinToString("")
        
        // 触发回调传递令牌
        notifyTokenCallback?.invoke(token)
        println("APNs Token: $token")
    }

    override fun application(
        application: UIApplication,
        didFailToRegisterForRemoteNotificationsWithError: NSError
    ) {
        println("APNs注册失败: ${didFailToRegisterForRemoteNotificationsWithError.localizedDescription}")
    }

    companion object : UIResponderMeta(), UIApplicationDelegateProtocolMeta
}

3. 完善Kotlin层的令牌获取逻辑

修改fetchNotifyToken函数,将业务层回调绑定到全局变量,确保AppDelegate能触发它:

actual fun fetchNotifyToken(tokenFun: (String) -> Unit) {
    // 保存业务层回调
    notifyTokenCallback = tokenFun
    // 注册远程通知(若AppDelegate启动时未注册)
    UIApplication.sharedApplication.registerForRemoteNotifications()
}

注:移除suspend修饰符,因为registerForRemoteNotifications是异步操作,无需挂起函数。若业务层需协程处理,可在回调内切换到协程上下文。

4. 测试验证

运行iOS应用后,授权通知权限,控制台会打印APNs令牌,同时业务层回调会接收到该令牌,可在回调中完成令牌提交服务器的逻辑。


内容的提问来源于stack exchange,提问作者Mac Z

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 20:22:39