WatchAppDelegate.swift
4.02 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
//
// WatchAppDelegate.swift
// Runner Watch App
//
// Created by 权海 on 2026/6/17.
//
import WatchKit
import UserNotifications
@MainActor
final class WatchAppDelegate: NSObject, WKApplicationDelegate, UNUserNotificationCenterDelegate {
private enum HealthAuthorizationState {
case notRequested
case requesting
case completed
}
private var healthAuthorizationState: HealthAuthorizationState = .notRequested
func applicationDidFinishLaunching() {
setup()
let center = UNUserNotificationCenter.current()
center.delegate = self
requestNotificationPermission()
}
private func setup(){
WatchUserAgent.share.genUA()
WatchSessionManager.share.addListen()
WatchUserinfoManager.share.setup()
requestHealthAuthorizationIfNeeded()
}
func sceneDidBecomeActive() {
switch healthAuthorizationState {
case .completed:
// Local HealthKit reads and observer registration never depend on
// login state. Upload methods perform their own token check.
WatchHealthWidgetRefreshCoordinator.shared.refreshAll()
WatchHealthObserverUploader.shared.startObserversIfNeeded()
WatchHealthObserverUploader.shared.performFullUpload()
case .notRequested:
requestHealthAuthorizationIfNeeded()
case .requesting:
// The completion below will refresh data and start observers.
break
}
}
private func requestHealthAuthorizationIfNeeded() {
guard case .notRequested = healthAuthorizationState else { return }
healthAuthorizationState = .requesting
WatchDataManager.share.requestAuthForHealth { [weak self] success in
guard let self else { return }
if !success {
self.healthAuthorizationState = .notRequested
return
}
self.healthAuthorizationState = .completed
WatchDataManager.share.fetchMyTodayData()
WatchDataManager.share.getLatestHealthData()
WatchDataManager.share.getAcitivtyTarget()
// Register observers only after the authorization request has
// completed. Registering earlier can make background delivery fail
// permanently for this process.
WatchHealthObserverUploader.shared.startObserversIfNeeded()
WatchHealthObserverUploader.shared.performFullUpload()
}
}
private func requestNotificationPermission() {
UNUserNotificationCenter.current().requestAuthorization(
options: [.alert, .sound, .badge]
) { granted, error in
guard granted else { return }
DispatchQueue.main.async {
WKApplication.shared().registerForRemoteNotifications()
}
}
}
func didRegisterForRemoteNotifications(withDeviceToken deviceToken: Data) {
let token = deviceToken.map { String(format: "%02x", $0) }.joined()
AppGroupConstants.defaults?.set(token, forKey: AppGroupConstants.Key.watchDeviceToken)
Task{
await UserInfoService().uploadDeviceInfo()
}
}
func didFailToRegisterForRemoteNotificationsWithError(_ error: Error) {
}
// App 在前台收到通知:热启动前台展示
func userNotificationCenter(
_ center: UNUserNotificationCenter,
willPresent notification: UNNotification
) async -> UNNotificationPresentationOptions {
let userInfo = notification.request.content.userInfo
print("watch will present:", userInfo)
return [.banner, .sound]
}
// 用户点击通知:冷启动 / 后台 / 前台都走这里
func userNotificationCenter(
_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse
) async {
let userInfo = response.notification.request.content.userInfo
print("watch notification clicked:", userInfo)
WatchNotificationRouter.shared.handle(userInfo: userInfo)
}
}