9
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

FirebaseAdvent Calendar 2017

Day 14

GCMからFCMへ移行する際の移行期間を考える

Last updated at Posted at 2017-12-13

「もともとGCMを使っていて、FCMに移行しなければならない」
こういった話が最近出てきているプロダクトは多いのではないでしょうか。

単純にGCMをFCMへ置き換えた場合、
アプリをアップデートしただけで起動していなかったらまだFCMのデバイストークンをサーバへ送っておらず、
かつGCMを辞めてしまっているので、Push通知を受け取る手段が無くなってしまいます。
(Receiverでアプリアップデートを検知してデバイストークンを送るようにする手段もありますが)

・GCMを使っている旧バージョンのユーザが
・自動アップデートなどでアプリをFCM版へアップデートし
・アプリを起動していない場合は
・GCMで通知を受け続けなければならない
と、このように考え、その中で私がハマった事についてお話します。

ちなみにこの対処は「GCMからFCMへの移行期間のみの対応」ですので、
FCM版アプリへの移行が完全に終われば不要となります。

起こった問題

  • 通知が2件来てしまう
    • 独自の通知とFCMの通知とダブルで出てしまう
    • FCMの通知をGCMが食ってしまう
    • GCMの通知をFCMが食ってしまう

これらの問題について、それぞれ解説していきます。

通知が2件出てきてしまう

問題点:独自の通知とFCMの通知が両方出てしまう

FCMでは、独自で通知の出力を実装せずともPush通知を出してくれます。
ただし、出してくれる条件は以下のように定義されています。
Firebase公式リファレンス:メッセージの処理
スクリーンショット 2017-12-01 15.58.07.png

この中で システムトレイ と書かれているところでは、FCMが自動でPush通知を出してくれます。
言い換えると、アプリを起動していない場合を除き、Push通知を出したい場合は独自で実装は必要になります。
(アプリを起動してバックグラウンドに回っている状態など)
ただ、独自で onMessageReceived に記載をして色々と試してみた所、Push通知がなぜか2件出てしまう事象となりました。

解決策:ダウンストリームメッセージにNotificationを含めてはならない

ユーザへ通知を出す際に独自のサーバを介する場合は、サーバからFCMへHTTPリクエストを出すことでユーザへPush通知を送信することが可能です。
その際にFCMへ出すリクエストに注意が必要です。
含められるリクエストの内容はこちらです。
Firebase公式リファレンス:ダウンストリーム メッセージの構文

独自に定義できるパラメータも含めた場合、ドキュメント通りに記載すると下記のようになります。

FcmDownStream.json
{
    "to": "[デバイストークン]",
    "notification": {
        "title": "ディズニー待ち時間",
        "body": "ディズニー待ち時間だといつでもどこでもパークの待ち時間が閲覧できます!",
        "icon": "icon_launcher",
        "color": "#f56df2"
    },
    "data": {
        "attractionId": "1",
        "type": "greeting",
        "waitTime": "180"
    }
}

ここで Notification を含めてしまうと、意図せずともFCMが勝手に通知を出してしまいます。
ということは、「独自のPush通知とFCMの通知が両方出てしまう」状態になります。
ですので、独自で出したい場合は Notification は含まないようにし、通知は全て独自で出すようにしましょう。

FCMとGCMと両方の通知が出てしまう

FCMの通知をGCMが食ってしまう

GCMの実装とFCMの実装が同時に存在すると
GCMのReceiverがFCMのイベントを食って、イベントを出してしまいます。

解決策:GCMから来たPush通知のイベントか否かを判断する

その為、GCMのイベントを捕まえるReceiverのクラスに、GCMから来たPush通知のイベントか否かの判断が必要です。

GcmBroadcastReceiver.java
public class GcmBroadcastReceiver extends WakefulBroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        String from = intent.getStringExtra("from");
        String fcmSenderId = "[FCMのSenderId]";
        if (fcmSenderId.equals(from)) {
            return;
        }

        // Push通知を出す処理
        // ...
    }
}

「GCMから来たイベントか?」はIntentの getStringExtra("from"); で取得できます。
ここでは「FCMから来たイベントの場合はその場でreturnする」としています。

こちらの記事で詳しく触れられています。
【Android】GCMとFCMを両方入れるとPush通知が2回届く問題

GCMの通知をFCMが食ってしまう

逆にFCMがGCMの通知を食ってしまうパターンも経験しました。

解決策:GCMから来たPush通知のイベントか否かを判断する

GCMが出してしまう時と同様の対策をします。

PictlinkFirebaseMessagingService.java
public class MyFirebaseMessagingService extends FirebaseMessagingService {
    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        super.onMessageReceived(remoteMessage);

        if ("[GCMのSenderId]".equals(remoteMessage.getFrom())) {
            return;
        }
        // 通知を出す処理
        // ...
    }

FcmからのPush通知に必要な情報は onMessageReceivedremoteMessage として渡されます。
GCMでのチェック同様に from で取れるので、 remoteMessage.getFrom() で判断します。

まとめ

  • 通知を独自で出したい場合はFCMへのHTTPリクエストに Notification は含まないようにしましょう!
  • GCMとFCMが混在する場合は、明示的に「自分自身の通知しか出さない」ようにしましょう!
9
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?