push通知の通知音を変更する

こんにちはm_saekiです。

push通知のサウンドを任意に変更する要望が仕事であり、記事も少ないし皆さんの助けになればと思い投稿します！
Android O対応はもちろんしているので安心して下さい。

# 環境
macOS : High Sierra
AndroidStudio : 3.3.1
kotlin : 1.3.21

# 事前に準備してほしいもの
1. Firebaseのセットアップ
2. サーバーキー、FCMで発行されるデバイストークン
3. push通知を送信できる環境(私は[Postman](https://www.getpostman.com/)から送信しました)

# 前提

push通知を受信した時に下記の値が返ってくる想定です！

```
"data" : {
    "title" : "titleだよ",
    "body" : "bodyだよ",
    "channel_name" : "channel_name_sound_1"
  }
```

# 要件

1. push通信で返ってきたchannel_nameからサウンドを切り分ける
2. channel_nameが想定外ならデフォルトのサウンドに設定する
3. Android O対応を行う

# 実装

## AndroidManifest.xml

Manifestには自分でカスタムするServiceクラスを定義します。

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

## src/build.gradle

```
dependencies {
  implementation 'com.google.firebase:firebase-auth:17.0.0'
  implementation 'com.google.firebase:firebase-messaging:18.0.0'
}
apply plugin: 'com.google.gms.google-services'
```

## app/build.gradle
```
repositories {
  google()
}
dependencies {
  classpath 'com.google.gms:google-services:4.2.0'
}
```


## MyService.kt

MyServiceクラスでの処理を細かく説明します

### onMessageReceived

この処理をoverrideすることによってpush通知の受け取りを行います。
他にもtoken発行時に呼び出される処理とかあるので気になる人はチェックして下さいmm

```
override fun onMessageReceived(remoteMessage: RemoteMessage?) {
    super.onMessageReceived(remoteMessage)
    remoteMessage?.data?.let {
        sendData(it)
    }
}
```

### createChannel

チャンネルグループ、チャンネルを作成する処理になります。
どちらも複数作成することができますので拡張性が高くなりましたねー
気になる方はこの辺をチェック！！[NotificationChannel](https://developer.android.com/reference/android/app/NotificationChannel)

```
private fun createChannel() {
        // Android O以上なら対応する
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            // 既にChannel Groupが作成されている場合は省く
            if (NotificationManagerCompat.from(this).getNotificationChannelGroup(channelGroupId) != null) return
        // チャンネルグループのインスタンス作成
            val group = NotificationChannelGroup(channelGroupId, channelGroupName)
            NotificationManagerCompat.from(this).createNotificationChannelGroup(group)

            // AudioAttributesの定義
            val audioAttributes = AudioAttributes.Builder()
                    .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
                    .setLegacyStreamType(AudioManager.STREAM_NOTIFICATION)
                    .build()

            // チャンネルのインスタンス作成
            val channel = NotificationChannel(channelId1, channelName1, NotificationManagerCompat.IMPORTANCE_DEFAULT)
                    .apply { setSound(channelSound, audioAttributes) }
            val default = NotificationChannel(channelId1, channelName1, NotificationManagerCompat.IMPORTANCE_DEFAULT)
                    .apply { setSound(Settings.System.DEFAULT_NOTIFICATION_URI, audioAttributes) }

            NotificationManagerCompat.from(this).createNotificationChannels(listOf(channel, default))
        }
    }
```

### createNotification

NotificationCompat.BuilderにchannelIdが必須になっているので注意しましょう！
O以下のサウンドの設定もこちらのビルダー処理で定義しないといけないのでめんどくさいですmm

```
// O以下の場合のハンドリング
// チャンネルの概念がないのでここでサウンドをセットしている
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
  setSound( when (channelId) {
    channelId1 -> { channelSound }
    else -> { Settings.System.DEFAULT_NOTIFICATION_URI }
  })
}
```

# 所管

全体のコードはこちらです
https://gist.github.com/m-saeki0926/26d88ac08afd94a1d9588fc93da863bb

Android Oからpush通知の仕様が変わりすぎてマジでびっくりです！！
記事が全然見当たらなかったので、push通知でサウンドを変更するなんて結構珍しいんですかね？？
この記事が困っているエンジニアの助けになれば幸いです！

最近アプリをリリースしたのでインストールして下さい!!
https://play.google.com/store/apps/details?id=com.youtoo.app