FCM推送通知问题:"error":"NotRegistered"

27

我在使用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"
19个回答

23

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

如果是NotRegistered,则应从您的服务器数据库中删除注册ID,因为该应用已从设备中卸载,或者客户端应用未配置接收消息。


2
不,情况并非如此!我已经发送了多个通知!其中一些通知已成功发送,而另一些则出现了“未注册”错误。在这两种情况下,应用程序都已安装在设备上。 - Shashank Shah
1
一些通知已成功发送,而一些则出现了“NotRegistered”错误。@ShashankShah也遇到了同样的问题,请问你有什么解决方法可以分享吗? - Nandam Mahesh
在搜索了4个四之后,我确定这是正确的答案。 - Dorbagna

21

1
@maddy,这对我没有起作用。我在发出请求时更改了服务器密钥,但仍然收到相同的错误。 - AIon
@AIon,从Firebase控制台发送一条测试通知,如果它能够正常工作,则问题可能在您这边。 - Maddy

11
这是一个客户端问题,而不是服务端问题。可能会有多种情况导致此问题:
  • 如果客户端应用程序取消注册 GCM。
  • 如果客户端应用程序被自动注销,这可能发生在用户卸载应用程序时。例如,在 iOS 上,如果 APNS 反馈服务报告 APNS 令牌无效。
  • 如果注册令牌过期(例如,Google 可能决定刷新注册令牌,或者针对 iOS 设备的 APNS 令牌已过期)。
  • 如果客户端应用程序已更新,但新版本未配置接收消息。
请参见https://developers.google.com/cloud-messaging/http-server-ref
在应用程序启动时,我检查存储本地的令牌是否与新令牌匹配。如果不匹配,则在我的服务器上刷新令牌。我也会在FirebaseInstanceIDService::onTokenRefresh中执行此操作。

https://dev59.com/71UK5IYBdhLWcg3w4jQv - Martin Zeitler

7

事实上,当应用程序首次运行时,Firebase 会为目标设备生成一个唯一的设备 ID,并将其用作设备的身份标识。

如果用户卸载应用程序或清除应用程序的数据,则在重新安装或重新打开应用程序时,设备 ID 将不同。这将导致 Firebase 无法识别该 ID 以发送通知。这将导致错误未注册


那就是答案,但你怎么修复它呢 :D - Dimitar
@Dimitar 请确保您将推送通知发送到当前已安装的应用程序。 - Mahesh Jamdade
你如何通过最新的FCM记录日期来实现这个? - Dimitar

3

我在卸载并重新安装应用程序后遇到了这个错误。

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

因此,我们必须先删除先前的实例ID,然后创建新的fcm令牌。请参见以下代码...

只需添加未注释的行即可解决我的问题。

有关代码解决方案,请参见第一个评论 :)

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

希望这对你有用!:)

4
_firebaseRegister() { // _firebaseMessaging.deleteInstanceID(); _firebaseMessaging.getToken().then((token) => fcmtoken = token); }该函数用于注册 Firebase 实例 ID,并获取推送通知的令牌(fcmtoken)。其中,注释部分代码为删除实例 ID 的操作。 - Sadhvik Chirunomula

2
在我的情况下,问题出现在接收方,而不是发送方。如果你向一个长时间未运行该应用的人发送消息,则他们的设备令牌就过期了。他们只需要重新启动应用程序即可。
在你的情况下,你是否确保在发送多个通知时,所有收到消息的设备都在运行中,并且应用程序通过调用FirebaseMessaging.getInstance().getToken()在启动时刷新令牌?

1
我的问题与以上所有问题都不同。我们尝试发送的Firebase消息超过了4Kb的最大大小限制。这很少会触发"NotRegistered"错误。但问题是,我记录了应用程序可能未安装的时刻。因此,请检查Firebase消息的大小。

1
我有一个百分之百的解决方案,最近我修复了这个问题。这个错误发生是因为你在发送通知到一个没有包含你的Firebase设置API密钥的设备上。例如,当你注册用户时,用户从不同的Firebase设置注册,所以你的Android令牌是不同的,并且你正在向其他Firebase设置发送请求,而那里没有创建你要发送通知(消息)的Android令牌,因此你必须确保你的用户Android令牌是从与你使用Firebase API密钥的项目相同的Firebase项目生成的。

5
如果有分段和标点符号,阅读起来会更加舒适。 - Zobayer Hasan

1

一个可能的解决方案是更新用户的推送令牌。当客户端应用程序更新(新版本),旧的推送令牌将被更改。


1

在我的情况下,两个克隆的模拟器是问题的原因。 我认为克隆的模拟器具有相同的设备ID,因此Firebase认为它们是同一台设备。 所以当一个设备收到推送消息时,推送令牌可能会被删除并返回“NotRegistered”。 如果您处于类似的情况,请尝试删除模拟器并创建新的模拟器。


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