web-dev-qa-db-ja.com

FCMのトークンを取得する正しい方法-iOS 10 Swift 3

firebaseAuth/FCMなどでFirebaseを実装し、Firebase Consoleから通知を正常に送信しました。

しかし、私は自分のアプリサーバーから通知をプッシュする必要があります。

デバイスの登録IDを取得する正しい方法は次のとおりです:-

1)didRegisterForRemoteNotificationWithDeviceTokenから登録IDトークンを取得

func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
    var token = ""

    for i in 0..<deviceToken.count {
        token += String(format: "%02.2hhx", arguments: [deviceToken[i]])
    }

    print("Registration succeeded!")
    print("Token: ", token)
    Callquery(token)

}

2)firebaseから登録トークンを取得(現在の登録トークンを取得するFirebaseドキュメントに基づく)

let token = FIRInstanceID.instanceID().token()!

私は最初の方法を使用していましたが、登録IDがそれに応じてアプリサーバーデータベースに保存されていてもプッシュ通知が受信されず、このCURLセッションの結果が表示されます:-

{"multicast_id":6074293608087656831,"success":0,"failure":1,"canonical_ids":0,"results":[{"error":"InvalidRegistration"}]}

私はまた、2番目の方法を試し、以下のようにアプリを実行中に致命的なエラーが発生しました:- enter image description here

誰かが私に正しい方法を教えてくれれば感謝します!

33
aznelite89

tokenRefreshNotification関数は、アプリの起動時に常に呼び出されるとは限りません。

ただし、通常のdidRegisterForRemoteNotificationsWithDeviceTokenデリゲート関数内にコードを配置すると、毎回トークンを取得できます。

func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
    if let refreshedToken = InstanceID.instanceID().token() {
        print("InstanceID token: \(refreshedToken)")
    }
}

(Swift 3 + Firebase 4.0.4)

51
Sam

Swift 3 + Firebase 4.0.4:

static var FirebaseToken : String? {
    return InstanceID.instanceID().token()
}
24
MBH

Firebaseが推奨する方法:

let token = Messaging.messaging().fcmToken

参照: iOSでのFirebase Cloud Messagingクライアントアプリのセットアップ

23
Musa almatri

Swift 4 + Firebase(5.3.0)

func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
    InstanceID.instanceID().instanceID(handler: { (result, error) in
        if let error = error {
            print("Error fetching remote instange ID: \(error)")
        } else if let result = result {
            print("Remote instance ID token: \(result.token)")
        }
    })
}
13
Daniyal Raza

Swift 4

礼儀: https://stackoverflow.com/a/50945350/1014164

InstanceID.instanceID().instanceID { (result, error) in
    if let error = error {
        print("Error fetching remote instange ID: \(error)")
    } else if let result = result {
        print("Remote instance ID token: \(result.token)")
    }
}
7
cohen72

FCMデバイストークンSwift

    let fcmDeviceToken = FIRInstanceID.instanceID().token()
    print("FCM token: \(fcmDeviceToken ?? "")")
6
jazzbpn

Firebaseトークン更新通知の最初の登録:

NotificationCenter.default.addObserver(self, selector: 
     #selector(tokenRefreshNotification), name:     
     NSNotification.Name.InstanceIDTokenRefresh, object: nil)

その後、tokenRefreshNotificationセレクターでトークンを受信できます。

func tokenRefreshNotification(_ notification: Notification) {
    if let refreshedToken = FIRInstanceID.instanceID().token() {
      print("InstanceID token: \(refreshedToken)")
    }

    // Connect to FCM since connection may have failed when attempted before having a token.
    connectToFcm()
}
5

2番目のオプションを使用すると、これは本当に愚かでシンプルに見えますが、そのnilのオプションの致命的なエラーを修正するには、最後のforce-unwrapを削除するだけです

あなたのコード:
var token = FIRInstanceID.instanceID().token()!
成功する:
var token = FIRInstanceID.instanceID().token()

それは少なくともその厄介なクラッシュを修正します

5
John Leonardo

私は同じ問題を抱えていましたが、何が起こっているのか理解できませんでした。

@Samによって提案されたdidRegisterForRemoteNotificationsWithDeviceTokenは(ほぼ)毎回呼び出されるため、回避策として適しています。ただし、更新されたトークンでアプリを初めて開いたときには呼び出されません。

したがって、このシナリオでは次のものが必要です。

func messaging(_ messaging: Messaging, didRefreshRegistrationToken fcmToken: String) {
    print("Refreshed Token: \(fcmToken)")
}

したがって、次のもののみを使用する場合:

func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
    if let fcmToken = InstanceID.instanceID().token() {
        print("InstanceID token: \(fcmToken)")
    }
}

ユーザーがアプリを2回開いたときにのみ、「更新されたトークン」を取得します。

アプリをアンインストールし、ビルドフォルダーをクリーンアップすることで(製品>ビルドフォルダーのクリーン)、更新トークンを強制的に管理しました。テストに適しています。

理想的には、messaging:didReceiveRegistrationTokenデリゲートメソッドですべて処理できますが、動作させることはできませんでした。 FCMトークンの変更を通知する別の方法は、ドキュメントで提案されているNSNotificationという名前のkFIRMessagingRegistrationTokenRefreshNotificationをリッスンすることです。 https://firebase.google.com/docs/cloud-messaging/ios/client

2
erickva

最初に次のようなライブラリをインポートします。

import FirebaseInstanceID
import FirebaseMessaging
import UserNotifications

デリゲートの設定:MessagingDelegate、UNUserNotificationCenterDelegate

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, MessagingDelegate, UNUserNotificationCenterDelegate {

DidFinishLaunching()でこのコードを記述します。

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

    // Override point for customization after application launch.
    FirebaseApp.configure()
    Messaging.messaging().delegate = self

    //remote Notifications
    if #available(iOS 10.0, *) {
        UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge]) { (isGranted, err) in
            if err != nil {
                //Something bad happend
            } else {
                UNUserNotificationCenter.current().delegate = self
                Messaging.messaging().delegate = self

                DispatchQueue.main.async {
                    UIApplication.shared.registerForRemoteNotifications()
                }
            }
        }
    } else {
        // Fallback on earlier versions
    }

    if #available(iOS 10, *) {
        UNUserNotificationCenter.current().requestAuthorization(options: [.badge,.sound,.alert], completionHandler: { (granted, error) in
            application.registerForRemoteNotifications()
        })
    }else{
        let notificationSettings = UIUserNotificationSettings(types: [.badge,.sound,.alert], categories: nil)
        UIApplication.shared.registerUserNotificationSettings(notificationSettings)
        UIApplication.shared.registerForRemoteNotifications()
    }

    return true
}

このようにconnectFCMメソッドを記述します。

func ConnectToFCM() {
    Messaging.messaging().shouldEstablishDirectChannel = true

    if let token = InstanceID.instanceID().token() {
        print("\n\n\n\n\n\n\n\n\n\n ====== TOKEN DCS: " + token)
    }

また、プッシュ通知を登録および受信するためのデリゲートメソッドを記述します。

func messaging(_ messaging: Messaging, didRefreshRegistrationToken fcmToken: String) {
    print("\n\n\n\n\n ==== FCM Token:  ",fcmToken)
    HelperFunction.helper.storeInUserDefaultForKey(name: kFCMToken, val: fcmToken)
    ConnectToFCM()
}

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

   // UIApplication.shared.applicationIconBadgeNumber += 1

    NotificationCenter.default.post(name: NSNotification.Name(rawValue: "Barker"), object: nil)
}

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

    print(userInfo)
}

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

    print(userInfo)

    completionHandler(UIBackgroundFetchResult.newData)
}

}

これで、firebaseコンソールからテストできます。 enter image description here

100%動作し、簡単でテスト済み

注:1)xcodeの機能セクションからのプッシュ通知を有効にします。

2)firebaseプロジェクト設定にアップロードされた両方のp12証明書を2回確認します。

3)デバイストークンは、シミュレータではなく実際のデバイスからのみ取得できます。

1

現在のFCMトークンを取得するには

if let token = Messaging.messaging().fcmToken {
    // token is current fcmToken
}

現在のFCMトークンを更新するには

現在のinstanceIdを削除すると、新しいトークンはすぐにMessagingDelegate(messaging:didReceiveRegistrationToken)で受信されます。

InstanceID.instanceID().deleteID { (error) in
    if let er = error {
        print(er.localizedDescription)
    } else {
        print("instanceID().deleteID  success ---------------➤")
    }
}
1
Brownsoo Han