Using Live Activities in a Kotlin Multiplatform (KMP) iOS project requires bridging native Swift/Objective-C APIs with KMP. Since Live Activities are an iOS-specific feature introduced in iOS 16.1 via ActivityKit, they are not directly available in Kotlin. However, you can interact with them via expect/actual declarations or platform-specific Swift code.
Here’s how to approach this
kotlin {
iosX64()
iosArm64()
iosSimulatorArm64()
sourceSets {
val iosMain by getting {
dependencies {
// your iOS-specific dependencies
}
}
}
}
2. Create Swift Code for Live Activities
Create a Swift file in the iosApp module (or your iOS target module):
swift
Copy code
import ActivityKit
struct LiveActivityManager {
static func startActivity(content: String) {
if ActivityAuthorizationInfo().areActivitiesEnabled {
let attributes = MyActivityAttributes(name: content)
let contentState = MyActivityAttributes.ContentState(value: 0)
do {
let \_ = try Activity\<MyActivityAttributes\>.request(attributes: attributes, contentState: contentState)
} catch {
print("Error starting activity: \\(error)")
}
}
}
static func updateActivity(activityID: String, value: Int) {
Task {
let updatedState = MyActivityAttributes.ContentState(value: value)
for activity in Activity\<MyActivityAttributes\>.activities {
if activity.id == activityID {
await activity.update(using: updatedState)
}
}
}
}
}
Define your attributes:
swift
Copy code
struct MyActivityAttributes: ActivityAttributes {
public struct ContentState: Codable, Hashable {
var value: Int
}
var name: String
}
3. Expose Swift Code to Kotlin
Use an Objective-C bridging header or expose Swift to Kotlin via a wrapper:
a. Mark Swift functions with @objc and use a class:
swift
Copy code
@objc class LiveActivityWrapper: NSObject {
@objc static func startActivity(withContent content: String) {
LiveActivityManager.startActivity(content: content)
}
}
b. Add to Bridging Header (if needed):
objc
Copy code
#import "YourAppName-Swift.h"
4. Call iOS-specific Code from Kotlin
Use Platform-specific implementation in Kotlin:
commonMain
kotlin
Copy code
expect fun startLiveActivity(content: String)
iosMain
kotlin
Copy code
actual fun startLiveActivity(content: String) {
LiveActivityWrapper.startActivity(withContent = content)
}
5. Use It in Shared Code
Now you can call startLiveActivity("MyContent") from shared code and have it trigger Live Activities on iOS.
Notes:
Ensure your iOS app has appropriate entitlements (com.apple.developer.activitykit) and runs on iOS 16.1+.
Live Activities only work on real devices, not on the iOS Simulator.
You might need to configure Info.plist for widget support if using Dynamickotlin {
iosX64()
iosArm64()
iosSimulatorArm64()
sourceSets {
val iosMain by getting {
dependencies {
// your iOS-specific dependencies
}
}
}
}
2. Create Swift Code for Live Activities
Create a Swift file in the iosApp module (or your iOS target module):
swift
Copy code
import ActivityKit
struct LiveActivityManager {
static func startActivity(content: String) {
if ActivityAuthorizationInfo().areActivitiesEnabled {
let attributes = MyActivityAttributes(name: content)
let contentState = MyActivityAttributes.ContentState(value: 0)
do {
let \_ = try Activity\<MyActivityAttributes\>.request(attributes: attributes, contentState: contentState)
} catch {
print("Error starting activity: \\(error)")
}
}
}
static func updateActivity(activityID: String, value: Int) {
Task {
let updatedState = MyActivityAttributes.ContentState(value: value)
for activity in Activity\<MyActivityAttributes\>.activities {
if activity.id == activityID {
await activity.update(using: updatedState)
}
}
}
}
}
Define your attributes:
swift
Copy code
struct MyActivityAttributes: ActivityAttributes {
public struct ContentState: Codable, Hashable {
var value: Int
}
var name: String
}
3. Expose Swift Code to Kotlin
Use an Objective-C bridging header or expose Swift to Kotlin via a wrapper:
a. Mark Swift functions with @objc and use a class:
swift
Copy code
@objc class LiveActivityWrapper: NSObject {
@objc static func startActivity(withContent content: String) {
LiveActivityManager.startActivity(content: content)
}
}
b. Add to Bridging Header (if needed):
objc
Copy code
#import "YourAppName-Swift.h"
4. Call iOS-specific Code from Kotlin
Use Platform-specific implementation in Kotlin:
commonMain
kotlin
Copy code
expect fun startLiveActivity(content: String)
iosMain
kotlin
Copy code
actual fun startLiveActivity(content: String) {
LiveActivityWrapper.startActivity(withContent = content)
}
5. Use It in Shared Code
Now you can call startLiveActivity("MyContent") from shared code and have it trigger Live Activities on iOS.
Notes:
Ensure your iOS app has appropriate entitlements (com.apple.developer.activitykit) and runs on iOS 16.1+.
Live Activities only work on real devices, not on the iOS Simulator.
You might need to configure Info.plist for widget support if using Dynamic Island or Lock Screen widgets.
Let me know if you want a working example or GitHub template! Island or Lock Screen widgets.
Let me know if you want a working example or GitHub template!