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

如何在Kotlin Multiplatform iOS项目中使用LiveActivity

在Kotlin Multiplatform iOS项目中实现LiveActivity的方案

目前Kotlin Multiplatform没有官方提供LiveActivity的绑定API,你可以通过两种方式实现:cinterop绑定Objective-C API 或者 Swift类桥接调用,以下是具体步骤:


方式一:使用cinterop绑定ActivityKit

1. 创建cinterop定义文件

在项目的src/nativeInterop/cinterop目录下新建LiveActivity.def文件,内容如下:

language = Objective-C
modules = ActivityKit UIKit
header = """
#import <ActivityKit/ActivityKit.h>
#import <UIKit/UIKit.h>

// 自定义LiveActivity的属性和状态类
@interface LiveActivityAttributes : NSObject <ActivityAttributes>
@property (nonatomic, readonly) NSString *taskTitle;
- (instancetype)initWithTaskTitle:(NSString *)taskTitle;
@end

@interface LiveActivityState : NSObject
@property (nonatomic, readonly) NSString *currentProgress;
- (instancetype)initWithProgress:(NSString *)progress;
@end
"""

2. 在build.gradle.kts中配置cinterop

在KMP的iOS目标块中添加cinterop配置:

kotlin {
    ios {
        binaries.framework {
            baseName = "YourKMPFramework"
        }
        cinterops {
            create("LiveActivity") {
                defFile(file("src/nativeInterop/cinterop/LiveActivity.def"))
                includeDirs("src/nativeInterop/include") // 如果有额外头文件需要引入
            }
        }
    }

    sourceSets {
        iosMain.dependencies {
            implementation(project.dependencies.cinterop("LiveActivity"))
        }
    }
}

3. 实现Objective-C类的具体逻辑

在src/nativeInterop/include目录下新建LiveActivityImpl.m文件(如果没有include目录就创建),实现刚才定义的类:

#import "LiveActivity.def"

@implementation LiveActivityAttributes
- (instancetype)initWithTaskTitle:(NSString *)taskTitle {
    self = [super init];
    if (self) {
        _taskTitle = taskTitle;
    }
    return self;
}
@end

@implementation LiveActivityState
- (instancetype)initWithProgress:(NSString *)progress {
    self = [super init];
    if (self) {
        _currentProgress = progress;
    }
    return self;
}
@end

4. 在Kotlin代码中调用LiveActivity

import com.yourpackage.LiveActivity.*
import platform.Foundation.NSError
import platform.objc.exceptionForNSError

fun startLiveActivity(taskTitle: String, progress: String) {
    if (platform.os.version.majorVersion >= 16 && platform.os.version.minorVersion >= 1) {
        val attributes = LiveActivityAttributes(taskTitle)
        val state = LiveActivityState(progress)
        try {
            val activity = ActivityKit.Activity.request(attributes, state, null)
            // 保存activity.id用于后续更新/结束
        } catch (error: NSError) {
            val exception = exceptionForNSError(error)
            // 处理启动失败的异常
        }
    }
}

方式二:Swift类桥接(更简单直观)

1. 在iOS项目中创建LiveActivity管理类

在Xcode的iOS target里新建LiveActivityManager.swift:

import ActivityKit

@objc class LiveActivityManager: NSObject {
    @objc static func startLiveActivity(title: String, progress: String) -> String? {
        guard #available(iOS 16.1, *) else { return nil }
        
        struct TaskAttributes: ActivityAttributes {
            public typealias ContentState = TaskState
            
            struct TaskState: Codable, Hashable {
                var progress: String
            }
            
            var title: String
        }
        
        let attributes = TaskAttributes(title: title)
        let state = TaskAttributes.TaskState(progress: progress)
        
        do {
            let activity = try Activity.request(attributes: attributes, contentState: state)
            return activity.id
        } catch {
            print("LiveActivity启动失败: \(error.localizedDescription)")
            return nil
        }
    }
    
    @objc static func updateLiveActivity(activityId: String, newProgress: String) {
        guard #available(iOS 16.1, *) else { return }
        
        Task {
            for activity in Activity<TaskAttributes>.activities where activity.id == activityId {
                await activity.update(using: TaskAttributes.TaskState(progress: newProgress))
            }
        }
    }
    
    @objc static func endLiveActivity(activityId: String) {
        guard #available(iOS 16.1, *) else { return }
        
        Task {
            for activity in Activity<TaskAttributes>.activities where activity.id == activityId {
                await activity.end(dismissalPolicy: .immediate)
            }
        }
    }
}

2. 配置Xcode桥接文件

确保Xcode生成了项目的桥接文件(通常命名为YourProject-Bridging-Header.h),如果没有,手动创建并在Build Settings中指定路径,然后添加:

#import <Foundation/Foundation.h>

@class LiveActivityManager;

3. 在Kotlin代码中调用Swift类

import platform.Foundation.NSString
import platform.objc.objc_getClass
import platform.objc.ObjCClass

fun startLiveActivity(title: String, progress: String): String? {
    val managerClass = objc_getClass("LiveActivityManager") as? ObjCClass
    return managerClass?.invokeStaticMethod(
        "startLiveActivity:progress:",
        title as NSString,
        progress as NSString
    ) as? String
}

fun updateLiveActivity(activityId: String, progress: String) {
    val managerClass = objc_getClass("LiveActivityManager") as? ObjCClass
    managerClass?.invokeStaticMethod(
        "updateLiveActivity:newProgress:",
        activityId as NSString,
        progress as NSString
    )
}

fun endLiveActivity(activityId: String) {
    val managerClass = objc_getClass("LiveActivityManager") as? ObjCClass
    managerClass?.invokeStaticMethod(
        "endLiveActivity:",
        activityId as NSString
    )
}

通用注意事项

  1. 确保iOS项目的Info.plist中添加LiveActivity权限:
<key>NSSupportsLiveActivities</key>
<true/>
  1. 必须在Xcode中创建Widget Extension来定义LiveActivity的UI布局,KMP暂不支持直接创建Widget扩展。
  2. 仅支持iOS 16.1及以上版本,调用前务必做版本判断。

内容的提问来源于stack exchange,提问作者吊霸天

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 08:48:24