Live Activities
Integrate Live Activities into your Unity app to display real-time updates on the iOS Lock Screen and Dynamic Island. AXP
Live Activities are an iOS-only feature. The liveActivityManager module is a no-op on Android.
The Live Activity APIs require iOS 16.1 or later. On earlier versions, each call fails and reports the error to the onError callback.
For the push API method, see the iOS Live Activities messaging guide. See also the iOS Live Activities feature guide.
App setup
Live Activities require native iOS setup that Unity does not generate. After exporting the Xcode project, add a widget extension that defines your ActivityAttributes, then register each Live Activity type with Airship using a plugin extender.
Using the plugin extender, call LiveActivityManager.shared.setup from onAirshipReady to configure your Live Activities. Call configurator.register for each Live Activity type that your app defines, and include a block that returns the property Airship uses to track the activity. This name is used to send updates through APNs.
import Foundation
import AirshipKit
import AirshipFrameworkProxy
import ActivityKit
// This class header is required to be automatically picked up by the Airship plugin:
@objc(AirshipPluginExtender)
public class AirshipPluginExtender: NSObject, AirshipPluginExtenderProtocol {
public static func onAirshipReady() {
if #available(iOS 16.1, *) {
// Will throw if called more than once
try? LiveActivityManager.shared.setup { configurator in
// Call for each Live Activity type
await configurator.register(forType: Activity<SportsActivityAttributes>.self) { attributes in
// Track this property as the Airship name for updates
attributes.gameID
}
}
}
// other setup
}
}Because Unity regenerates the Xcode project on a clean build, the widget extension and the extender must be reapplied, or scripted as a post-build step, whenever the project is regenerated.
Starting Live Activities
Start a Live Activity with the Start coroutine. The attributesType must match the ActivityAttributes type defined in your widget extension.
StartCoroutine(Airship.Shared.liveActivityManager.Start(
new LiveActivityStartRequest() {
attributesType = "SportsActivityAttributes",
content = new LiveActivityContent() {
state = new Dictionary<string, object>() {
{ "status", "Game Pending" },
},
relevanceScore = 0.0,
},
attributes = new Dictionary<string, object>() {
{ "gameID", "sports-game-123" },
},
},
(LiveActivityInfo info) => {
Debug.Log("Started Live Activity: " + info.id);
},
(System.Exception error) => {
Debug.LogError("Failed to start Live Activity: " + error.Message);
}
));Each method takes an optional onError callback. Pass one to catch failures such as running on iOS 16.0, where the Live Activity APIs are unavailable.
Updating Live Activities
To update a Live Activity, you need its activity ID. Use ListAll to find it.
StartCoroutine(Airship.Shared.liveActivityManager.ListAll((LiveActivityInfo[] activities) => {
foreach (LiveActivityInfo activity in activities) {
StartCoroutine(Airship.Shared.liveActivityManager.Update(new LiveActivityUpdateRequest() {
activityId = activity.id,
content = new LiveActivityContent() {
state = new Dictionary<string, object>() {
{ "status", "Game starting!" },
},
relevanceScore = 0.0,
},
}));
}
}));Ending Live Activities
End a Live Activity with the End coroutine and the activity ID. As with Update, use ListAll to find the ID.
string liveActivityId = "<ACTIVITY_ID>";
StartCoroutine(Airship.Shared.liveActivityManager.End(new LiveActivityEndRequest() {
activityId = liveActivityId,
dismissalPolicy = new LiveActivityDismissalPolicy() {
type = "default",
},
}));The dismissal policy type accepts immediate, default, or after. The after policy also requires an ISO 8601 date, set through the date field on LiveActivityDismissalPolicy.