如何在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 ) }
通用注意事项
- 确保iOS项目的
Info.plist中添加LiveActivity权限:
<key>NSSupportsLiveActivities</key> <true/>
- 必须在Xcode中创建Widget Extension来定义LiveActivity的UI布局,KMP暂不支持直接创建Widget扩展。
- 仅支持iOS 16.1及以上版本,调用前务必做版本判断。
内容的提问来源于stack exchange,提问作者吊霸天
相关产品推荐
相关产品推荐

