// // AppDelegate.swift // JJUNGTABLE // // Created by Sean Kim on 10/26/23. // import UIKit import SwiftUI import Combine import UserNotifications import Firebase import FirebaseMessaging import KakaoSDKCommon @main class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate, MessagingDelegate{ var viewModel = ViewModel() private var cancellables = Set() private var version: [Version] = [] private let gcmMessageIDKey = "gcm.message_id" // private var cancellables = Set() // private var versions: [Version] = [] func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) } func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) { } private func checkVersion() { API.shared.readData(path: "/db/version/read", queryItems: [URLQueryItem(name: "os_type", value: "I")]) .sink { completion in switch completion { case .finished: printLog(self.version) //현재 버전이 업데이트 버전보다 OOO 하다 switch compareVersion(currentVersion(), self.version[0].update_ver) { case .bigger: self.viewModel.isUpdate = "N" case .smaller, .equal: self.viewModel.isUpdate = "Y" case .error: self.viewModel.alertData = self.viewModel.systemErrorAlert() self.viewModel.showAlert.toggle() } switch compareVersion(currentVersion(), self.version[0].final_ver) { case .bigger, .equal: // 현재 버전이 스토어 버전보다 높거나 같을 같을 떄 - 이상 x break case .smaller: let choice = self.version[0].update_choice == "Y" ? true : false switch compareVersion(currentVersion(), self.version[0].force_ver) { case .bigger, .equal: // 현재 버전이 강업보다 높다 if !choice { break // 업데이트를 안내할 필요 없음 } else { self.viewModel.alertData = .init(title: "업데이트 안내", body: """ 앱 최신 버전이 새로 나왔습니다. 지금 업데이트 하시겠어요? """, button: [ButtonType(name: "지금 업데이트", role: .cancel , function: {exit(1)}), ButtonType(name: "나중에", role: .none , function: nil), ]) self.viewModel.showAlert.toggle() } case .smaller: // 현재 버전이 강업보다 닞다 -> 강업을 해야 한다. self.viewModel.alertData = .init(title: "업데이트 안내", body: """ 시스템이 제대로 동작하지 못했습니다. 앱을 종료후 다시 실행해주세요. """, button: [ButtonType(name: "지금 업데이트", role: .none, function: {exit(1)})]) self.viewModel.showAlert.toggle() case .error: self.viewModel.alertData = self.viewModel.systemErrorAlert() self.viewModel.showAlert.toggle() } case .error: self.viewModel.alertData = self.viewModel.systemErrorAlert() self.viewModel.showAlert.toggle() } // 버전 비교 처리 case .failure(let error): printLog(error) self.viewModel.alertData = self.viewModel.systemErrorAlert() self.viewModel.showAlert.toggle() } } receiveValue: { data in do { let decoder = JSONDecoder() self.version = try decoder.decode([Version].self, from: data) } catch { printLog(error) self.viewModel.alertData = self.viewModel.systemErrorAlert() self.viewModel.showAlert.toggle() } } .store(in: &cancellables) } } // MARK: - 기초 셋업 extension AppDelegate { func application(_ application: UIApplication,didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool { printLog("Start Set AppDelegate") if isIllegalDevice() { viewModel.alertData = .init(title:"경고", body: """ 변경된 OS('탈옥'등)의 스마트폰은 서비스를 이용할수 없습니다. """, button: [ButtonType(name: "확인", role: .none , function: {exit(1)})]) viewModel.showAlert.toggle() } else { checkVersion() // Firebase 설정 FirebaseApp.configure() // App Check 설정 // AppCheck.setAppCheckProviderFactory(AppCheckDebugProviderFactory()) // 카카오 SDK 초기화 코드 KakaoSDK.initSDK(appKey: KEY.kakaoAppKey) #if FCM // FCM 설정 Messaging.messaging().delegate = self #endif // Noti 설정 UNUserNotificationCenter.current().delegate = self let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound] UNUserNotificationCenter.current().requestAuthorization(options: authOptions) { granted, error in if let error = error { printLog("Authorization error: \(error.localizedDescription)") } if granted { DispatchQueue.main.async { UIApplication.shared.registerForRemoteNotifications() } } else { printLog("Notification permission denied.") } } application.registerForRemoteNotifications() UIApplication.shared.registerForRemoteNotifications() // 네트워크 모니터 초기화 _ = NetworkMonitor.shared } printLog("End Set AppDelegate") return true } func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) { } } extension AppDelegate { // 24.05.30 (수정완) - 앱이 원격 푸시 알림 등록을 성공적으로 마친 후 호출 func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) { // 파이어 베이스 SMS 하려고 하는 세팅 Auth.auth().setAPNSToken(deviceToken, type: .unknown) printLog("원격 푸시 알림 등록 성공 ") let deviceTokenString = deviceToken.reduce("", {$0 + String(format: "%02.2hX", $1)}) viewModel.deviceToken = deviceTokenString // Firebase에 디바이스 토큰 등록 Messaging.messaging().apnsToken = deviceToken printLog("DeviceToken: \(viewModel.deviceToken)") } // 24.05.30 (수정완) - 초기 FCM토큰 등록 func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) { @UserDefault (key: "isRegisterToken", defaultValue: "F") var isRegisterToken printLog("토큰 등록 동작 시작") guard let fcmToken = fcmToken else { return } viewModel.pushFCMToken = fcmToken Task { if isRegisterToken == "F" { // switch await FB_CRUD.shared.create("Token", doc: "\(viewModel.deviceToken)", // data: ["fcmToken":"\(viewModel.pushFCMToken)"]) { // case .success(_): // viewModel.pushFCMToken = fcmToken // isRegisterToken = "T" // printLog("초기 토큰 등록 성공") // case .failure(let error): // isRegisterToken = "F" // viewModel.alertData = .init(body:""" // 시스템이 제대로 동작하지 못했습니다. // 앱을 종료후 다시 실행해주세요. // """, // button: [ButtonType(name: "종료", role: .destructive ,function: {exit(1)})]) // viewModel.showAlert.toggle() // printLog("초기 토큰 등록 실패") // } } else { // if viewModel.pushFCMToken != fcmToken { // switch await FB_CRUD.shared.update("Token", doc: "\(viewModel.deviceToken)", // data: ["fcmToken":"\(viewModel.pushFCMToken)"]) { // case .success(_): // viewModel.pushFCMToken = fcmToken // isRegisterToken = "T" // printLog("토큰 재등록 성공") // case .failure(_): // viewModel.alertData = .init(body:""" // 시스템이 제대로 동작하지 못했습니다. // 앱을 종료후 다시 실행해주세요. // """, // button: [ButtonType(name: "종료", role: .destructive ,function: {exit(1)})]) // viewModel.showAlert.toggle() // printLog("토큰 재등록 실패") // } // } } printLog("FCM Token: \(viewModel.pushFCMToken)") } } // 앱 켜져있을때 알럿 받으면 func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification) async -> UNNotificationPresentationOptions { let userInfo = notification.request.content.userInfo //파이어 베이스 SMS 수신설정 부 if Auth.auth().canHandleNotification(userInfo) { return [] } if let apsData = userInfo["aps"] as? [AnyHashable: Any], let messageId = userInfo["gcm.message_id"] as? String, let badge = apsData["badge"] as? Int { // switch await FB_CRUD.shared.read("Users", doc: "\(viewModel.userId)") { // case .success(let data): // if var noReadList = data["noReadAlert"] as? [String] { // noReadList.append(messageId) // viewModel.noReadAlertList = noReadList // switch await FB_CRUD.shared.update("Users", doc: "\(viewModel.userId)", // data: ["noReadAlert":noReadList]) { // case .success(let data): // await viewModel.setBadge() // case .failure(let gg): // printLog(noReadList) // } // printLog(viewModel.noReadAlertList) // printLog(viewModel.noReadAlertList.count) // // } // case .failure(let failure): // printLog(failure) // } } Messaging.messaging().appDidReceiveMessage(userInfo) if #available(iOS 14.0, *) { return [[.list,.banner,.sound]] } else { return[[.alert,.sound]] } } // Background 상태에서 수신 받은 Notification을 터치해 앱으로 진입했을 때 호출 func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse) { printLog("ININININININi") let userInfo = response.notification.request.content.userInfo //파이어 베이스 SMS 수신설정 부 if Auth.auth().canHandleNotification(userInfo) { return } if let apsData = userInfo["aps"] as? [AnyHashable: Any] { if let alert = apsData["alert"] as? [AnyHashable: Any], let messageKey = apsData[gcmMessageIDKey] as? String { printLog("apsData: \(apsData)") printLog("alert: \(alert)") printLog("key: \(messageKey)") if let param = alert["parameter"] { printLog(param as? String) } // viewModel.setBadge() } } } func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) { // 파이어 베이스 SMS 설정부 if Auth.auth().canHandleNotification(userInfo) { completionHandler(.noData) return } // printLog("Back = \(userInfo)") // FB_CRUD.shared.sendPushNotification("확인", body: "확인") // @UserDefault (key: "fcmToken", defaultValue: "") var pushFCMToken // @UserDefault (key: "userId", defaultValue: "") var userId // @UserDefault (key: "noReadAlertList", defaultValue: [""]) var noReadAlertList // // let userInfo = notification.request.content.userInfo // // if let apsData = userInfo["aps"] as? [AnyHashable: Any], // let messageId = userInfo["gcm.message_id"] as? String, // let badge = apsData["badge"] as? Int { // // switch await FB_CRUD.shared.read("Users", doc: "\(userId)") { // case .success(let data): // printLog(data) // if var noReadList = data["noReadAlert"] as? [String] { // noReadList.append(messageId) // noReadAlertList = noReadList // await FB_CRUD.shared.update("Users", doc: "\(userId)", // data: ["noReadAlert":noReadList]) // printLog(noReadList) // printLog(noReadAlertList) // printLog(noReadAlertList.count) // await viewModel.setBadge(badge: noReadAlertList.count) // } // case .failure(let failure): // printLog(failure) // } // // } } }