Androidの通知を種別ごとにまとめる

投稿の練習がてら、通知のまとめ方を記載します。

## なにやる？
通知を一定数以上打つと
Android7.0~通知がこうなってしまうので・・・
<img width="230" alt="スクリーンショット 2018-12-09 13.53.16.png" src="https://qiita-image-store.s3.amazonaws.com/0/164446/79a29966-767f-0009-61bc-8a2be4466566.png">

これを種別ごとにまとめてみる

### とりあえず作ったコード
通知が受け取れればいいのでシンプルなもの。  

```kotlin
class MyFirebaseMessagingService : FirebaseMessagingService() {

    override fun onMessageReceived(remoteMessage: RemoteMessage?) {
        super.onMessageReceived(remoteMessage)

        remoteMessage ?: return

        val notification = remoteMessage.notification
        showNotification(notification?.title, notification?.body)
    }

    private fun showNotification(title: String?, body: String?) {

        val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
        val notification = NotificationCompat.Builder(this)
                .setContentTitle(title)
                .setContentText(body)
                .setSmallIcon(R.drawable.abc_ic_star_black_16dp)

        notificationManager.notify(Random().nextInt(100), notification.build())
    }
}
```

## 通知のまとめ方

### Android7.0  

#### 書き換えたコードがこちら
```kotlin
class MyFirebaseMessagingService : FirebaseMessagingService() {

    override fun onMessageReceived(remoteMessage: RemoteMessage?) {
        super.onMessageReceived(remoteMessage)

        remoteMessage ?: return

        val notification = remoteMessage.notification
        showNotification(notification?.title, notification?.body)
    }

    private fun showNotification(title: String?, body: String?) {

        val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager

        // 通知種別をタイトルから分類する
        val notificationType = NotificationType.getType(title)

        // 子の通知の生成と配信
        val notification = NotificationCompat.Builder(this)
                .setContentTitle(title)
                .setContentText(body)
                .setSmallIcon(R.drawable.abc_ic_star_black_16dp)
                .setGroup(notificationType.id)
        notificationManager.notify(Random().nextInt(100), notification.build())

        // グループごとにサマリーするための通知を生成配信する
        val groupSummaryNotification = NotificationCompat.Builder(this)
                .setContentTitle(title)
                .setSmallIcon(R.drawable.abc_ic_star_black_16dp)
                .setGroupSummary(true)
                .setGroup(notificationType.id)
        notificationManager.notify(notificationType.id.toInt(), groupSummaryNotification.build())
    }

    enum class NotificationType(val id: String, val title: String) {
        TEST1("0", "通知テスト1"),
        TEST2("1", "通知テスト2"),
        UNKNOWN("-1", "");

        companion object {
            fun getType(title: String?): NotificationType {
                NotificationType.values().forEach {
                    if (it.title == title) {
                        return it
                    }
                }
                return UNKNOWN
            }
        }
    }
}
```

#### 何をしてるか？

- `NotificationType`で通知の`Title`ごとに通知の種別を選定します。
- `notification`に対して、`setGroup`で通知種別ごとの`id`を登録します。
- 通知をまとめるためには、通知をまとめるための通知が必要なため、それ専用の通知を別途作成します(`groupSummaryNotification `)
- `groupSummaryNotification`に`setGroupSummary(true)`と`setGroup`で`notification`の`setGroup`と同じ`id`をセットする

以上で、通知をこのようにまとめることができます。

<img width="241" alt="スクリーンショット 2018-12-09 14.36.55.png" src="https://qiita-image-store.s3.amazonaws.com/0/164446/d860472a-5309-7df2-722a-e44148206f25.png">

### Android 8.0~
Android 8.0からは通知チャンネルの影響で、チャンネルを登録してても通知がうまくまとまらなくなる。  
理由はまとめる用の通知に対しても、チャンネル登録をする必要があるため。

ちなみに上記の`groupSummaryNotification`にチャンネル登録しないとこうなる。
<img width="228" alt="スクリーンショット 2018-12-09 15.42.32.png" src="https://qiita-image-store.s3.amazonaws.com/0/164446/9f7f72a3-f3c8-ac3e-1d15-82a0e87f3099.png">

バラバラ・・・

チャンネル登録すると・・・
<img width="236" alt="スクリーンショット 2018-12-09 15.46.32.png" src="https://qiita-image-store.s3.amazonaws.com/0/164446/8b925793-e688-ab04-46bb-331ea52329ec.png">

ちゃんと通知がまとまる。
コードはこんな感じ。

```kotlin
// 子の通知の生成と配信
val notification = NotificationCompat.Builder(this, notificationType.id)
        .setContentTitle(title)
        .setContentText(body)
        .setSmallIcon(R.drawable.abc_ic_star_black_16dp)
        .setGroup(notificationType.id)
notificationManager.notify(Random().nextInt(100), notification.build())

// グループごとにサマリーするための通知を生成配信する
val groupSummaryNotification = NotificationCompat.Builder(this, notificationType.id)
        .setContentTitle(title)
        .setSmallIcon(R.drawable.abc_ic_star_black_16dp)
        .setGroupSummary(true)
        .setGroup(notificationType.id)
notificationManager.notify(notificationType.id.toInt(), groupSummaryNotification.build())
```
`Builder`の第２引数にチャンネルIDをセットしただけ

以上となります。

## 参考

https://developer.android.com/training/notify-user/group