【问题标题】:InvalidRegistration error in Firebase Cloud Messaging for Android适用于 Android 的 Firebase 云消息传递中的 InvalidRegistration 错误
【发布时间】:2017-01-29 14:08:24
【问题描述】:

我正在开发一个使用推送通知功能的 Android 应用程序。我需要从服务器推送。我为此使用 Firebase。坦率地说,这是我第一次使用 Firebase。我是 Firebase 的新手。但是当我使用 PHP 和 CURL 从服务器推送时,它给了我无效的注册错误。

我像这样在 Android 中获得 Firebase 令牌

String token = FirebaseInstanceId.getInstance().getToken();

然后我将该令牌发送到服务器并保存在数据库中。

在服务器,我是这样推的

class Pusher extends REST_Controller {

    function __construct()
    {
        parent::__construct();
    }

    public function notification_get()
    {
        $rows = $this->db->get('device_registration')->result();
        $tokens= array();
        if(count($rows)>0)
        {
            foreach($rows as $row)
            {
                $tokens[] = $row->token;
            }
        }
        $message = array("message"=>"FCM PUSH NOTIFICATION TESTING");
        if(count($tokens)>0)
        {
            $result = $this->send_notification($tokens,$message);
            if(!$result)
            {
                die("Unable to send");
            }
            else{
                $this->response($result, REST_Controller::HTTP_OK);
            }
        }

    }

    function send_notification($tokens,$message)
    {
        $url = 'https://fcm.googleapis.com/fcm/send';
        $fields = array(
                'registration_ids'=>$tokens,
                'data'=>$message
            );

        $headers = array(
                'Authorization:key = AIzaSyApyfgXsNQ3dFTGWR6ns_9pttr694VDe5M',//Server key from firebase
                '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_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($fields));
        $result = curl_exec($ch);
        if($result==FALSE)
        {
            return FALSE;
        }
        curl_close($ch);
        return $result;
    }
}

我正在使用 CodeIgniter 3 框架来构建 Rest API。当我从浏览器推送访问 url 时,它返回带有错误的 JSON 数据,如下图所示。

如您所见,它给出了 InvalidRegistration 错误,并且消息未推送到设备。我的代码有什么问题?

附加

这是我在 android 中显示通知的 FirebaseMessagingService 类

public class FirebaseMessagingService extends com.google.firebase.messaging.FirebaseMessagingService {

    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        super.onMessageReceived(remoteMessage);
        showNotification(remoteMessage.getData().get("message"));
    }

    private void showNotification(String message)
    {
        Intent i = new Intent(this,MainActivity.class);
        i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);

        PendingIntent pendingIntent = PendingIntent.getActivity(this,0,i,PendingIntent.FLAG_UPDATE_CURRENT);

        NotificationCompat.Builder builder = new NotificationCompat.Builder(this).setAutoCancel(true)
                .setContentTitle("FCM Test")
                .setContentText(message)
                .setSmallIcon(R.drawable.info)
                .setContentIntent(pendingIntent);

        NotificationManager manager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
        manager.notify(0,builder.build());
    }
}

【问题讨论】:

    标签: android codeigniter firebase push-notification firebase-cloud-messaging


    【解决方案1】:

    虽然我没有使用 codeigniter,但我在发送到 iOS 设备时遇到了 InvalidRegistration 错误,所以我想在这里分享我的解决方案。

    在将Notification message 发送到单个 设备令牌时,我必须在 PHP 中将 registration_ids 更改为 to,并确保该值to 是字符串而不是数组。

    改变这个:

    'registration_ids'=>$tokens,
    

    到这里:

    'to'=>$tokens[0],
    

    【讨论】:

    • 'to' 用于向一个用户发送通知,而 'registration_ids' 用于发送多个用户。我们可以计算 $tokens 的数量,然后据此设置 'to' 和 'registration_ids' 条件。感谢您提出这个问题。
    【解决方案2】:

    无效的注册 ID 检查注册 ID 的格式 你传递给服务器。确保它与注册 ID 匹配 手机收到 com.google.firebase.INSTANCE_ID_EVENT 意图并且你没有截断它或添加额外的 人物。当错误代码为 InvalidRegistration 时发生。

    请与应用端和你端检查完全相同的注册ID是否存储在移动应用程序通过onTokenRefresh方法接收它的服务器中。您应该收到与开发人员在FirebaseInstanceId.getInstance().getToken() 中获得的完全相同的注册令牌

    当我收到你的评论并且你已经更新了这里的代码时,你的代码有一些变化,它来自谷歌文档,它自己......

    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
    
        // TODO(developer): Handle FCM messages here.
        Log.d(TAG, "From: " + remoteMessage.getFrom());
    
        // Check if message contains a data payload.
        if (remoteMessage.getData().size() > 0) {
            Log.d(TAG, "Message data payload: " + remoteMessage.getData());
        }
    
        // Check if message contains a notification payload.
        if (remoteMessage.getNotification() != null) {
            Log.d(TAG, "Message Notification Body: " + remoteMessage.getNotification().getBody());
        }
    
        // Also if you intend on generating your own notifications as a result of a received FCM
        // message, here is where that should be initiated. See sendNotification method below.
    }
    

    Firebase 具有三种消息类型:

    通知消息:通知消息在后台运行或 前景。当应用程序在后台时,通知消息是 传送到系统托盘。如果应用程序在前台, 消息由 onMessageReceived() 或 didReceiveRemoteNotification 回调。这些本质上是 称为显示消息。

    数据消息:在Android平台上,数据消息可以工作 背景和前景。数据消息将由 onMessageReceived()。此处特定于平台的说明是:开 Android,数据payload可以在Intent中获取 启动您的活动。

    同时包含通知和数据负载的消息:在 后台,应用程序在通知中接收通知负载 托盘,并且仅在用户点击托盘时处理数据负载 通知。在前台时,您的应用会收到一条消息 两个有效载荷都可用的对象。其次,click_action 参数通常用于通知负载而不是数据 有效载荷。如果在数据负载中使用,此参数将被处理 作为自定义键值对,因此您需要实现 使其按预期工作的自定义逻辑。

    【讨论】:

    • 啊,是的。在我的数据库中,有一行带有无效令牌。我得到成功返回 "{\"multicast_id\":8042731220476088762,\"success\":1,\"failure\":0,\"canonical_ids\":0,\"results\":[{\"message_id\ ":\"0:1474456734183863%97da1d69f9fd7ecd\"}]}"。但设备没有收到通知。
    • 您在哪个平台上没有收到通知?
    • 在安卓上。我没有收到任何通知。
    • 我刚刚添加了代码。该类也在清单文件中声明。
    • 但是我没有对该类做任何事情,因为我认为在清单文件中声明就足够了。是吗?
    【解决方案3】:

    对于 Android 中的 Java 不要使用 FirebaseInstallation 生成令牌我不知道为什么,但它没有返回有效的令牌。每次尝试通过 FCM REST API 发布时收到“InvalidRegistration”。

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

    }

    改用这个:

    if (firebaseUser != null) {
            FirebaseInstanceId.getInstance().getInstanceId()
                    .addOnCompleteListener(task -> {
                        if (!task.isSuccessful()) {
                            Log.d(TAG, "getInstanceId failed", task.getException());
                            return;
                        }
                        if (task.getResult() != null) updateToken(task.getResult().getToken());
                    });
    
        }
    
     private void updateToken(String refreshToken) {
        DocumentReference documentReference;
        Token token1 = new Token(refreshToken);//just a class with str field
        Map<String, Object> tokenMAp = new HashMap<>();
        tokenMAp.put("tokenKey", token1.getToken());
        Log.d(TAG, "updateToken: " + token1.getToken());
        String id = firebaseUser.getUid();
       
            baseref=sp.getString(BASE_REF,DEFAULT);
            documentReference= FirebaseFirestore.getInstance().document(baseref);
            updateDocWithToken(documentReference,tokenMAp);
        }
    private void updateDocWithToken(DocumentReference documentReference, Map<String, Object> tokenMAp) {
        documentReference.set(tokenMAp, SetOptions.merge());
    }
    

    【讨论】:

      猜你喜欢
      • 2018-02-06
      • 1970-01-01
      • 2017-04-25
      • 2012-11-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多