【问题标题】:Swift iOS app receive push notification when app is inactive and run code当应用程序处于非活动状态并运行代码时,Swift iOS 应用程序会收到推送通知
【发布时间】:2020-05-15 19:09:01
【问题描述】:

平台

斯威夫特 5

iOS 13+

xCode 11

节点 v14.2.0

Firebase/Firestore 最新

设置

Alice 向 Bob 发送推送通知,而 Bob 的电话是 .inactive.background。 Bob 的手机应该会收到通知并立即触发代码。

问题

这个问题有很多答案,但我能找到的大部分内容都围绕着破解 PushKit 和 CallKit 原生 API 以发送 .voIP 推送。根据这个问题 (iOS 13 not getting VoIP Push Notifications in background),Apple 不再允许您发送 .voIP 推送而不触发 CallKit 的本机电话响铃例程。

在 iOS 端,我在 AppDelegate.swift 中有以下位

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        
        registerForPushNotifications()
 
    }
 
    func application(_ application: UIApplication,
                     didReceiveRemoteNotification userInfo: [AnyHashable: Any],
                     fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void)
    {
        
        print(">>> I would like this to be triggered even if the app is asleep")
        
        switch application.applicationState {
            case .active:
                print(">>>>>>> the app is in [FOREGROUND]: \(userInfo)")
                break
            case .inactive, .background:
                print(">>>>>>>> the app is in [BACKGROUND]: \(userInfo)")
                break
            default:
                break
        }
    }
    

    func registerForPushNotifications() {

        UNUserNotificationCenter.current().delegate = self
        
        UNUserNotificationCenter
            .current()
            .requestAuthorization(options:[.alert, .sound, .badge]) {[weak self] granted, error in
                guard granted else { return }
                self?.getNotificationSettings()
        }
    }
        
    func getNotificationSettings() {
    
        UNUserNotificationCenter.current().getNotificationSettings { settings in
            
            guard settings.authorizationStatus == .authorized else { return }
            
            Messaging.messaging().delegate = self

            DispatchQueue.main.async {
                // Register with Apple Push Notification service
                UIApplication.shared.registerForRemoteNotifications()
                
                /// cache token client side and save in `didRegisterForRemoteNotificationsWithDeviceToken`
                if let token = Messaging.messaging().fcmToken {
                    self.firebaseCloudMessagingToken = token
                }
            }
        }
    }
    
    //@Use: listen for device token and save it in DB, so notifications can be sent to this phone
    func application(_ application: UIApplication,
        didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        
        if (firebaseCloudMessagingToken != nil){
            self.updateMyUserData(
                  name   : nil
                , pushNotificationToken: firebaseCloudMessagingToken!
            )
        }
    }

    func application(_ application: UIApplication,
        didFailToRegisterForRemoteNotificationsWithError error: Error) {
        ///print(">>> Failed to register: \(error)")
    }


    @available(iOS 10.0, *)
    func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
        
        // @NOTE: this fires when the app is open. So you can go the call screen right away
        let payload = notification.request.content.userInfo as! [String:Any?]
        let type = payload["notificationType"]
        
        print(">> this fires if the app is currently open")

    }
    
    /// @NOTE: we are using backward compatible API to access user notification when the app is in the background
    /// @source: https://firebase.google.com/docs/cloud-messaging/ios/receive#swift:-ios-10
    @available(iOS 10.0, *)
    func userNotificationCenter(_ center: UNUserNotificationCenter,
                                    didReceive response: UNNotificationResponse,
                                    withCompletionHandler completionHandler: @escaping () -> Void) {

        print(" this fires when the user taps on the notification message")
    }

在服务器/Node.js 端,我以这种方式发送推送通知:

// Declare app push notification provider for PushKit
const _ApnConfig_ = {
    token: {
          key   : fileP8
        , keyId : "ABCDEFG"
        , teamId: "opqrst"
    },
    production: false
};
 
var apnProvider = new apn.Provider(_ApnConfig_);


exports.onSendNotification = functions.https.onRequest((request, response) => {

    var date = new Date();
    var timeStamp = date.getTime();

    const deviceTok = "..."

    var recepients = [apn.token( deviceTok )] 

    const notification = new apn.Notification();    
    notification.topic = "com.thisisnt.working"


    notification.body = "Hello, world!";    


    notification.payload = {
          from: "node-apn"
        , source: "web"
        , aps: {
              "content-available": 1
            , "data" : { "custom_key":"custom value", "custom_key_2":"custom value 2" }
        }       
    };


    notification.body = "Hello, world @ " + timeStamp;

    return apnProvider.send(notification, recepients).then(function(res) {  


        console.log("res.sent: ", res.sent)
        console.log("res.failed: ", res.failed)

        res.failed.forEach( (item) => {
            console.log(" \t\t\t failed with error:", item.error)
        })

        return response.send("finished!");

    }).catch( function (error) {

        console.log("Faled to send message: ", error)
        return response.send("failed!");

    })
})

两者都很标准。我已将content-availabe 设置为1。现在消息正在通过 Apple 推送通知中心显示并显示,它们只是没有按预期触发带有 didReceiveRemoteNotification 的块。

【问题讨论】:

    标签: ios swift firebase push-notification


    【解决方案1】:

    您需要启用后台模式 - 远程通知功能。

    要接收后台通知,您必须将远程通知后台模式添加到您的应用中。在 Signing & Capability 选项卡中,添加 Background Modes 功能,然后选中 Remote notification 复选框。

    启用远程通知后台模式:

    对于 watchOS,将此功能添加到您的 WatchKit 扩展中。

    来源:Pushing Background Updates to Your App | Apple Developer Documentation

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-11
      • 2017-08-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多