Подтвердить что ты не робот

DidReceiveRemoteNotification не работает в фоновом режиме

Я работаю над большим приложением с огромным куском устаревшего кода. В настоящее время - существует реализация для:

- (void) application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo

Проблема заключается в том, что он вызывается только тогда, когда приложение находится на переднем плане или когда пользователь удаляет уведомление, когда приложение находится в фоновом режиме. Я попытался реализовать:

- (void) application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler

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

4b9b3361

Ответ 1

Реализация didReceiveRemoteNotification и didReceiveRemoteNotification:fetchCompletionHandler является правильным способом, но вам также необходимо сделать следующее:

Обязательно зарегистрируйтесь для удаленных уведомлений, см. здесь:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{    
    [[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound)];

    return YES;
}

Также не забудьте отредактировать Info.plist и установите флажки "Включить фоновые режимы" и "Удаленные уведомления":

enter image description here

Кроме того, вам нужно добавить "content-available":1 в свою полезную нагрузку push-сообщения, иначе приложение не будет проснуто, если оно находится в фоновом режиме (см. здесь):

Для push-уведомления для запуска операции загрузки, полезная нагрузка уведомлений должна включать ключ, доступный для контента, с его значение установлено в 1. Когда этот ключ присутствует, система пробуждает приложение в фон (или запускает его в фоновом режиме) и вызывает приложение делегаты Применение: didReceiveRemoteNotification: fetchCompletionHandler: метод. Ваша реализация этого метода должна загружать соответствующий контент и интегрировать его в ваше приложение.

Таким образом, полезная нагрузка должна выглядеть примерно так:

{
    aps = {
        "content-available" : 1,
        sound : ""
    };
}

Ответ 2

  • Зарегистрировать для push-уведомления в делегате приложения.
  • Добавить фоновый режим в приложениях.
  • Добавить "content-available" = "1" при отправке push-уведомления (если вы используете firebase, замените "content-available" = "1" на "content_available" = "true" при отправке push-уведомления со стороны сервера).

Ответ 3

У меня была та же проблема. Появился баннер уведомлений, но -приложение: didReceiveRemoteNotification: fetchCompletionHandler: метод не вызывался. Решение для меня, которое работало, заключалось в том, чтобы добавить реализацию - application: метод doReceiveRemoteNotification: method и переадресация вызова -application: didReceiveRemoteNotification: fetchCompletionHandler::

func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) {

    self.application(application, didReceiveRemoteNotification: userInfo) { (UIBackgroundFetchResult) in

    }
}

Ответ 4

Я создаю проект iOS, который будет использовать Firebase Cloud Messaging (FCM) для доставки пользовательских элементов данных, отправляемых через уведомления Firebase/APNS, с сервера компании на устройство iOS.

Первое, что я должен был понять, это то, что в отличие от Android, не существует аналогичного типа "Службы", который мог бы собирать и сохранять отправляемую мной информацию, независимо от того, находится ли приложение на переднем плане (активное), на заднем плане (до в памяти) или не активен (не в памяти). Поэтому я должен использовать уведомления, а не сообщения с данными, которые я разработал для Android.

После долгих чтений, чтобы понять как Apple APNS, так и интерфейс Firebase между приложением iOS и сервером APNS, просмотрев бесчисленное количество публикаций о стековом потоке и других веб-ресурсах, я наконец-то понял, как заставить это работать в соответствии с моими требованиями.

Когда с сервера отправляется уведомляющее сообщение Firebase Cloud Messaging (FCM) (или консоль Firebase, так как FCM по умолчанию использует уведомления, а не сообщения данных), оно доставляется через APNS и представляется как уведомление на устройстве iOS. Когда пользователь нажимает на баннер уведомления, iOS делает следующее: если приложение не запущено/загружено, iOS запускает приложение, если приложение загружается/работает, но в фоновом режиме iOS выводит приложение на передний план ИЛИ, если приложение на переднем плане (во всех трех случаях) содержимое сообщения затем доставляется через приложение func (_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any], fetchCompletionHandler завершениеHandler: (UIBackgroundFetchResult) → Void) {}.

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

1) Перейдите к настройке APNS и Firebase, довольно просто, создавайте и регистрируйте сертификаты и тому подобное.

2) В appDelegate, didFinishLaunchingWithOptions добавьте:

        Messaging.messaging().delegate = self as? MessagingDelegate

        if #available(iOS 10.0, *) {

            UNUserNotificationCenter.current().delegate = self

            let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]

            UNUserNotificationCenter.current().requestAuthorization(
                options: authOptions,
                completionHandler: {_, _ in })
        }
        else {

            let settings: UIUserNotificationSettings =
                UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)

            application.registerUserNotificationSettings(settings)
        }

        application.registerForRemoteNotifications()

3) Затем добавьте эти функции обратного вызова в appDelegate:

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

        // Print message ID.
        if let messageID = userInfo["gcm.message_id"] {

            print("\n*** application - didReceiveRemoteNotification - fetchCompletionHandler - Message ID: \(messageID)")
        }

        // Print full message.
        print("\n*** application - didReceiveRemoteNotification - full message - fetchCompletionHandler, userInfo: \(userInfo)")

        myNotificationService?.processMessage(title: userInfo["Title"] as! String
            , text: userInfo["Text"] as! String, completion: { (success) in

                if success {
                    completionHandler(.newData)
                }
                else {
                    completionHandler(.noData)
                }
        })
    }

    func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {

        completionHandler([.alert, .badge, .sound])
    }

Очень полезно:

https://developer.apple.com/library/archive/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/CreatingtheNotificationPayload.html

https://firebase.googleblog.com/2017/01/debugging-firebase-cloud-messaging-on.html