适用于Android的Firebase云消息传递中的InvalidRegistration错误

时间:2016-09-21 10:56:38

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

我正在开发一款使用推送通知功能的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数据,如下面的屏幕截图所示。

enter image description here

正如您所看到的,它提供了InvalidRegistration错误,并且未将消息推送到设备。我的代码出了什么问题?

其他

这是我的FirebaseMessagingService类,它在android

中显示通知
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());
    }
}

3 个答案:

答案 0 :(得分:3)

对于 Android 中的 Java 不要使用 FirebaseInstallation 生成令牌我不知道为什么,但它没有返回有效的令牌。每次尝试通过 FCM REST API POST 时收到“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());
}

答案 1 :(得分:2)

  

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

请与应用方和您方共同确认,移动设备上的应用程序在onTokenRefresh方法中将相同的注册ID存储在服务器中。您应该已经收到与FirebaseInstanceId.getInstance().getToken()

中的开发人员完全相同的注册令牌

当我收到您的评论并且您已经更新了代码时,您的代码中的一些更改是来自Google doc自己...

@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,可以在Intent中检索数据有效负载   发起你的活动。

     

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

答案 2 :(得分:1)

虽然我没有使用codeigniter,并且在发送到InvalidRegistration设备时遇到iOS错误,但我想我会分享我是如何解决这种情况的。

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

改变这个:

'registration_ids'=>$tokens,

对此:

'to'=>$tokens[0],