web-dev-qa-db-ja.com

didReceiveRemoteNotificationがバックグラウンドで機能しない

私は、レガシーコードの巨大なチャンクを持つ大きなアプリに取り組んでいます。現在-以下のための実装があります:

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

問題は、アプリがフォアグラウンドにあるときにのみ呼び出されることですORアプリがバックグラウンドにあるときにユーザーが通知をタップすると、私は実装しようとしました:

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

しかし、アプリは同じように動作します。いずれにせよ-アプリがバックグラウンドにある場合、このメソッドは呼び出されません。何が問題なのでしょうか?

35
YogevSitton

didReceiveRemoteNotificationdidReceiveRemoteNotification: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を追加する必要があります。そうしないと、バックグラウンドにある場合、アプリは起動しません( documentation here を参照):

プッシュ通知でダウンロード操作をトリガーするには、通知のペイロードに値が1に設定されたコンテンツで使用可能なキーが含まれている必要があります。そのキーが存在する場合、システムはアプリをバックグラウンドで起動(またはバックグラウンドで起動)し、アプリデリゲートのapplication:didReceiveRemoteNotification:fetchCompletionHandler:メソッドを呼び出します。そのメソッドの実装は、関連するコンテンツをダウンロードしてアプリに統合する必要があります

したがって、ペイロードは少なくとも次のようになります。

{
    aps = {
        "content-available" : 1,
        sound : ""
    };
}
69
Baris Akar
  1. アプリデリゲートでプッシュ通知に登録します。
  2. アプリ機能にバックグラウンドモードを追加します。
  3. プッシュ通知の送信中に「content-available」= "1"を追加します(firebaseを使用している場合は、サーバー側からプッシュ通知を送信中に "content-available" = "1"を "content_available" = "true"に置き換えてください)。
13
Mahadev Mandale

同じ問題がありました。通知バナーは表示されましたが、-application:didReceiveRemoteNotification:fetchCompletionHandler:メソッドは呼び出されませんでした。私のために働いた解決策は、-application:didReceiveRemoteNotification:メソッドの実装を追加し、-application:didReceiveRemoteNotification:fetchCompletionHandler ::への呼び出しを転送することでした

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

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

    }
}
5
ZaEeM ZaFaR

Firebase Cloud Messaging(FCM)を使用してFirebase/APNS通知を介して送信されるカスタムデータ要素を企業サーバーからiOSデバイスに配信するiOSプロジェクトを作成しています。

最初に理解しなければならないことは、Androidとは異なり、アプリがフォアグラウンド(アクティブ)、バックグラウンド(まだ)にあるかどうかに関係なく、送信する情報をキャプチャおよび保存できる同様のタイプの「サービス」がないことです。 (メモリ内)またはアクティブでない(メモリ内ではない)。したがって、Android用に設計したようなデータメッセージではなく、通知メッセージを使用する必要があります。

Apple APNSとiOSアプリとAPNSサーバー間のFirebaseインターフェースの両方を理解し、stackoverflowやその他のWebリソースに関する無数の投稿を見て、最後にこれを機能させる方法を見つけました。私の要件のため。

Firebase Cloud Messaging(FCM)通知メッセージがサーバー(または、FCMがデフォルトではNotification NOT DataメッセージとしてFirebase Console)から送信されると、APNSを介して配信され、iOSデバイスに通知として表示されます。ユーザーが通知バナーをタップすると、iOSは次を実行します。アプリが実行/ロードされていない場合、iOSはアプリを起動します。アプリがロード/実行されているが、バックグラウンドでiOSがアプリをフォアグラウンドに持ってくる場合ORアプリがフォアグラウンド(3つすべてのケース)にある場合、メッセージコンテンツはfunc application(_ application:UIApplication、didReceiveRemoteNotification userInfo:[AnyHashable:Any]、fetchCompletionHandler completionHandler:(UIBackgroundFetchResult)->無効){}。

確かなことは、バックグラウンドモードを有効にしてリモート通知をチェックする必要があることです。ペイロードに{"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

0
AndyW58