Вопрос по firebase, apple-push-notifications, ios, swift, firebase-cloud-messaging – Firebase Cloud Messaging iOS: нет фонового push-уведомления

15

Используя новый облачный обмен сообщениями Firebase с методом swizzling, я успешно могу получить полезную нагрузку вdidReceiveRemoteNotification метод в моем приложении делегат, когда мое приложениена передний план, Однако я не получаю никакой полезной нагрузки иdidReceiveRemoteNotification не вызывается, когда мое приложениесправочная информациянесмотря на ответ API, что сообщение успешно отправлено (см. ниже)
Вот запрос, который я отправляю в API FCM, чтобы вызвать push-уведомлениеhttps://fcm.googleapis.com/fcm/send

{
"to": "{valid-registration-token}",
"priority":"high", //others suggested setting priority to high would fix, but did not
  "notification":{
      "body":"Body3",
      "title":"test"  
 } 
}


с ответом от FCM

{
      "multicast_id": 6616533575211076304,
      "success": 1,
      "failure": 0,
      "canonical_ids": 0,
      "results": [
        {
          "message_id": "0:1468906545447775%a4aa0efda4aa0efd"
        }
      ]
    }

Вот мой код приложения

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {

        Fabric.with([Crashlytics.self])
        FIRApp.configure()

        NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(self.tokenRefreshNotification),
                                                         name: kFIRInstanceIDTokenRefreshNotification, object: nil)
        return true
    }



    func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject], fetchCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) {
        // Let FCM know about the message for analytics etc.
        FIRMessaging.messaging().appDidReceiveMessage(userInfo)

        // Print full message.
        print("%@", userInfo)

        // handle your message

//        let localNotification = UILocalNotification()
//        localNotification.fireDate = NSDate()
//        let notification = userInfo["notification"]!
//        localNotification.alertBody = notification["body"] as? String
//        localNotification.alertTitle = notification["title"] as? String
//        localNotification.timeZone = NSTimeZone()
//        application.scheduleLocalNotification(localNotification)

    }

    func tokenRefreshNotification(notification: NSNotification) {
        let refreshedToken = FIRInstanceID.instanceID().token()!
        print("InstanceID token: \(refreshedToken)")
        LoginVC.registerForPushNotifications()
        connectToFcm()
    }


    //foreground messages
    func applicationDidBecomeActive(application: UIApplication) {
        connectToFcm()
    }

    // [START disconnect_from_fcm]
    func applicationDidEnterBackground(application: UIApplication) {
        FIRMessaging.messaging().disconnect()
        print("Disconnected from FCM.")
    }


    func connectToFcm() {
        FIRMessaging.messaging().connectWithCompletion { (error) in
            if (error != nil) {
                print("Unable to connect with FCM. \(error)")
            } else {
                print("Connected to FCM.")
            }
        }
    }

}

Я вызываю этот код в более позднем потоке в моем приложении, чтобы запросить разрешения

static func registerForPushNotifications() {
    let settings: UIUserNotificationSettings =
                UIUserNotificationSettings(forTypes: [.Alert, .Badge, .Sound], categories: nil)
            UIApplication.sharedApplication().registerUserNotificationSettings(settings)
            UIApplication.sharedApplication().registerForRemoteNotifications()
}

Так как я могу получать уведомления, пока приложение заранее, я предполагаю, что это снимет все опасения, что мои apns сертификаты не загружены или что маркер регистрации неверен. Если это не так, пожалуйста, прокомментируйте, и я снова пойду по этой кроличьей норе. Вероятно, есть что-то простое, что я упускаю из виду, но как я могу получить уведомления, пока приложение находится в фоновом режиме? Спасибо

@ArthurThompson До этой версии кода я не использовал метод swizzling, и реализовал метод didRegisterForeRemoteNotificationsWIthDeviceToken, где я смог получить токен. Сначала я надеялся, что с этим покончено, но когда этот токен не сработал для FCM, мне пришлось провести рефакторинг. Это отвечает на ваш вопрос? Daniel George
Похоже, у песочницы APN были некоторые проблемы (forums.developer.apple.com/thread/52224) но теперь уже решены, вы все еще видите проблемы с этим? Arthur Thompson
@Kazimieras Да, я прочитал все это. Я попытался установить высокий приоритет и контент-доступный для истины. но не повезло. Я также пытался использовать оба одновременно. но другие говорили, что это не сработает, и в моем случае это снова было правдой. Daniel George
Когда ваше приложение находится на переднем плане, вы можете получать сообщения непосредственно из FCM, а не через APN, что используется, когда ваше приложение находится в фоновом режиме. Чтобы убедиться, что APN настроены правильно, вы можете подтвердить получение токена APN, реализовав метод didRegisterForRemoteNotificationsWithDeviceToken. Arthur Thompson

Ваш Ответ

6   ответов
0

Выполните следующие действия после получения успешного токена от FCM, чтобы включить выборку данных полезной нагрузки в фоновом режиме с использованием FCM:

откройте Project Navigator> AppCapabilities> Background Mode> проверить наличие удаленных уведомлений

В App.delegate определить:

func application(_ application: UIApplication,didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {

    print("userinfo in background mode on-\(userInfo)")

    completionHandler(UIBackgroundFetchResult.newData)
}

Правильно отформатируйте данные в соответствии с рекомендациями Apple:введите описание ссылки здесь

Не забудьте добавить пару ключ-значение:{"content-available":1} если вы не сможете получить полезную нагрузку в фоновом режиме.

Теперь попробуйте отправить уведомление снова, используя токен FCM. Удачного кодирования

-2

AFAIK, для ios вы не сможете использовать FCM для отправки push-уведомлений для приложений в фоновом или отключенном состоянии.

Push-уведомление Firebase

0

Желаемое поведение, по крайней мере для моего приложения, заключается в получении push-уведомления, где содержимое PN (Push-уведомления) должно отображаться на нужной странице приложения.

У меня есть три различных состояния приложения, в которые может поступать PN: (конечно, это зависит от вашей реализации, но вы должны понять, как Apple обрабатывает PN в этих состояниях)

(поведение определяется яблоком!)

1) приложение находится на переднем плане:

PN получилвсплывает в Центре уведомлений (вы можете нажать на него или нет - это не имеет значения)значок будет обновленPN доступен на нужной странице

В этом случае приложениевсегда обрабатывает PN

2) приложение в фоновом режиме:

PN получилвсплывает в Центре уведомлений (вы можете нажать на него или нет - это не имеет значения)значок будет обновленPN доступен на нужной странице

В этом случае приложениевсегда обрабатывает PN

3) приложение убито / закрыто:

PN получилвсплывает в Центре уведомлений

сейчас есть три возможных пути

Проведите уведомление прочь -> PN будетНЕ обработано приложением

откройте приложение через иконку запуска -> PN будетНЕ обработано приложением

нажмите на уведомление -> приложение будет обработано PN

Конечно, это зависит от вашей реализации, потому что в случае «3. Откройте приложение с помощью значка панели запуска напрямую» вы можете просто получить все PN в запуске приложения через дополнительный API. НО вы должны понять, как Apple предотвращает обработку PN в некоторых случаях.

Я надеюсь, что это помогает кому-то!

10

(несмотря на использование метода swizzling, который должен делать это автоматически), вы все равно должны установить токен APNS в экземпляре Firebase. Следовательно, это означает, что вы также должны реализоватьdidRegisterForRemoteNOtificationsWithDeviceToken метод с чем-то вроде

func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) {


        // set firebase apns token
        FIRInstanceID.instanceID().setAPNSToken(deviceToken, type: FIRInstanceIDAPNSTokenType.Unknown)
}

В качестве добавленной заметки. С помощью"priority":"high" был полезен для тестирования, так как сразу отправлял уведомление.

Когда в приложении включена функция Swizzling, оно автоматически устанавливает маркер APN, поэтому нет необходимости реализовывать didRegisterForRemoteNotificationsWithDeviceToken. Arthur Thompson
Ключом для меня был выбор «Неизвестно» в качестве типа. Ранее я пробовал и «Песочницу», и «Разработка», но в любом случае она работала некорректно. Объект токена равен нулю при запуске чистой установки, однако я обошел это с помощью проверки безопасности, и уведомление о обновлении токена запускается несколько раз из того, что я вижу. Kazimieras
Как только у меня все заработало, я сделал новую установку, и теперь объект токена FIRInstanceID.instanceID (). Имеет значение nil, и я не могу connectToFcm с кодом ошибки 501. Есть идеи? Daniel George
@ArthurThompson, так почему же, даже используя обновленную версию, мне пришлось сделать это, чтобы решить проблему с фоновыми уведомлениями? На самом деле, документация Google для Firebase содержит множество руководств с устаревшими и неясными методами. juniorgarcia
0

Подобно решению Даниэля Джорджа, я мог бы решить мою проблему с:

Messaging.messaging().apnsToken = deviceToken

FirebaseInstanceID 2.0.8, FirebaseMessaging 2.0.8

0

true в полезную нагрузку JSON. В противном случае вы не получите push-уведомление в фоновом режиме.

"notification" : {
            "content_available" : true,
            "body" : "this is body",
            "title" : "this is title"
}

Похожие вопросы