iOS16.1系统开始正式支持实时活动,更新Xcode为最新的14.1版本,(跟着官方文档步骤)开始着手开发
提示:项目是OC项目,且这次实时活动用到了用到远程推送
1.新建OC项目,Info-Plist文件加入Bool类型的权限key值为:Supports Live Activities value为:YES
2.如果项目之前有过小组件,则不需要再创建新的Widget-Extension,直接在@main WidgetBundle里面添加要创建的Live-Activity组件即可(我们在后面添加)
3.(我是OC项目)在主项目里面新建一个MyLiveActivityAttributes.swift
struct MyLiveActivityAttributes: ActivityAttributes {
typealias EasyDriveOrderState = ContentState
public struct ContentState: Codable, Hashable {
var orderId: Int?
var subOrderType: Int?
var status: Int?
var startTime: String?
var endTime: String?
var startCode: Int?
var studentName: String?
var studentAvatar: String?
var userName: String?
var userAvatar: String?
var courseName: String?
var isSendToken: Int?
var lessonLeftTime:Int?
var isMicrophonePermissionGranted: Int?
}
var contentState: ContentState
init(MyOrderData: MyOrderData) {
self.contentState = ContentState(
orderId: MyOrderData.orderId,
subOrderType: MyOrderData.subOrderType,
status: MyOrderData.status,
startTime: MyOrderData.startTime,
endTime: MyOrderData.endTime,
startCode: MyOrderData.startCode,
studentName: MyOrderData.studentName,
studentAvatar: MyOrderData.studentAvatar,
userName: MyOrderData.userName,
userAvatar: MyOrderData.userAvatar,
courseName: MyOrderData.courseName,
isSendToken: MyOrderData.isSendToken,
lessonLeftTime: MyOrderData.lessonLeftTime,
)
}
}
struct MyOrderData: Codable {
let orderId: Int?
let subOrderType: Int?
let status: Int?
let startTime: String?
let endTime: String?
let startCode: Int?
let studentName: String?
let studentAvatar: String?
let userName: String?
let userAvatar: String?
let courseName: String?
let isSendToken: Int?
let lessonLeftTime: Int?
enum CodingKeys: String, CodingKey {
case orderId = "order_id"
case subOrderType = "sub_order_type"
case status = "status"
case startTime = "start_time"
case endTime = "end_time"
case startCode = "start_code"
case studentName = "student_name"
case studentAvatar = "student_avatar"
case userName = "user_name"
case userAvatar = "user_avatar"
case courseName = "course_name"
case isSendToken = "is_send_token"
case lessonLeftTime = "lesson_left_time"
}
}
func parseMyOrderData(jsonData: Data) -> MyOrderData? {
let decoder = JSONDecoder()
do {
let MyOrderData = try decoder.decode(MyOrderData.self, from: jsonData)
return MyOrderData
} catch {
print("Error decoding JSON: \(error)")
return nil
}
}
4.(我是OC项目)在主项目里面新建一个MyLiveActivityManager.swift
自动生成OC Swift 桥接文件
@available(iOS 16.1, *)
@objcMembers
class MyLiveActivityManager: NSObject {
static let shared = MyLiveActivityManager()
private override init() { }
var liveActivity: Activity<CoachLiveActivityAttributes>?
var isActivityRunning = false
@available(iOS 16.1, *)
func startLiveActivity(data: [String: Any], completion: @escaping (String?) -> Void) async {
guard let jsonData = try? JSONSerialization.data(withJSONObject: data, options: []),
let orderData = parseOrderData(jsonData: jsonData) else {
print("Missing or invalid arguments")
completion(nil)
return
}
if(self.isActivityRunning || Activity<CoachLiveActivityAttributes>.activities.count > 0){
print("count=====\(Activity<CoachLiveActivityAttributes>.activities.count)")
print("Activity updateLiveActivity 内 \(data)")
self.updateLiveActivity(data: data)
}else{
let attributes = CoachLiveActivityAttributes(orderData: orderData)
do {
print("Activity startLiveActivity 内\(data)")
let activity = try Activity.request(attributes: attributes, contentState: attributes.contentState, pushType: .token)
self.liveActivity = activity
self.isActivityRunning = true
Task {
do {
print("Activity request========")
获取Token 给后台实时推送
if let pushTokenUpdates = self.liveActivity?.pushTokenUpdates {
for await data in pushTokenUpdates {
let token = data.map { String(format: "%02x", $0) }.joined()
print("Received push token: \(token)")
completion(token)
return
}
}
} catch {
completion("")
}
}
Task {
for await state in activity.activityStateUpdates {
if (state == .active) {
/// The Live Activity is active, visible to the user, and can receive content updates.
print("device-----活动active")
isActivityRunning = true
} else if (state == .ended) {
print("device-----活动ended")
isActivityRunning = false
/// The Live Activity is visible, but the user, app, or system ended it, and it won't update its content anymore.
} else { // .dismissed
/// The Live Activity ended and is no longer visible because the user or the system removed it.
print("device-----活动dismissed")
isActivityRunning = false
}
}
}
} catch let error {
print("can't launch live activity: \(error.localizedDescription)")
completion("")
}
}
}
func updateLiveActivity(data: [String: Any]) -> Bool {
guard let jsonData = try? JSONSerialization.data(withJSONObject: data, options: []),
let orderData = parseOrderData(jsonData: jsonData) else {
print("Missing or invalid arguments")
return false
}
let attributes = CoachLiveActivityAttributes(orderData: orderData)
print("Activity updateLiveActivity 内\(data)")
Task {
do {
await liveActivity?.update(using: attributes.contentState)
print("Activity updated successfully")
return true
} catch {
print("Failed to update live activity: \(error)")
return false
}
}
return false
}
func endLiveActivity(data: [String: Any], completion: @escaping (Bool) -> Void) {
guard let jsonData = try? JSONSerialization.data(withJSONObject: data, options: []),
let orderData = parseOrderData(jsonData: jsonData) else {
print("Missing or invalid arguments")
completion(false)
return
}
let attributes = CoachLiveActivityAttributes(orderData: orderData)
Task {
do {
await liveActivity?.end(using: attributes.contentState, dismissalPolicy: .immediate)
self.isActivityRunning = false;
print("Activity ended successfully")
completion(true)
} catch {
print("Failed to end live activity: \(error)")
completion(false)
}
}
}
func isLiveActivitySupported() -> Bool {
return ActivityAuthorizationInfo().areActivitiesEnabled
}
}
5.(我是OC项目)AppDelegate 调用
[[MyLiveActivityManager shared]startLiveActivityWithData:args completion:^(NSString * token) {
if (token) {
result(token);
} else {
result(@"");
}
} completionHandler:^{
}];
效果如上图完美避坑。