【Android】まだやってない人のためのGCMからFCMへの移行作業まとめ

# Android、GCMからFCMへの移行


Googleでは2018年4月10日より[GCM](https://developers.google.com/cloud-messaging/)を非推奨としています。GCMサーバーとクライアントAPIは非推奨となり、2019年4月11日に削除されることになっています。

FCMはもっとクールで最高なサービスです、移行しましょう👍

GCMからFCMへの移行に際して対応内容をまとめました、ご参考になれば
幸いです。

## Firebase Console でプロジェクトの登録

* [firebase console](https://console.firebase.google.com/u/0/)でプロジェクト作成しAndroidのプロジェクトでfirebase導入の設定を行う

>
①Firebaseコンソールで、[プロジェクトの追加]を選択します。
②既存のGoogle CloudプロジェクトのリストからGCMプロジェクトを選択し、[Add Firebase]を選択します。
③Firebaseのようこそ画面で、Android AppにFirebaseを追加を選択します。
④パッケージ名とSHA-1を入力し、[アプリケーションの追加]を選択します。 Firebaseアプリ用の新しいgoogle-services.jsonファイルがダウンロードされます。
⑤[続行]を選択し、AndroidStudioでGoogleサービスプラグインを追加し（firebaseで表示されいる）手順に従います。

[Migrate a GCM Client App for Android to Firebase Cloud Messaging](https://developers.google.com/cloud-messaging/android/android-migrate-fcm)

## gradleの修正

削除

```.java
dependencies {
  compile "com.google.android.gms:play-services-gcm:15.0.1"
}
```

追加

```.java
dependencies {
  compile "com.google.firebase:firebase-messaging:17.3.0"
}
```

## AndroidMAnifest.xmlの修正

### パーミッション削除

FCM SDKによって、必要なものはパーミッション設定を含め、自動的に追加されます。明示的に設定し重複することを避けるため、削除します。  
また、GcmReceiverが不要になるため削除します。

以下に相当する箇所を削除します。

```.java
<uses-permission android:name="android.permission.WAKE_LOCK" />
<permission android:name="<your-package-name>.permission.C2D_MESSAGE"
            android:protectionLevel="signature" />
<uses-permission android:name="<your-package-name>.permission.C2D_MESSAGE" />

...

<receiver
    android:name="com.google.android.gms.gcm.GcmReceiver"
    android:exported="true"
    android:permission="com.google.android.c2dm.permission.SEND" >
    <intent-filter>
        <action android:name="com.google.android.c2dm.intent.RECEIVE" />
        <category android:name="com.example.gcm" />
    </intent-filter>
</receiver>
```

###  GcmListenerServiceの記述を修正

変更前

```.java
<service
    android:name=".MyGcmListenerService"
    android:exported="false">
    <intent-filter>
        <action android:name="com.google.android.c2dm.intent.RECEIVE" />
    </intent-filter>
</service>
```

変更後

```.java
<service
    android:name=".MyFcmListenerService">
    <intent-filter>
        <action android:name="com.google.firebase.MESSAGING_EVENT" />
    </intent-filter>
</service>
```

<br>
補足
>android:exported  
アクティビティを他のアプリのコンポーネントから起動できるかどうか。起動できる場合は "true"、起動できない場合は "false" を設定します。"false" の場合、同じアプリまたは同じユーザー ID を持つアプリのコンポーネントからのみアクティビティを起動できます。

[Android Developer](https://developer.android.com/guide/topics/manifest/activity-element?hl=ja)

## 関連クラスの実装・修正

### GCMReceiverService.java の継承元をGcmListenerService から FirebaseMessagingService（メッセージ受信機能を担う） に変更

（変更前）MyGcmListenerService.java

```.java
public class MyGcmListenerService extends GcmListenerService {
  @Override
  public void onMessageReceived(String from, Bundle data){
    ...
  }

  ...
}
```

（変更後）MyFcmListenerService.java

```.java
public class MyFcmListenerService extends FirebaseMessagingService {
  @Override
  public void onMessageReceived(RemoteMessage message){
    String from = message.getFrom();
    Map data = message.getData();
  }
  ...
}
```

### トークン取得処理周りの実装をしている場合

FirebaseMessagingServiceにonNewTokenメソッドがあるのでそれを使用します。
FirebaseMessagingServiceを継承したクラスでonNewTokenメソッドをオーバーライドすることで対応できます。

```.java
class MyFirebaseMessagingService : FirebaseMessagingService() {
    override fun onNewToken(token: String?) {
        // tokenを使用した処理
    }
}
```

[FirebaseInstanceIdServiceがDeprecatedになった件
](https://qiita.com/keijumt/items/d45ea0da3dfa6284ad90)
[StackOverFlow FirebaseInstanceIdService is deprecated](https://stackoverflow.com/questions/51123197/firebaseinstanceidservice-is-deprecated)


トークンが生成される際の処理ですが、以前はFirebaseInstanceIdServiceクラス内にて対応していました。  
しかし、firebase-messaging:17.1.0からFirebaseInstanceIdServiceがdeprecatedになっているため現状は上記のような実装になっています。
>This class was deprecated.
In favour of overriding onNewToken in FirebaseMessagingService. Once that has been implemented, this service can be safely removed.

[FirebaseInstanceIdServiceに関する公式ドキュメント](https://firebase.google.com/docs/reference/android/com/google/firebase/iid/FirebaseInstanceIdService)


また、登録処理は不要になります  
明示的に登録トークンの生成を開始する必要はなくなりました。ライブラリが自動的に行ってくれます。したがって、次のようなコードも削除することができます。

```.java
  InstanceID instanceID = InstanceID.getInstance(this);
  String token = instanceID.getToken(getString(R.string.gcm_defaultSenderId),
          GoogleCloudMessaging.INSTANCE_ID_SCOPE, null);
  // [END get_token]
  Log.i(TAG, "GCM Registration Token: " + token);

```

また、現在のトークンを取得する際は以下のようにして取得することができます。

```.java
FirebaseInstanceId.getInstance().getInstanceId().addOnSuccessListener( new OnSuccessListener<InstanceIdResult>() {
            @Override
            public void onSuccess(InstanceIdResult instanceIdResult) {
                String deviceToken = instanceIdResult.getToken();
                Log.d("test", "現在の token: " + deviceToken);
            }
        });

```
[What to use now that FirebaseInstanceId.getInstance().getToken() is deprecated [duplicate]](https://stackoverflow.com/questions/51125169/what-to-use-now-that-firebaseinstanceid-getinstance-gettoken-is-deprecated/51342447)


## バックエンド側

* サーバーのEndpoint変更

【GCM Endpoint】
gcm-http.googleapis.com/gcm/
gcm-xmpp.googleapis.com

これらを下記に変更します  

【FCM Endpoint】
fcm.googleapis.com/fcm/
fcm-xmpp.googleapis.com

## 参考

* [Androidの新プッシュ通知FCMへの移行](http://blog.kotemaru.org/2016/05/28/android-fcm-sample.html)
* [Migrate a GCM Client App for Android to Firebase Cloud Messaging](https://developers.google.com/cloud-messaging/android/android-migrate-fcm)
* [Android Push通知 GCMからFCMに移行 #Android #Firebase](https://qiita.com/flatfisher/items/31f5c9e21ae56cccff8d)
* [Android で GCM から FCM に乗り換える](https://www.lanches.co.jp/blog/5513)