-
iOS 푸시 랜딩 (active, inactive, background)Language/iOS,AOS 2023. 3. 1. 18:19
사용자 단말기에서 푸시 메세지를 받고, 터치해서 원하는 페이지로 이동하는 방식에 대해서 정리해 두자!
필자는 웹뷰를 사용하고 있으니 처리방식에 참고 바랍니다.
푸시 알림 설정은 아래 포스팅을 참고 부탁드립니다.
https://dchkang83.tistory.com/150
푸시 알림 핸들링
푸시 알림 핸들링 고려사항 2가지
- 푸시 메시지 받았을때
- 푸시 메시지 클릭했을때
1. 푸시 알림 받았을때
푸시 알림을 수신 받게 되면 해당 메소드가 실행됩니다.
extension AppDelegate: UNUserNotificationCenterDelegate { ... public func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) { ... // 푸시 메시지 받았을때 let userInfo = notification.request.content.userInfo; Utils.Log("######### userNotificationCenter willPresent : \(userInfo)") ... } ... }
2. 푸시 알림 클릭했을때
푸시 알림을 클릭 후 고려해야 할 상황은 3가지입니다.
- 앱이 활성화 상태에서 알림 클릭 (active)
- 앱이 비활성화 상태에서 알림 클릭 (inactive)
- 앱이 종료되어 있는 상태에서 알림 클릭 (background)
이벤트 핸들링
사용자가 푸시알림을 선택하게 되면 userNotificationCenter의 didReceive의 함수가 호출되게 되는데 해당 함수에서 UIApplication.shared.applicationState의 3가지 타입인 active, inactive, background 상태에 따라서 현재 앱이 종료되어 있는지, 활성화/비활성화 상태를 판단할 수 있습니다.
extension AppDelegate: UNUserNotificationCenterDelegate { ... public func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) { ... let userInfo = response.notification.request.content.userInfo let application = UIApplication.shared switch application.applicationState { case .active: NotificationCenter.default.post(name: Notification.Name("didReceivePushTouch"), object: nil, userInfo: userInfo) case .inactive: NotificationCenter.default.post(name: Notification.Name("didReceivePushTouch"), object: nil, userInfo: userInfo) case .background: guard let notiKey = userInfo["notiKey"]! as? String else { return } let userDefault = UserDefaults.standard userDefault.set(notiKey, forKey: "NOTIFICATION_KEY") userDefault.synchronize() default: Utils.Log("undefined applicationState") } ... } ... }
필자는 active, inactive 상태일 경우에는 observer를 설정해 두고 바로 처리하고, 앱이 꺼져있는 background 상태에서는 후처리해줄 ViewController가 존재하지 않아서 UserDefaults에 키를 담아뒀다가 앱이 실행되었을때 원하는 페이지로 이동 하거나 후처리하는 방식을 사용해 보았습니다.
active, inactive 방식
앱이 켜저 있는 상테임으로 웹뷰에 처리할 내용을 알려줄수 있습니다.
class MainViewController: BaseViewController { ... override func viewDidLoad() { super.viewDidLoad() NotificationCenter.default.addObserver(forName: Notification.Name("didReceivePushTouch"), object: nil, queue: nil) { notification in Utils.Log("Work Completed notification : \(notification)") guard let userInfo = notification.userInfo, let notiKey = userInfo["notiKey"]! as? String else { return } Utils.Log("Work Completed notiKey : \(notiKey)") // Value of type 'Notification' has no subscripts // self.executeJavasScript(wKWeb: self.wKMainWeb, callback: "window.setNotificationId('\(notiKey)')") } } ... }
background 방식 (앱이 완전이 꺼져 있는 상태에서 푸시 알림 클릭)
앱이 완전히 꺼져있는 상태에서 푸시 알림을 클릭하여 앱이 켜지는 부분이라서 웹뷰에 페이지 떠있는지도 알수가 없으니 푸시 클릭시에 UserDefaults에 푸시에 대한 키를 가지고 있고 앱이 완전히 켜진뒤 웹 사이트의 init 시점에 iOS앱에 푸시받은부분이 있는지 체크하는 식으로 처리하였습니다.
// MARK: - 웹 액션 - 정의 // WebAction을 구분하는데 사용되는 타입 enum WebAction: String { ... case getNotificationId ... } extension MainViewController: WKScriptMessageHandler { func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) { guard message.name == "IosBridge", let messages = message.body as? [String: Any], let action = messages["action"] as? String else { return } let webAction = WebAction(rawValue: action) Utils.Log("@@@@@@@@@@@@@@@@@@@@@@@ \(action) : \(message.body)") switch webAction { ... case .getNotificationId: guard let params: [String: Any] = messages["params"] as? [String: Any], let callback = params["callback"] as? String else { return } let userDefault = UserDefaults.standard let notiKey:String? = userDefault.string(forKey: "NOTIFICATION_KEY") // 링크가 있는 푸시를 클릭하는 경우에만 실행 if(notiKey != nil) { self.executeJavasScript(wKWeb: self.wKMainWeb, callback: "\(callback)('\(notiKey!)')") userDefault.removeObject(forKey: "NOTIFICATION_KEY") userDefault.synchronize() } ... default: Utils.Log("undefined action") } } }
짝짝짝!
iOS개발자가 아니라서 아직도 많이 헤메고 있지만 하이브리드앱 개발에 대한 방향성을 조금씩 알아 나가는거 같습니다.
나중에 다시만들면 더 좋게 만들겠지!! 아자아자 힘내자!
'Language > iOS,AOS' 카테고리의 다른 글
URI 스킴 적용 (URL Scheme) (0) 2023.03.06 Universal link 적용하기 (0) 2023.03.02 웹뷰 캐시 삭제 (0) 2023.03.01 scrollView 확대/축소 방법 (0) 2023.02.24 페이스북 간편 로그인 (0) 2023.02.23