web-dev-qa-db-ja.com

Firebase 4.0でプッシュ通知が機能しない

今日、ポッドを新しいFirebase 4.0に更新しました。提案された変更を行い、Githubサンプルからコードを取得しました。私は正直言って迷ってしまいます。FCMトークンを取得して、Firebaseコンソールからメッセージを送信しても何も表示されません。

更新すると、メッセージが送信されたと表示されますが、コンソールとデバイスを確認しても何もありません。何が欠けていますか?

ここに私のappdelegateがあります:

//
//  Created by Erik Grosskurth on 4/24/17.
//

import UIKit
import FirebaseAnalytics
import FirebaseInstanceID
import FirebaseMessaging
import UserNotifications
import SystemConfiguration
import MobileCoreServices
import Quickblox
import QuickbloxWebRTC


let kQBApplicationID:UInt = 3545252534
let kQBAuthKey = "udfgsegsetrgsextr"
let kQBAuthSecret = "setbsetbsetbsetrbset"
let kQBAccountKey = "sbrtsbrtbsrtbsrtbrt"

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?
    let gcmMessageIDKey = "gcm.message_id"

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {

        // [START register_for_notifications]

        FirebaseApp.configure()

        Messaging.messaging().delegate = self

        if #available(iOS 10.0, *) {
            // For iOS 10 display notification (sent via APNS)
            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()

        if (Messaging.messaging().fcmToken != nil) {
            DataModel.sharedInstance.sessionInfo.FirebaseAccessToken = Messaging.messaging().fcmToken!
            print("FCM token: \(DataModel.sharedInstance.sessionInfo.FirebaseAccessToken)")
        }else {
            print("token was nil")
        }

        // [END register_for_notifications]

        //Quickblox config
        QBSettings.setApplicationID(kQBApplicationID)
        QBSettings.setAuthKey(kQBAuthKey)
        QBSettings.setAuthSecret(kQBAuthSecret)
        QBSettings.setAccountKey(kQBAccountKey)

        // Set settings for zone
        QBSettings.setApiEndpoint("https://api.quickblox.com", chatEndpoint: "chat.quickblox.com", forServiceZone: .production)
        // Activate zone
        QBSettings.setServiceZone(.production)

        QBSettings.setKeepAliveInterval(30)
        QBSettings.setAutoReconnectEnabled(true)
        QBRTCConfig.setStatsReportTimeInterval(1)
        QBRTCConfig.setDialingTimeInterval(5)
        QBRTCConfig.setAnswerTimeInterval(60)

        return true
    }

    // [START receive_message]
    func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any]) {

        Messaging.messaging().appDidReceiveMessage(userInfo)

        if let messageID = userInfo[gcmMessageIDKey] {
            print("Message ID: \(messageID)")
        }

        print(userInfo)

    }

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

        Messaging.messaging().appDidReceiveMessage(userInfo)

        if let messageID = userInfo[gcmMessageIDKey] {
            print("Message ID: \(messageID)")
        }

        print(userInfo)

        completionHandler(UIBackgroundFetchResult.newData)

    }


    // when APNs has assigned the device a unique token
    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {

        print("didRegisterForRemoteNotificationsWithDeviceToken()")

        Messaging.messaging().apnsToken = deviceToken

        //Messaging.messaging().setAPNSToken(deviceToken, type: MessagingAPNSTokenType.sandbox)
        //Messaging.messaging().setAPNSToken(deviceToken, type: MessagingAPNSTokenType.prod)
        //Messaging.messaging().setAPNSToken(deviceToken, type: MessagingAPNSTokenType.unknown)

        let deviceTokenString = deviceToken.reduce("", {$0 + String(format: "%02X", $1)})
        DataModel.sharedInstance.sessionInfo.APNSAccessToken = deviceTokenString
        print("APNS Access Token: \(deviceTokenString)")

    }


    // [END receive_message]
    func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
        print("Unable to register for remote notifications: \(error.localizedDescription)")
    }


    func applicationWillResignActive(_ application: UIApplication) {
        // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
        // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
    }

    func applicationDidEnterBackground(_ application: UIApplication) {
        QBChat.instance().disconnect { (error) in
            if error != nil {
                print("error: \(String(describing: error))")
            } else {
                print("success for applicationDidEnterBackground")
            }
        }
    }

    func applicationWillEnterForeground(_ application: UIApplication) {
        let qbUser = QBUUser()
        qbUser.id = DataModel.sharedInstance.qbLoginParams.id
        qbUser.password = DataModel.sharedInstance.sessionInfo.QBPassword
        QBChat.instance().connect(with: qbUser) { (error) in
            if error != nil {
                print("error: \(String(describing: error))")
            } else {
                print("success for applicationWillEnterForeground")
            }
        }
    }

    func applicationDidBecomeActive(_ application: UIApplication) {
        // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
    }

    func applicationWillTerminate(_ application: UIApplication) {
        QBChat.instance().disconnect { (error) in
            if error != nil {
                print("error: \(String(describing: error))")
            } else {
                print("success for applicationWillTerminate")
            }
        }
    }

    // LOCK IN PORTRAIT MODE
    func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
        return UIInterfaceOrientationMask(rawValue: UIInterfaceOrientationMask.portrait.rawValue)
    }

}

// [START ios_10_message_handling]
@available(iOS 10, *)
extension AppDelegate : UNUserNotificationCenterDelegate {

    // Receive displayed notifications for iOS 10 devices.
    func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
        let userInfo = notification.request.content.userInfo

        // With swizzling disabled you must let Messaging know about the message, for Analytics
        Messaging.messaging().appDidReceiveMessage(userInfo)
        // Print message ID.
        if let messageID = userInfo[gcmMessageIDKey] {
            print("Message ID: \(messageID)")
        }

        // Print full message.
        print(userInfo)

        // Change this to your preferred presentation option
        completionHandler([])
    }

    func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
        let userInfo = response.notification.request.content.userInfo
        // Print message ID.
        if let messageID = userInfo[gcmMessageIDKey] {
            print("Message ID: \(messageID)")
        }

        // Print full message.
        print(userInfo)

        completionHandler()
    }
}
// [END ios_10_message_handling]

extension AppDelegate : MessagingDelegate {
    // [START refresh_token]
    func messaging(_ messaging: Messaging, didRefreshRegistrationToken fcmToken: String) {
        DataModel.sharedInstance.sessionInfo.FirebaseAccessToken = fcmToken
        print("Firebase registration token: \(fcmToken)")
    }
    // [END refresh_token]
    // [START ios_10_data_message]
    // Receive data messages on iOS 10+ directly from FCM (bypassing APNs) when the app is in the foreground.
    // To enable direct data messages, you can set Messaging.messaging().shouldEstablishDirectChannel to true.
    func messaging(_ messaging: Messaging, didReceive remoteMessage: MessagingRemoteMessage) {
        print("Received data message: \(remoteMessage.appData)")
    }
    // [END ios_10_data_message]
}

ここにログがあります:

2017-05-31 16:49:56.937067-0400 Telemed[1843:937699] [Firebase/Analytics][I-ACS003016] Firebase Analytics App Delegate Proxy is disabled. To log deep link campaigns manually, call the methods in FIRAnalytics+AppDelegate.h.
2017-05-31 16:49:56.937 Telemed[1843] <Warning> [Firebase/Analytics][I-ACS003016] Firebase Analytics App Delegate Proxy is disabled. To log deep link campaigns manually, call the methods in FIRAnalytics+AppDelegate.h.
2017-05-31 16:49:57.023568-0400 Telemed[1843:937706] [Firebase/Analytics][I-ACS005000] The AdSupport Framework is not currently linked. Some features will not function properly. Learn more at 
2017-05-31 16:49:57.023 Telemed[1843] <Warning> [Firebase/Analytics][I-ACS005000] The AdSupport Framework is not currently linked. Some features will not function properly. Learn more at 
2017-05-31 16:49:57.028454-0400 Telemed[1843:937697] [Firebase/Analytics][I-ACS023007] Firebase Analytics v.4000000 started
2017-05-31 16:49:57.028 Telemed[1843] <Notice> [Firebase/Analytics][I-ACS023007] Firebase Analytics v.4000000 started
2017-05-31 16:49:57.029042-0400 Telemed[1843:937697] [Firebase/Analytics][I-ACS023008] To enable debug logging set the following application argument: -FIRAnalyticsDebugEnabled (see )
2017-05-31 16:49:57.029 Telemed[1843] <Notice> [Firebase/Analytics][I-ACS023008] To enable debug logging set the following application argument: -FIRAnalyticsDebugEnabled (see )
FCM token: myTokenIsHere
2017-05-31 16:49:57.101756-0400 Telemed[1843:937699] [Firebase/Analytics][I-ACS032003] iAd framework is not linked. Search Ad Attribution Reporter is disabled.
2017-05-31 16:49:57.102 Telemed[1843] <Warning> [Firebase/Analytics][I-ACS032003] iAd framework is not linked. Search Ad Attribution Reporter is disabled.
2017-05-31 16:49:57.103700-0400 Telemed[1843:937697] [Firebase/Analytics][I-ACS023012] Firebase Analytics enabled
2017-05-31 16:49:57.103 Telemed[1843] <Notice> [Firebase/Analytics][I-ACS023012] Firebase Analytics enabled
Destroyed Session but Saved Login
2017-05-31 16:49:57.158678-0400 Telemed[1843:937637] [MC] System group container for systemgroup.com.Apple.configurationprofiles path is /private/var/containers/Shared/SystemGroup/systemgroup.com.Apple.configurationprofiles
2017-05-31 16:49:57.159102-0400 Telemed[1843:937637] [MC] Reading from public effective user settings.
didRegisterForRemoteNotificationsWithDeviceToken()
APNS Access Token: 091F01B...

>>> ------> **解決済み<------- <<< **

トラブルシューティングと究極のフェイスパームへの詳細なダイビングAT終わり...このスレッドに従ってください:https:// github.com/firebase/quickstart-ios/issues/29

特別な感謝 THE RIZ 問題を解決するための彼の時間!

12
Erik Grosskurth

Firebase Cloud Messagingは、APNs構成が機能していることを確認し、その上にFCMを追加する必要があるため、iOSで正しく設定するには非常に複雑です。

APNsセットアップ

APNs認証キーもAppleで期限切れではなく、サンドボックス環境と本番環境の両方で機能し、同じキー(.p8ファイルとして)を使用できるため、非常に優れていますApple開発者アカウントの下にあるallアプリすべてにプッシュ通知を送信します。

また、失敗の可能性がある新しい領域typosも導入されます。ランダムなバンドルIDを入力でき、Xcodeで適切な「チーム」が構成されている限り、アプリはAPNsデバイストークンを取得します。

APNを介してそのデバイストークンに通知を送信すると(私は このスクリプト を使用して、HTTP/2 +認証キーを介してテスト通知を送信しました)、DeviceTokenNotForTopicエラーが発生します。何がうまくいかなかったのか。

チェックリスト

  • アプリのバンドルIDが送信先のバンドルIDと一致していることを確認してください
  • 少なくともaps-environmentキーがdevelopmentに設定された資格ファイルがあることを確認します(これは、リリースビルドでXcodeによって自動的に更新されます)
  • Firebaseなどの他のSDKで「自動」構成(つまり、スウィズリング)を使用している場合は、application:didRegisterForRemoteNotificationsWithDeviceToken:でAPNsトークンを取得していることを確認してください。これにより、少なくともAPNの設定に問題がないことが確認されます(ただし、タイプミスがある可能性があります)。

FCMセットアップ

使用しているGoogleService-Info.plistファイルが、plistのBUNDLE_IDキーと同じアプリのものであることを確認してください。 APNsキーはすべてのアプリで問題なく機能するため、同じGoogleService-Info.plistはアプリ全体で問題ないと考えていることを開発者が考えているのを見てきましたが、そうではありません。

テスト

問題のデバッグに役立つように、ターミナルから FCMのHTTP API を使用してテスト通知を送信することもお勧めします。 Firebase Notifications Consoleとは異なり、発生したエラーはそのまま表示されます。次に例を示します。

curl -X "POST" "https://fcm.googleapis.com/fcm/send" \
     -H "Authorization: key=SERVER_KEY" \
     -H "Content-Type: application/json" \
     -d $'{
  "notification": {
    "body": "Testing with direct FCM API",
    "title": "Test Message",
    "badge": "0",
    "sound": "default"
  },
  "registration_ids": [
    "FCM_TOKEN"
  ]
}'

SERVER_KEYに、Firebaseコンソール>プロジェクト設定>クラウドメッセージング>サーバーキーの値を入力します。 FCM_TOKENをFCMトークンに置き換えます。

FCM SDKで作業しているときに Paw を使用してアプリにテスト通知を送信します。

17
Rizwan Sattar