반응형
AppDelegate 메서드
IOS에서 앱의 실행상태가 변화할 때 앱 객체는 AppDelegate에 정의된 특정 메서드를 호출한다.
내부에서 적절한 메서드를 작성하여 포그라운드와 백그라운드시에 수신에 따른 적절한 처리를 해줄 수 있었다.
application; didFinishLaunchingWithOptions 메서드에서 firebase 세팅과 apns 등록을 해준다.
추가로 사일런트 푸시 처리 메서드쪽에서 백그라운드인경우 수신을 감지하여 적절한 처리를 해줄 수 있었다.
class AppDelegate: NSObject, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
FirebaseApp.configure()
// 원격알림 등록: 푸시든 로컬이든 알람 허용해야 그 이후에 가능
UNUserNotificationCenter.current().delegate = self
let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
UNUserNotificationCenter.current().requestAuthorization(
options: authOptions,
completionHandler: { _, _ in }
)
// APNs 등록
application.registerForRemoteNotifications()
// FirebaseMessaging
Messaging.messaging().delegate = self
return true
}
// 사일런트 푸시 처리 메소드
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any],
fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
if application.applicationState == .background {
// do tasks
UpboxFirebaseMessagingService.shared.handleFirebasePushNotification(userInfo: userInfo)
}
completionHandler(UIBackgroundFetchResult.newData)
}
func applicationDidBecomeActive(_ application: UIApplication) {
// 앱이 포그라운드로 돌아올 때 권한 체크
}
func applicationWillResignActive(_ application: UIApplication) {
// 앱이 활성 상태를 떠나기 직전에 호출됩니다.
}
func applicationDidEnterBackground(_ application: UIApplication) {
// 앱이 백그라운드 상태로 전환될 때 호출됩니다.
}
func applicationWillEnterForeground(_ application: UIApplication) {
// 앱이 백그라운드에서 포그라운드로 전환될 때 호출됩니다.
}
func applicationWillTerminate(_ application: UIApplication) {
// 앱이 종료될 때 호출됩니다.
}
func loadFCMToken() {
Messaging.messaging().token { token, error in
if let error = error {
print("Error fetching FCM registration token: \(error)")
} else if let token = token {
print("FCM registration token: \(token)")
UpboxFirebaseMessagingService.token = token
}
}
}
}
본인의 경우에는 웹뷰측에 푸시내용을 저장했어야 하는데, 포그라운드인 경우는 바로 웹뷰에 전달해주면 됐고
백그라운드인경우에는 DataModel에 저장만 하고, Resume시에 DataModel에 저장된 내용을 웹뷰에 전달하였다.
(Resume은 ContentView에서 .onChange(of: appStateObserver.isActive) 이벤트 내에서 처리했다.)
포그라운드 수신시에는 아래처럼 익스텐션으로 추가해주면 된다
extension AppDelegate : UNUserNotificationCenterDelegate {
// foreground에서 시스템 푸시를 수신했을 때 해당 메소드가 호출
func userNotificationCenter(_ center: UNUserNotificationCenter,
willPresent notification: UNNotification,
withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
let userInfo = notification.request.content.userInfo
if let title = userInfo["title"] as? String,
let body = userInfo["body"] as? String,
!title.isEmpty,
!body.isEmpty {
UpboxFirebaseMessagingService.shared.handleFirebasePushNotificationForeground(userInfo: userInfo)
}
let presentationOptions: UNNotificationPresentationOptions
if #available(iOS 14.0, *) {
presentationOptions = [.sound, .badge, .banner, .list]
} else {
presentationOptions = [.alert, .sound, .badge]
}
completionHandler(presentationOptions)
}
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
let tokenParts = deviceToken.map { data in String(format: "%02.2hhx", data) }
let token = tokenParts.joined()
print("Device Token: \(token)")
Messaging.messaging().apnsToken = deviceToken
}
}
extension AppDelegate: MessagingDelegate {
func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) {
print("Firebase registration token: \(String(describing: fcmToken))")
UpboxFirebaseMessagingService.token = fcmToken ?? ""
loadFCMToken()
}
}
참고로 push notification을 테스트 하기위해 사용한 FCM의 기존 HTTP API 전송예시는 다음과 같다. (이전 버전)
[POST] https://fcm.googleapis.com/fcm/send
[HEADER] Authorization: key=${서버 키 문자열}
{
"to": "테스트기기의 regist token",
"notification": {
"title": "표시될 푸시 타이틀",
"body": "표시될 푸시 내용"
},
"data": {
"title": "전송 데이터1",
"body": "전송 데이터2",
"notiType": "전송 데이터3",
"member": 7734,
"urn": "",
"param": ""
},
"priority": "high",
"content_available": true,
"apns": {
"payload": {
"aps": {
"content-available": 1
}
},
"headers": {
"apns-push-type": "background",
"apns-priority": "5"
}
}
}
반응형