푸시 랜딩


사용자 단말에서 푸시 메시지를 받고 터치로 원하는 페이지로 전환하는 방법을 정리해보자!

웹뷰를 사용하고 있으니 처리방법에 유의해주세요.

푸시 알림 설정에 대한 내용은 다음 게시물을 참조하세요.

https://dchkang83.150

Xcode Firebase 푸시 설정

Swift 기반 FCM(Firebase Cloud Messaging) 푸시 알림을 설정해 봅시다! 1. 기능 설정 배경 모드 추가 기능 -> “+” 추가 -> 배경 모드 추가 배경 모드 추가를 클릭하면 다음과 같이 표시됩니다. 저는 CHnage Al입니다.

dchkang83.tistory.com

푸시 알림 처리

푸시 알림 처리를 위한 두 가지 고려 사항

  1. 푸시 알림을 받았을 때
  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. 푸시 알림 클릭 시

푸시 알림을 클릭한 후 고려해야 할 세 가지 상황이 있습니다.

  • 앱이 활성(활성) 상태일 때 클릭 알림
  • 앱이 유휴(idle) 상태일 때 알림 클릭
  • 앱 종료 시 클릭 알림(백그라운드)

이벤트 처리

사용자가 푸시 알림을 선택하면 사용자 알림 센터 didReceive 함수이 함수에서 호출됩니다 세 가지 유형의 UIApplication.shared.applicationState사람 활성, 비활성, 백그라운드 상태에 따라 현재 앱이 종료되었는지 또는 활성화/비활성화되었는지 확인할 수 있습니다.

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")
        }
        
        ...
    }
    ...
}

활성 또는 비활성 상태에서 관찰자가 설정되고 즉시 처리됩니다.하다, 앱이 꺼져 있을 때의 백그라운드 상태사후 처리할 ViewController가 없기 때문에 UserDefaults에 키를 저장하고 앱 시작 또는 후처리 시 원하는 페이지로 전환이 방법을 시도했습니다.

활성, 비활성 방법

앱이 실행되는 동안 웹뷰에 무엇을 할지 알릴 수 있습니다.

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)')")
        }
    }
    ...
}

백그라운드 방식(앱이 완전히 비활성화되었을 때 푸시 알림 클릭)

앱이 완전히 비활성화된 상태에서 푸시 알림을 클릭하면 앱이 활성화되기 때문에 웹 보기에서 페이지가 떠 있는지 알 수 있는 방법이 없습니다. 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 개발자가 아니라서 아직 많이 헤매고 있지만 하이브리드 앱 개발의 방향성을 조금씩 알아가고 있는 것 같습니다.

나중에 또 하게 된다면 더 잘할게!! 최선을 다하자!