皆さんGoogle Homeは購入しましたか?
自分は miniだけ購入して、音楽再生や天気を教えてもらうなどデフォルトの機能を使っています。
音楽再生にはSpotifyで連携しています。Google Homeで再生中のとき、スマホに再生中の通知が表示されます。
今回のテーマはその通知です。
Google Homeが表示する通知が地味にリッチなので真似出来ないかなと思い、実装方法を調査しました。
こんな通知。展開したり折りたたむと、アニメーションします。
NotificationCompat.Style
通知の種類はいくつか用意されています。
BigTextStyle
などは馴染みがあると思いますが、今回のSpotifyの通知は MediaStyle
というものでした。
音楽系のサービスで利用されている MediaStyle
と、通知領域をカスタムできる DecoratedCustomViewStyle
と DecoratedMediaCustomViewStyle
について紹介します。
Style
を変更するには NoficationCompat.Builder
で Style
を設定します。
builder.setStyle(NotificationCompat.BigTextStyle().also {
// Styleならではの記述
})
MediaStyle
MediaStyle
はSupport Library 26.0.0から v4 media-compat library
に移ったようです。なので依存関係に追加が必要です。
implementation "com.android.support:support-media-compat:27.0.2"
Styleは以下のようになります。 __android.support.v4.media.app
からimportする__ので注意が必要です。android.support.v4.app
と NotificationCompat
が被ります。
builder.setStyle(android.support.v4.media.app.NotificationCompat.MediaStyle()
.setShowActionsInCompactView(0)
)
MediaSession
が必要かと思いきや、無くても利用可能です。
通常の通知と異なり、 NotificationCompat.Builder#addAction
で__追加したActionは、通知領域の中に表示__されます。
MediaStyle#setShowActionsInCompactView
の引数で、compact
状態のときに表示するActionを指定できます。追加したAction順にintで指定します。
以下の例は、 setShowActionsInCompactView(0)
で、Actionを3つ追加したものです。
DecoratedCustomViewStyle
通知のViewは RemoteViews
を使うことでカスタムできますが、__バージョン間や端末による違いなどを考慮する必要__がでてきます。また、Actionが正しく表示されなくなります。
これらの問題を解決しつつ、カスタムできるStyleが DecoratedCustomViewStyle
です。
builder.setStyle(NotificationCompat.DecoratedCustomViewStyle())
カスタムViewを適応できる状態は3種類あります。
-
ContentView
- 通知領域で折りたたまれてる状態です。
- こちらを変更するには
NotificationCompat.Builder#setCustomContentView
を使います。 - __
NotificationCompat.Builder#setContent
は内部的にはDeprecated
になっている__ので利用しないようにしましょう。
-
BigContentView
- 通知領域で展開されてる状態です。
- こちらを変更するには
NotificationCompat.Builder#setCustomBigContentView
を使います。
-
HeadsUpContentView
- HeadsUp通知で表示されてる状態です。
- こちらを__設定していない場合は
ContentView
が表示__されます。 - こちらを変更するには
NotificationCompat.Builder#setCustomHeadsUpContentView
を使います。 - HeadUp通知の最大領域は、Nougat以降では148dpになるようです。
- それ以上カスタムViewで表示させようとすると見切れます。
比較するとわかりますが、デフォルトで用意される領域は残しつつカスタムViewが適応できる形です。
DecoratedCustomViewStyle | デフォルト |
---|---|
DecoratedMediaCustomViewStyle
DecoratedMediaCustomViewStyle
も MediaStyle
と同様に、 v4 media-compat library
から利用します。
Styleは以下のようになります。
builder.setStyle(android.support.v4.media.app.NotificationCompat.DecoratedMediaCustomViewStyle()
.setShowActionsInCompactView(0)
)
変更できる3つのViewを設定した状態が次のような状態です。
Actionがアイコンで表示されるため、若干テキストで表示できる領域が大きいです。
OSバージョンによる違い
エミュレータで試した結果なので利用する端末によっては違う可能性があります。
L | M | N | O |
---|---|---|---|
HeadsUp通知の条件
Oreoでは、Channelの設定でIMPORTANCE_HIGH
になってないと__通知のPriorityを変えたり、LEDや通知音を設定してもHeadsUpとして表示されません__。
背景色の変更
OreoからはViewのカスタムをしなくても背景色を変更できます。
NotificationCompat.Builder#setColorized
で変更できますが、以下のどちらかを満たす必要があります。
- ServiceからのForeground通知
-
MediaStyle
orDecoratedMediaCustomViewStyle
でMediaSession
を設定する
逆にNougatだと、どちらを設定しても背景色はそのままです。カスタムViewで背景色を変更すれば可能です。
Marshmallowだと、 NotificationCompat.Builder#setColor
だけで背景色がつきます。
Lollipopだと、Marshmallowと挙動似ていますがHeads Up通知には背景色がつきません。
###Heads Up通知の文字色
カスタムViewを当てた場合、MarshmallowとLollipopだと、Heads Up通知はデフォルトで白になる ので変更する際は注意が必要です。
###mipmapを使うとクラッシュする
Oreoで NotificationCompat.Builder#setSsmallIcon
に mipmap
のリソースを利用するとSystem UIがクラッシュします。
System UIを再起動しても、__通知が残っている限りクラッシュ__し続けます。
まとめ
Inboxのアプリ以外でも InboxStyle
を使っても良いように、__メディア再生を伴わないアプリで MediaStyle
を使っても__問題ありません。
__通知領域からアイコンでユーザにアクションを促したい場合__などはうまく使えると思います。NougatからActionで画像が利用できなくなったので、代替出来ると思います。
DecoratedなStyleを利用すれば、OSに馴染みつつカスタマイズできます。しかし、乱用してオレオレUIにして、ただただ他のアプリより目立つ風にしてしまうではなく、デザインガイドラインを読んで、意義に成り立つようなUIを設計してください。
リポジトリはこちらです。
参考
Revision 26.0.0 Release / Recent Support Library Revisions | Android Developers
Android N の通知 / Google Developers Japan
Heads-up notifications
/ Android Developers
Android 8.0 の機能と API / Android Developers
Android Oreo Notification Crashes System UI / Stack Overflow