Implementing LiveActivity
Some Limits
iOS 16.1 and above versions support;
LiveActivity can be retained for up to eight hours, and up to twelve hours on the lock screen;
Remote operation requires users to configure the p8 certificate;
The equipment only supports iPhone, and is the iPhone 14 Pro and 14 Pro Max with a "pill-shaped screen";
Access Guide
1.Add support configuration for Live Activities
Add the key-value: Supports Live Activities = YES in the Info.plist of the main program.
2.Create a WidgetExtension. If there is already one in the project, skip this step.


3.Code implementation
3.1 Implement Activity Attributes
The following implementation needs to implement the corresponding data model according to your own business. Among them, the data in ContentState can be dynamically updated. It is recommended to define activityID as the unique identifier of LiveActivity.
import Foundationimport ActivityKitstruct LiveActivityAttributes: ActivityAttributes {public struct ContentState: Codable, Hashable {// Dynamic stateful properties about your activity go here!var text: Stringvar pauseTime: Date?var endTime: Date?}// Fixed non-changing properties about your activity go here!// custom activityID when creating a LiveActivityvar activityID: String}
3.2 Create UI
Please write the specific UI according to your own business. It contains the definitions of Lock Screen UI and Dynamic Island UI.
import ActivityKitimport WidgetKitimport SwiftUIstruct LiveActivityLiveActivity: Widget {var body: some WidgetConfiguration {ActivityConfiguration(for: LiveActivityAttributes.self) { context in// Lock screen/banner UI goes hereVStack {Text("Hello \(context.state.text)")}.activityBackgroundTint(Color.cyan).activitySystemActionForegroundColor(Color.black)} dynamicIsland: { context inDynamicIsland {// Expanded UI goes here. Compose the expanded UI through// various regions, like leading/trailing/center/bottomDynamicIslandExpandedRegion(.leading) {Text("Leading \(context.attributes.activityID)\(context.state.text)")}DynamicIslandExpandedRegion(.trailing) {Text("Trailing \(context.state.text)")}DynamicIslandExpandedRegion(.center) {Text("Center \(context.state.text)")}DynamicIslandExpandedRegion(.bottom) {Text("Bottom \(context.state.text)")// more content}} compactLeading: {Text("CL \(context.state.text)")} compactTrailing: {Text("CT \(context.state.text)")} minimal: {Text("CB \(context.state.text)")}.widgetURL(URL(string: "https://cloud.tencent.com/document/product/269/100621")).keylineTint(Color.red)}}}
The layout definition of Dynamic Island UI is as follows:

3.3 Client Operation, Add Startup, Update and Stop Logic
// startlet activity = try Activity.request(attributes: adventure,content: .init(state: initialState, staleDate: nil),pushType: .token)// updateawait activity.update(ActivityContent<AdventureAttributes.ContentState>(state: contentState,staleDate: Date.now + 15,relevanceScore: alert ? 100 : 50),alertConfiguration: alertConfig)// endawait activity.end(ActivityContent(state: finalContent, staleDate: nil), dismissalPolicy: dismissalPolicy)
3.4 Remote Reporting Configuration and Update Operation
Listen for token updates and report
Task {for await pushToken in activity.pushTokenUpdates {let pushTokenString = pushToken.hexadecimalStringLogger().debug("New push token: \(pushTokenString)")try await self.setLiveActivity(activityID:activity.attributes.activityID, pushToken: pushToken)}}func setLiveActivity(activityID: String, pushToken: Data) async throws {var _apnsConfig = ImSDK_Plus.V2TIMLiveActivityConfig()_apnsConfig.businessID = xxxx_apnsConfig.token = pushToken_apnsConfig.activityID = activityIDos_log("%@", type: .debug, "setLiveActivity activityID: \(activityID)\ntoken:\(pushToken.hexadecimalString)")ImSDK_Plus.V2TIMManager.sharedInstance().setLiveActivity(_apnsConfig, succ: {print("setLiveActivity succ")}, fail: {code, desc inprint("setLiveActivity fail, \(code), \(desc)")})}
Submit the cleaning of LiveActivity
func clearActivity(activityID: String) async throws {os_log("clearActivity ID: \(activityID)")ImSDK_Plus.V2TIMManager.sharedInstance().setLiveActivity(nil, succ: {print("clearActivity succ")}, fail: {code, desc inprint("clearActivity fail, \(code), \(desc)")})}
Update and disable IOS real-time activity on the server side
Notes:
1. Push restrictions for LiveActivity. The P8 certificate, p8 certificate, must be configured.
2. If the recipient does not report the corresponding activityID, it will automatically downgrade to a normal notification push.
Format description of the JSON Object corresponding to ApnsInfo.LiveActivity
Field Name | Type | Option | Field description |
LaId | string | Required | The flag of the real-time activity that needs to be pushed corresponds to the client activityID. The length does not exceed 64 bytes. |
Event | string | Required | update a policy Query an instance Reset the access password of an instance |
ContentState | JSON Object | Required | Custom key: value object. It needs to match the client SDK value. Corresponding apns official document: Starting and updating Live Activities with ActivityKit push notifications | Apple Developer Documentation. |
DismissalDate | Integer | Optional. | The uinx Time when the lock screen real-time activity ends if the event is end. If not filled in, it defaults to the current time, and the lock screen will end soon. |
Request sample:
Omitted or unlisted parameters in the example, refer to the documentation: Single chat, Wholesale chat, related to offlinePushInfo.
{"MsgBody": [...] // Relevant description here for MsgBody"OfflinePushInfo": {"PushFlag": 0,"Title": "Offline Push Title""Desc": "Offline push content""Ext": "{\"entity\":{\"k1\":\"v1\",\"k2\":\"v2\"}}", // custom passthrough field, use string in json format for push"ApnsInfo": {"LiveActivity": {"LaId": "timpush","Event": "update", // update LA"ContentState": {"k1": v1,"k2": v2,...}}},"AndroidInfo": {... // Related reference of AndroidInfo in official website document}}}
{"MsgBody": [...] // Relevant description here for MsgBody"OfflinePushInfo": {"PushFlag": 0,"Title": "Offline Push Title""Desc": "Offline push content""Ext": "{\"entity\":{\"k1\":\"v1\",\"k2\":\"v2\"}}", // custom passthrough field, use string in json format for push"ApnsInfo": {"LiveActivity": {"LaId": "timpush","Event": "end", // end LA"ContentState": {"k1": v1,"k2": v2,...},"DismissalDate": 1739502750}},"AndroidInfo": {... // Related reference of AndroidInfo in official website document}}}