web-dev-qa-db-ja.com

Firebase Cloud MessagingのAndroidのInvalidRegistrationエラー

Androidプッシュ通知機能を使用するアプリを開発しています。サーバーからプッシュする必要があります。Firebaseを使用しています。率直に言って、Firebaseを使用するのはこれが初めてです。 。しかし、PHPとCURLを使用してサーバーからプッシュすると、無効な登録エラーが発生します。

FirebaseトークンをAndroidのように取得します

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;
    }
}

Rest APIの構築にCodeIgniter 3フレームワークを使用しています。ブラウザからアクセスするURLをプッシュすると、以下のスクリーンショットのようにエラーのあるJSONデータが返されます。

enter image description here

ご覧のとおり、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());
    }
}
6
Wai Yan Hein

無効な登録IDサーバーに渡す登録IDの形式を確認してください。電話がcom.google.firebase.INSTANCE_ID_EVENTインテントで受信する登録IDと一致していること、および切り捨てたり追加の文字を追加していないことを確認してください。エラーコードがInvalidRegistrationの場合に発生します。

モバイル側のアプリケーションがonTokenRefreshメソッドで受信するサーバーに、まったく同じ登録IDが保存されていることを、アプリ側とユーザー側の両方で確認してください。開発者がFirebaseInstanceId.getInstance().getToken()で取得したものとまったく同じ登録トークンを受け取っているはずです

私はあなたのコメントを得て、あなたがここでコードを更新したので、それはGoogle doc it selfからのものですあなたのコードのいくつかの変更です...

@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には3つのメッセージタイプがあります。

通知メッセージ:通知メッセージはバックグラウンドまたはフォアグラウンドで機能します。アプリがバックグラウンドにある場合、通知メッセージはシステムトレイに配信されます。アプリがフォアグラウンドにある場合、メッセージはonMessageReceived()またはdidReceiveRemoteNotificationコールバックによって処理されます。これらは基本的に表示メッセージと呼ばれるものです。

データメッセージ:オンAndroidプラットフォーム、データメッセージはバックグラウンドとフォアグラウンドで動作します。データメッセージはonMessageReceived()によって処理されます。ここでプラットフォーム固有の注意は:Androidでは、データペイロードはアクティビティの起動に使用されるインテントで取得できます。

通知とデータペイロードの両方を含むメッセージ:バックグラウンドでは、アプリは通知トレイで通知ペイロードを受け取り、ユーザーが通知をタップしたときにのみデータペイロードを処理します。フォアグラウンドでは、アプリは両方のペイロードが利用可能なメッセージオブジェクトを受け取ります。次に、click_actionパラメーターは、データペイロードではなく、通知ペイロードでよく使用されます。データペイロード内で使用する場合、このパラメーターはカスタムキーと値のペアとして扱われるため、意図したとおりに機能するにはカスタムロジックを実装する必要があります。

2
Arpit Patel

私はcodeigniterを使用しておらず、InvalidRegistrationデバイスへの送信中にiOSエラーが発生していましたが、ここで状況を解決する方法を共有すると思いました。

私はregistration_idsto in PHPに送信するときNotification messagesingleデバイストークン、およびtoの値が配列ではなく文字列であることを確認します。

これを変える:

'registration_ids'=>$tokens,

これに:

'to'=>$tokens[0],
4