FCM的正确令牌获取方式 - iOS 10 Swift 3

52

我已经使用Firebase和FirebaseAuth/FCM等实现了应用程序,通过Firebase控制台成功地发送了通知。

然而,我需要从自己的应用程序服务器推送通知。

我想知道以下哪种方式是检索设备注册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"}]}

我也尝试了第二种方法,但在运行应用程序时出现致命错误,如下所示:- 在这里输入图像描述

如果有人能指出正确的方法,将不胜感激!


请看这个链接,它可以帮助你:https://dev59.com/FloU5IYBdhLWcg3wO1QW - Anbu.Karthik
注意:didRegisterForRemoteNotificationWithDeviceToken中的deviceToken参数不是Firebase注册令牌。您仍然需要按照下面的说明调用return InstanceID.instanceID().token()。 - William T. Mallard
15个回答

56

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)


你好,如何发布请求令牌? - Girl_engineer
2
如果有人和我一样,deviceToken:Data参数不是FCM注册令牌。来自InstanceID().token()的令牌才是。 - William T. Mallard
我收到了“token()已过时:请改用instanceIDWithHandler:”的警告。 - user11182249
1
我改成了这样:InstanceID.instanceID().instanceID { (result, error) in if error == nil { print("InstanceID token: (result)") } else { print(error, ": 获取 Fire 令牌时出错") } } - user11182249
这个怎么样:(https://firebase.google.com/docs/cloud-messaging/ios/client)?注册令牌通过方法`messaging:didReceiveRegistrationToken:`传递。通常情况下,此方法在每次应用程序启动时调用一次以获取注册令牌。 - Parth

46

24

Swift 3 + Firebase 4.0.4:

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

4
为了澄清,您的答案与下面的答案(Messaging.messaging().fcmToken)有什么区别?@MBH - j3141592653589793238
https://dev59.com/sKLia4cB1Zd3GeqPm7Cs - hmlasnk

21

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)")
        }
    })
}

8

Swift 4

本文原创:https://dev59.com/d1UL5IYBdhLWcg3wCEQA#50945350

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)")
    }
}

当在主屏幕视图加载viewDidLoad中调用时,我收到了“静态成员'instanceID'无法使用”的错误提示,请问您能提供帮助吗? - kemdo
@kemdo请确保您写的是带有括号的InstanceID.instanceID().instanceID,而不是InstanceID.instanceID.instanceID - cohen72
@kemdo,Yocoh,当我遇到“Static member 'instanceID......”问题时,你们是如何解决的? - Jamshed Alam

6

FCM设备令牌 swift3

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

5

选择第二个选项,可能看起来非常愚蠢/简单,但为了修复那个nil可选项致命错误,只需删除结尾处的强制解包即可。

你的代码:
var token = FIRInstanceID.instanceID().token()!
修改为:
var token = FIRInstanceID.instanceID().token()

这样至少可以修复那个讨厌的崩溃。


嗨John,错误仍然存在,似乎是FIRInstanceID.instanceID().token()返回了nil。 - aznelite89
1
@aznelite89,它为什么是nil的原因是你还没有注册Firebase Cloud Messaging。 - applejack42

5

获取当前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 ---------------➤")
    }
}

5

首先,注册 Firebase Token 刷新通知:

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()
}

1
请注意,InstanceIDTokenRefreshFIRInstanceID现已过时。 - José

2
我遇到了同样的问题,但是无法确定出现了什么问题。@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)")
    }
}

你只有在用户第二次打开应用程序时才会获得“刷新令牌”。
我成功地通过卸载应用程序并清理构建文件夹(Product > Clean Build Folder)来强制刷新令牌。这对于测试非常有用。
理想情况下,所有这些都可以在“messaging:didReceiveRegistrationToken”委托方法中处理,但我无法使其正常工作。另一种获取FCM令牌更改通知的方法是侦听名为“kFIRMessagingRegistrationTokenRefreshNotification”的“NSNotification”,如文档中所建议的:https://firebase.google.com/docs/cloud-messaging/ios/client

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接