Android Oでプッシュ通知が届かない時

## Android O の新機能 通知チャンネル（Notification Channel）に対応する

> Android 8.0 バージョンの SDK を対象としているアプリは、通知をユーザーに送信するために 1 つ以上の通知チャンネルを実装する必要があります。

チャネルを作らないと通知こなくなる。

#### 前提

- 通知の送信側　: Firabase Cloud Messaging (FCM)
- 端末 : Android O (8.0.0) 
    - API level 26

### 基本的なやり方はココを参考に
参考 : https://stackoverflow.com/questions/46784463/firebase-notification-is-not-working-on-android-o

#### 対応ポイント（ざっくり）

- Android OではNotification Channelが必須
- デフォルトのNotification Channelは `AndroidManifest.xml` で定義できる
- ・・がチャネルは `onMessageReceived()` で作成される
- FCMからのデータペイロードが `data`, `notification` 両方の場合、アプリがバックグラウンドにいると、通知はシステムトレイに届く
- システムトレイに届く前にチャネルを作っておかないといけない 


##### [蛇足] FCMのメッセージ（アプリがバックグラウンドの場合）の注意点

FCMから送られてくるjsonのデータ形式によって、動作が変わる
（最初の参考URLにあるstackoverflowの記述だと、dataペイロードがない場合にシステムトレイに届く、のように記載があるが、公式ドキュメントは以下。 dataとnotification両方ある場合にシステムトレイに届く）

参考 : https://firebase.google.com/docs/cloud-messaging/android/receive#handling_messages

| アプリの状態 | 通知 | データ ペイロード | 両方 |
| --- | --- | --- | --- |
| フォアグラウンド | onMessageReceived | onMessageReceived | onMessageReceived | 
| バックグラウンド | システムトレイ | onMessageReceived | 通知: システムトレイ インテントの追加部分にあるデータ | 

- 通知 : json に `notification` のみ
- データペイロード : json に `data` のみ
- 両方 : json に `notification`, `data` 両方含まれる


### FCMからのプッシュ通知

対応手順 : https://firebase.google.com/docs/cloud-messaging/android/client


#### FirebaseのSDKバージョンを確認する

Version 10.2.6で Notification Channel対応しているので、アプリの使っている Firebase バージョンを確認

```build.gradle
dependencies {
     compile 'com.google.firebase:firebase-messaging:11.8.0'
}
```

#### manifestを編集

マニフェストで指定できるのは、デフォルト通知のアイコン、色、チャネル

```AndroidManifest.xml
<meta-data
    android:name="com.google.firebase.messaging.default_notification_icon"
    android:resource="@drawable/ic_stat_ic_notification" />

<meta-data
    android:name="com.google.firebase.messaging.default_notification_color"
    android:resource="@color/colorAccent" />

<meta-data
    android:name="com.google.firebase.messaging.default_notification_channel_id"
    android:value="@string/default_notification_channel_id"/>
```

これらマニフェストで指定される値は FCM の notification に含まれるデータで上書きされる。

参考 : https://firebase.google.com/docs/cloud-messaging/http-server-ref

- チャネルIDは `android_channel_id` 

channel_idはマニフェストで指定しなくてもFCMがデフォルトの通知チャネルを作ってくれるっぽいけど、変なチャネル名になるらしい。

参考 : https://stackoverflow.com/questions/46047343/firebase-how-to-set-default-notification-channel-in-android-app

#### チャネルを作成

参考実装 : https://github.com/firebase/quickstart-android

MainActivityなどでチャネルを作成しておく（これ忘れると通知こない）

```java
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
  // Create channel to show notifications.
  String channelId  = getString(R.string.default_notification_channel_id);
  String channelName = getString(R.string.default_notification_channel_name);
  NotificationManager notificationManager = getSystemService(NotificationManager.class);
  notificationManager.createNotificationChannel(new NotificationChannel(channelId,
      channelName, NotificationManager.IMPORTANCE_LOW));
}
```

---

#### [補足] アプリのターゲットバージョンについて

https://www.gaprot.jp/pickup/old-tips/android-o/notification-channel

> また、targetSdkVersion で O 以上を指定してビルドする場合には、このチャンネルを一つ以上作成しないと、ユーザに通知が表示されなくなってしまうらしいので、ご注意ください。
O より前のバージョンをターゲットとしてビルドしたアプリを、O のユーザがインストールした場合はこの制限を気にする必要はありません。

チャネルを作成せずに、ターゲットバージョンだけ上げてしまうと、Android O端末でだけプッシュ通知が受信できなくなってしまう。
（アプリのターゲットSDKバージョンに次第で、Android O端末でも以前の通知方法で受信できるということでもある）

以下、Api Level26対応ならば以下のような感じ

```app/build.gradle
android {
  compileSdkVersion 26
  buildToolsVersion "26.0.2"
...
```

ここを変えると **このアプリはちゃんとAndroid O対応してるよ！** と表明することになるので、以下の他変更点にも留意。

https://developer.android.com/about/versions/oreo/android-8.0-migration.html