しがないエンジニアのブログ

技術的な内容をメモ代わりにつらつら

Google Cloud Messaging(GCM)からFirebase Cloud Messaging(FCM)への移行(android)

GCM/FCMとは

GCMとは、android端末のpush通知をサポートするクラウドサービスのこと
しかし、GCMは2019.4.11でサポートが完全に停止する

そのかわり、googleは新しくFCMの利用を呼びかけている
またFCMはandroidだけでなく、iOSもサポート対応のクロスプラットフォームである

移行のきっかけ

なぜ移行しようという話になったのかだが、サポート終了するっていうのは調べ始めてから発覚したこと。
そもそもの理由としては、targetSdkVersion 26以上じゃないとだめだよっていうgoogleのお達しがあったので、バージョンあげたことが発端だった。
2018年8月からtargetSdkVersionをAPIレベル26(Android 8.0)以上にする必要がある

バージョンアップをしたところ、バックグラウンドでの通知が届かなくなってしまったのである。
アプリが開いている状態なら問題なく通知が届くのだが、アプリを終了すると以下のようにエラーがでて落ちてしまっていた。

f:id:turgure:20180904182731p:plain:w300

そしてログもめっちゃ吐かれてた

09-03 16:30:23.564 27698-27698/your-package E/AndroidRuntime: FATAL EXCEPTION: main
    Process: your-package, PID: 27698
    java.lang.RuntimeException: Unable to start receiver com.google.android.gcm.GCMBroadcastReceiver: java.lang.IllegalStateException: Not allowed to start service Intent { act=com.google.android.c2dm.intent.RECEIVE flg=0x1000010 pkg=your-package cmp=your-package/.GCMIntentService (has extras) }: app is in background uid UidRecord{a11f8da u0a520 RCVR idle procs:1 seq(0,0,0)}
        at android.app.ActivityThread.handleReceiver(ActivityThread.java:3267)
        ...

社内の人に相談したところ、「FCM使ってますけどそんなの見たことないですよ?」って言われたので、FCMに移行することにした。

移行の手順

基本的には以下のURLの通りに進めれば問題ない
Migrate a GCM Client App for Android to Firebase Cloud Messaging  |  Cloud Messaging  |  Google Developers

1 . 以下のURLからfirebaseプロジェクトの作成
  https://console.firebase.google.com

google-services.jsonをプロジェクトに追加する必要があるため、その手順

1.1. 対象のプラットフォームを選ぶ(この記事ではandroidを扱う)
f:id:turgure:20180904174238p:plain:w400

1.2. 必要事項の入力
f:id:turgure:20180904171149p:plain:w400

証明書の確認は以下のように行う

$ keytool -v -list -alias androiddebugkey -keystore ~/.android/debug.keystore
$ keytool -v -list -alias <your-key-name> -keystore <path-to-production-keystore>

https://developers.google.com/android/guides/client-auth

1.3. google-services.jsonをダウンロード
  app/直下に配置する
f:id:turgure:20180904171615p:plain:w400

1.4. それぞれのbuild.gradeに追記してsync
  最新のバージョンがあればandroid studioが教えてくれるのでそれに合わせる
f:id:turgure:20180904171857p:plain:w400

1.5. アプリを実行、同期確認
f:id:turgure:20180904172228p:plain:w400

2 . build.gradleの変更
3 . AndroidManifest.xmlの変更

自分が行ったものをdiff形式でぺたり

4 . server endpointsの変更

https://android.googleapis.com/gcm/send

http://fcm.googleapis.com/fcm/send

に変更

5 . その他設定
  それぞれの実装状況に合わせて対応部分を修正

自分の所属プロジェクトでは、真ん中の
Optional: migrate your GcmListenerService
が修正対象でした

簡単に説明すると、AndroidManifest.xmlの変更と、serviceの変更

remoteMessageからデータを取得するとき、一般的な記事ではgetNotification()とかを使ったら値がnullになっていた
そこで、従来どおりintent経由で取得する方法として、toIntent()というまさに求めていた機能があったのでこれを利用
(あとで確認したらgetData()の方にはデータが入ってたのでこっち使ったほうがいいかも?)

Bundle extras = intent.getExtras();

Bundle extras = remoteMessage.toIntent().getExtras();

認証まわりはPHPを使ってたので元から特に書いてなかった

これで無事に今までどおり通知が届くようになった


参考URL