FCM 推送通知问题:“错误”:“未注册”

Posted

技术标签:

【中文标题】FCM 推送通知问题:“错误”:“未注册”【英文标题】:FCM push notification issue: "error":"NotRegistered" 【发布时间】:2017-07-03 15:28:31 【问题描述】:

我遇到了使用 FCM 向 android 发送推送通知的奇怪问题。

目标:- 发送推送通知时出错

以下是我确实具有向 Android 发送推送通知功能的场景

 public static function SendMultipleNotificationAndroid($groups)
    
        //your api key SERVER API KEY
        $apiKey = Yii::$app->params['android_api_key'];
        $url = 'https://fcm.googleapis.com/fcm/send';    
        $headers = array(
            'Authorization:key=' . $apiKey,
            'Content-Type: application/json'
        );
        
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        
        foreach($groups as $resG)
            $users  = $resG['users'];                        
            $msg    =   $resG['message'];
            $type    =   $resG['notification_type'];
            $notification_data    =   $resG['notification_data'];

            $deviceTokens = [];
            foreach($users as $resUser)
                $deviceTokens[] = $resUser['device_token'];
                //Add  Friend badge count +1
                Common::AddRemoveBadgeCount($resUser['user_id']);
            
            if(!empty($deviceTokens))
                $fields = array(
                    'registration_ids' => $deviceTokens,
                    'priority'     => 'high', 
                    'collapse_key' => $resG['notification_type'],   
                    'time_to_live' => 2419200,     
                    "click_action" =>"NotificationListingActivity",     
                    'data'         => [                  
                        "title"             => "ProjectName",
                        "body"              => $resG['message'],
                        "action_tag"        => $resG['notification_type'],
                        "message"           => $resG['message'],
                        'notification_type' => $type,
                        'notification_data' => $notification_data,
                        'sound'             => 'default',
                    ]
                );
                //Print result 
                p($ch,0);
                curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($fields));
                curl_exec($ch);
                        
        
        curl_close($ch);
    

所以问题是当我发送单个通知时它工作正常,但是当我发送多个通知时我每次都收到错误

<pre>Resource id #5</pre>"multicast_id":4818908994630396118,"success":1,"failure":1,"canonical_ids":0,"results":["error":"NotRegistered","message_id":"0:1487136045570022%c3bae3c6002e9358"]

<pre>Resource id #5</pre>"multicast_id":5218359780835228544,"success":1,"failure":1,"canonical_ids":0,"results":["error":"NotRegistered","message_id":"0:1487136046618669%c3bae3c6002e9358"]

当我们调试代码时,我们的数据库中确实有设备令牌,没有防火墙会停止发送推送通知。

每次我调用上面的函数我都会得到

"error":"NotRegistered"

【问题讨论】:

【参考方案1】:

我有一个 100% 的解决方案,我最近解决了这个问题 错误,因为您在设备上发送此通知而发生 其中不包含您的 Firebase 设置 api 密钥 例如 当您注册用户时,该用户从不同的地方注册 firebase 设置,因此您的 android 令牌与您的发送不同 对未为其创建 android 令牌的其他 firebase 设置的请求 您尝试向谁发送通知(消息),因此您必须 确保您的用户 android 令牌从相同的 firebase 生成 您正在使用哪个项目的项目 firebase api 密钥

【讨论】:

如果有段落和标点符号会更好阅读。【参考方案2】:

对于 ios,我遇到了同样的问题。我们只是将令牌保存在 didRegisterForRemoteNotificationsWithDeviceToken 上。如前所述,由于各种原因,您可能会失去对令牌的引用。

为了修复“未注册”错误,我在 App Delegate 中添加了以下内容:

extension AppDelegate: MessagingDelegate 
    func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String) 
        print("Firebase registration token: \(String(describing: fcmToken))")

        //Notification setup. Token will be available anywhere
        let dataDict: [String: String] = ["token": fcmToken ]
        NotificationCenter.default.post(
            name: Notification.Name("FCMToken"),
            object: nil,
            userInfo: dataDict
        )

        // Send token to Firebase server.
        if Auth.auth().currentUser?.uid != nil 
            guard let userUid = Auth.auth().currentUser?.uid else  return 
            let dataBaseRef = Database.database().reference()
            let value : [String : Any] "pushToken" : fcmToken]
            
            dataBaseRef.child("Your database path here").updateChildValues(value, withCompletionBlock:  (error, ref) in
                
                if error != nil 
                    print("Error with storing/updating user token", error?.localizedDescription as Any)
                
            )
        
    

didReceiveRegistrationToken 在令牌更新时被调用。您将需要卸载以前版本的应用,添加代码并重新分发更新版本。

【讨论】:

【参考方案3】:

事情是firebase在应用第一次运行时为你的目标设备生成一个唯一的设备ID,它会被用作设备的标识。

如果用户卸载应用程序或清除应用程序的数据,那么在这种情况下,在重新安装或重新打开应用程序时,设备 ID 会有所不同。这将导致 Firebase 无法识别 ID 来发送通知。这将导致错误未注册

【讨论】:

【参考方案4】:

就我而言,更新设备的 FCM 令牌有效!

【讨论】:

【参考方案5】:

卸载并重新安装应用程序时出现此错误。

我认为,当我们重新安装应用程序时,每次安装时都无法获得新的 fcm 令牌。

所以,我们必须先删除之前的实例 id,然后再创建新的 fcm 令牌。请看下面的代码..

只需添加未注释的行就解决了我的问题..

请参阅此解决方案的第一条评论以获取代码:)

_firebaseRegister()  
    // _firebaseMessaging.deleteInstanceID(); 
    _firebaseMessaging.getToken().then((token) => fcmtoken = token); 

希望这对你有用! :)

【讨论】:

_firebaseRegister() // _firebaseMessaging.deleteInstanceID(); _firebaseMessaging.getToken().then((token) => fcmtoken = token); 【参考方案6】:

在我们的例子中,当我们使用 Xcode“运行”覆盖应用的生产安装时,iOS 上会出现此问题(将生产应用替换为就地调试版本)。

应用仍会收到相同的注册令牌,但不接受消息(从 FCM 返回 NotRegistered)。

我们发现从设备上卸载应用程序并执行全新安装可以解决此问题。

【讨论】:

【参考方案7】:

我的问题与上述所有问题都不同。我们正在尝试的 Firebase 消息超出了 4Kb 的最大大小。触发“未注册”的可能性很小。但问题是我记录了这个应用程序可能没有安装的时刻。因此,还要检查Firebase 消息 的大小。

【讨论】:

【参考方案8】:

Android 应用程序向https://fcm.googleapis.com/fcm/send 发送请求时出现此错误:

...
"results": [
    
        "error": "NotRegistered"
    
]

虽然应用程序运行良好一段时间,并且推送通知已发送,然后(可能在应用程序中重新授权或 Play 市场中重新授权之后)该错误开始显示。

如果我更改了推送令牌(例如添加了“1”),那么我会收到另一个错误:

"results": [
    
        "error": "InvalidRegistration"
    
]

因此,Firebase 知道推送令牌,但没有发送通知。

我卸载了 Android 应用程序并重新安装。

【讨论】:

【参考方案9】:

在搜索“未注册”问题时,我们发现了以下...

在设备端,设备通知令牌的生成是通过以下代码完成的,当用户安装后第一次启动应用程序时。

RegToken = FirebaseInstanceId.getInstance().getToken(senderId, "FCM");  // Old code

我们使用派生自“FirebaseMessagingService”的其他类来创建/接收通知。但是该类中缺少以下方法。

// New code
@Override
public void onNewToken(String token) 
    Log.d(TAG, "Refreshed token: " + token);

    // If you want to send messages to this application instance or
    // manage this apps subscriptions on the server side, send the
    // Instance ID token to your app server.
    sendRegistrationToServer(token);
 

我们发现,每次App启动时,设备中的FCM系统都会调用上述方法。 (该应用程序没有卸载,但该方法每次都给出不同的令牌。)所以我们将我们的方法称为“sendRegistrationToServer(token);”将令牌连同“DeviceId”和其他识别数据一起提交给我们的服务器。当我们在这个令牌上从 php 服务器发送通知时,它返回 'sent' 而不是 "NotRegistered"。

【讨论】:

我同意你的做法。但是我有一个问题,如果某些用户暂时没有打开应用程序并且设备令牌之间的那个被更改了怎么办?我们应该怎么做? @Nils 令牌仅在应用程序打开时更改(应用程序的每次启动)。因此,如果未打开应用程序,则令牌不会更改。您可以在最后尝试,并在此处确认。 这对我来说很棒。在我的情况下,当用户安装应用程序时,我会收到 3-5 天的通知。如果用户 4-5 天不使用应用程序。我没有收到任何推送通知。知道我出了什么问题吗?【参考方案10】:

查看您是否已卸载该应用并修改了您的设备令牌。更新设备令牌,你的错误就会消失

【讨论】:

【参考方案11】:

这是客户端(设备)问题,而不是服务端问题。 多种情况可能会导致这种情况:

如果客户端应用取消注册 GCM。 如果客户端应用程序自动取消注册,如果用户卸载应用程序可能会发生这种情况。例如,在 iOS 上,如果 APNS 反馈服务 报告 APNS 令牌无效。 如果注册令牌过期(例如,Google 可能决定刷新注册令牌,或者 iOS 设备的 APNS 令牌已过期)。 如果客户端应用已更新,但新版本未配置为接收消息。

见https://developers.google.com/cloud-messaging/http-server-ref

在应用启动时,我检查本地存储的令牌是否与新令牌匹配。如果没有,那么我会刷新服务器上的令牌。我也在FirebaseInstanceIDService::onTokenRefresh 中这样做。

【讨论】:

***.com/questions/51123197/…【参考方案12】:

根据文档,因为移动设备测试不再安装您的应用程序

如果未注册,则应从 您的服务器数据库,因为该应用程序已从 设备,或客户端应用未配置为接收消息。

【讨论】:

不,不是这样的!!我已经在那里发送了多个通知!有些通知已成功发送,有些则出现 NotRegistered 错误。在这两种情况下,应用程序都安装在设备中。 "有些通知发送成功,有些有 NotRegistered 错误。" -> 有同样的问题@ShashankShah,如果你有工作可以分享一下吗?【参考方案13】:

对php不太了解,但最近我在另一个项目中遇到了同样的问题,我是这样解决的:

首先参考这个: Where can I find the API KEY for Firebase Cloud Messaging?

并获取更新的 API 密钥,如下图所示:snapshot

【讨论】:

@maddy 这对我不起作用。我在发出请求时更改了服务器密钥,但仍然出现同样的错误。 @AIon,从 firebase 控制台发送测试通知,如果它正常工作,那么问题可能出在您这边。

以上是关于FCM 推送通知问题:“错误”:“未注册”的主要内容,如果未能解决你的问题,请参考以下文章

FCm 错误 = 在 reactjs 中的推送通知上缺少注册?

使用 FCM 推送通知时颤动中的 Kotlin 文件错误

如何使用 FCM 在颤振中推送通知

FCM iOS:推送通知抛出无效参数

使用 FCM 推送通知 IOS

带有 FCM 推送通知的 Safari [重复]