Android

Android 5.0 LollipopでのNotificationについて

More than 1 year has passed since last update.

TechBooster冬コミ(C87)本用メモ
ちょくちょく主観的な解釈入ってるので注意

書いた本: 甘味アンドロイドパーク 第5章 「Android 5.0でのNotification」
http://techbooster.github.io/c87/#park
現在、BOOTHCOMIC ZINでお求め頂けます。

Android Lollipop 概要 - Notifications

http://developer.android.com/intl/ja/about/versions/lollipop.html#Notifications
和訳: http://firespeed.org/diary.php?diary=kenz-1783

↓の実現のためNotificationにカテゴリや優先度というプロパティが追加された

  • ユーザーはNotificationの詳細をロックスクリーンで表示できる。
  • 重要なNotificationのアラートはHeads-up Notificationで表示される。
    これまでは画面を専有して通知を表示していた。
  • 優先度などのためにNotificationと連絡先を結びつけるメタデータを持つようになった。
  • 新しいMediaのNotificationでは、Thumbs upの様なカスタムコントロールを最大6つのActionボタンと一貫性のあるメディアコントロールを提供する。
    もうRemoteViewで頑張らなくていい。
    ※多分MediaStyleのこと言ってるんだけど、Actionボタンは最大5つだった。
    ※MediaControlClientを動かなくしたから、ロックスクリーン上のNotificationでメディア再生のコントロールを提供するようにしろよ。便利なMediaStyleも用意したぞ。という意味。

Android 5.0 APIs | Android Developers

http://developer.android.com/intl/ja/about/versions/android-5.0.html#Notifications

なんちゃって和訳↓

Notifications

ロックスクリーンNotification

Android 5.0 のロックスクリーンはNotificationを表示できるようになりました。
セキュアなロックスクリーン上でsensitiveなNotificationを表示するかどうかを、ユーザーは設定画面で選択することが出来ます。

セキュアロックスクリーン上で表示されるNotificationは、その詳細表示レベルをアプリで制御すること出来ます。表示レベルを制御するためには、 setVisibility() で以下の値を設定します:

  • VISIBILITY_PRIVATE: 全ての内容を表示せず、アイコンなどの基本的な情報のみ表示します(訳注: これがデフォルトです)。
  • VISIBILITY_PUBLIC: 全ての内容を表示します。
  • VISIBILITY_SECRET: 何も表示しません。アイコンすら。

表示レベルがVISIBILITY_PRIVATEの場合、私的な詳細を隠した編集済みのNotificationを代わりに表示する事ができます。
例えば、SMSアプリはメッセージの内容や送信者を隠して「3件の新しいメッセージがあります」というNotificationを表示するべきです。
この代替のNotificationを表示させるには、まず置き換え用のNotificationをNotification.Builderで作ります。そして、普通のプライベートな情報を含んだNotificationを作る時に、置き換え用のNotificationをsetPublicVersion()メソッドで添付します。

Notificationのメタデータ

Android5.0では、より賢くNotificationをソートするために、Notificationのメタデータを使用します。メタデータを設定するには、Notificationを作るときにNotification.Builderの以下のメソッドを使用します:

  • setCategory(): デバイスが重要モードの場合に、Notificationをどう制御するかをシステムに知らせます(例えば、電話着信やインスタントメッセージ、アラームを表示するかどうか)。
  • setPriority(): 通常のNotificationに比べて、重要か重要でないかを設定します。通知音やバイブレーション付きのNotificationの場合には、重要度がPRIORITY_MAXまたはPRIORITY_HIGHに設定されたNotificationが、小さなフローティングウィンドウで表示されます。
  • addPerson(): Notificationに関連する一人または複数の人物(訳注: 連絡先データ)をNotificationに追加することを可能にします。これを使うことで、設定された人物でNotificationをグループ分けしたり、その人物がより重要かどうかでNotificationをランク付けしたりをシステムにさせる事ができます。

Notifications | Android 5.0 Changes | Android Developers

https://developer.android.com/intl/ja/about/versions/android-5.0-changes.html#BehaviorNotifications
和訳: http://firespeed.org/diary.php?diary=kenz-1784

※ targetSdkVersion = 21 の場合の振る舞い

Notification

Material Designスタイル

Material DesignのNotificationは白地に黒字になる。
表示に問題がある場合は以下の方法でfixする

  • setColor()でアイコン画像の後ろに円形のアクセントカラーを設定できる。
  • 色のあるアセットを削除する。システムはメインのNotificationアイコンにおいては非アルファチャンネルを無視します。
    ※アルファチャンネルでマスクして白単色のアイコンを自動生成する。 ※ただし、特定状況下で色付きのまま表示されてしまうバグがある。 https://code.google.com/p/android/issues/detail?id=81220

音とバイブレーション

  • Ringtone, MediaPlayer, Vibrator を使ったコードは削除する。
    代わりにNotification.Builderに増えたメソッドで設定する。
    • これで重要モードが正しく動作する
  • RingerModeをRINGER_MODE_SILENTに設定すると、端末が重要モードになる。
    • RINGER_MODE_NORMAL, RINGER_MODE_VIBLATEすに設定すると重要モードを離れる。
  • これまではタブレットではSTREAM_MUSICをマスターストリームとして音量コントロールしていました。
    5.0からは電話とタブレットととでマスターストリームは統一され、STREAM_RING, STREAM_NOTIFICATIONでコントロールされます。

ロックスクリーンでの可視性

※他と内容かぶってるので割愛

メディア再生

Heads-up Notification

端末がアクティブ(ロック解除状態&ディスプレイ点灯中)な状態の時、Notificationは、Heads-up Notificationと呼ばれる小さなウィンドウとして表示される事があります。
アクションボタンが表示されることを除けば、普通のコンパクトなNotificationと同じように表示されます。
ユーザーは現在のアプリを離れることなく、Heads-up Notificationからアクションを実行したり、単に消したり出来ます。

Heads-up Notifictonのトリガーとなる例は以下です。

  • fullScreenIntentを使用している
  • 高いpriorityを持ち、通知音またはバイブレーションが設定されている

あなたのアプリがこれらの条件に従ってNotificationを実装していれば、Heads-up Notificationが正しく表示されるでしょう。

※ fullScreenIntentは、Notificationを表示するのではなく、電話着信時やアラーム時に即時に画面遷移させるための機能。
 同じNotificationを投げても、5.0では、画面遷移せず、Heads-up Notificationとして表示される事になる。

メディアコントロールとRemoteControlClient

RemoteControlClientクラスはdeprecatedです。できるだけ早く新しいMediaSession APIに切り替えてください。

Android 5.0のロックスクリーンにはもうメディアコントロールは表示されません。
代わりに、ロックスクリーン上ではNotificationでコントロールができます。
ロック解除状態に関係なく一貫したエクスペリエンスを提供しながら、複数のメディアボタンの表示を制御できます。

Android 5.0では上記のためにMediaStyleが提供されます。
以下略

Notifications | Android Developers

http://developer.android.com/intl/ja/design/patterns/notifications.html

※ 5.0のことだけじゃなく、Notification全体のことが書いてある。

New in Android 5.0

  • Material Designで一貫性のある視覚的効果を得た
  • ロックスクリーンで表示できる。sensitiveな情報は隠せる。
  • 重要度の高い通知はHeads-up Notificationで表示されるようになった。
  • 通知のクラウド同期: ある通知を1つのデバイスで閉じると、他の自分のデバイスでも閉じてくれる。

Notification解剖学

※ WearのNotificationのことも書いてあったけど割愛

ベースレイアウト

Notificationは少なくとも以下の要素を持つ。

  • アプリのアイコン
  • タイトルやテキスト
  • タイムスタンプ

あとは写真(Large Icon)とか。

Notification.Builder で旧バージョン向けに作っているNotificationは、ちょっとは変わるが基本的にAndroid 5.0同じように表示される。

※ 原文の説明画像でNotification IconってなってるのはSmallIcon

拡張レイアウト

  • ベースレイアウトより、もうちょっと詳細な情報を表示できる。
  • 数行のメッセージや画像のプレビューなど。なんならメッセージ全体を読める。
  • ピンチアウトとか指スライドでNotificationを広げられる。
  • single-eventのために、3つのテンプレート(TEXT, INBOX, IMAGE)がある。

Actions

Notificationの下部にAction(のボタン)を表示できる。ユーザーはアプリを開かずにcommonなアクションを行える。

  • Actionは最大3つ
  • アイコンとラベルを設定できる
  • 拡張レイアウトじゃなくてもActionを設定すると広げられるようになる
  • Actionのボタンは通常隠れているので、それらの操作がアプリ内からも普通に行えること

なんでもNotificationから出来るようにするのではなく、最小限common(共通的、汎用的、一般的)な操作のみにする。

良い例

  • 表示しているコンテンツのタイプに対して、必要不可欠だったり、頻繁に使われ、かつ典型的なもの
  • ユーザーが作業を素早くこなせるようにするためのものであること

悪い例

  • 曖昧である
  • 単にNotificationをタップした時と同じ様な操作(対象を表示したり、とか)

Heads-up Notification

※Heads upは、頭上注意とか注意喚起とか、気をつけろって意味

Notificationのpriority(Android 4.1から増えたフィールド)がHighとかMaxとかになっていたり、フルスクリーンの場合、Heads-up Notificationになる。
優先度が高いNotificationが来たとき、拡張レイアウトが開いた状態と同じレイアウト(Actionが押せる状態)で短い時間表示される。時間を過ぎると消える。

Heads-up Notification の良い例

  • 操作中の電話着信
  • 操作中のアラーム
  • SMS受信
  • 電池残量が少ない時のアラート

これらの、4.4までは画面を専有したり邪魔したりして表示されていたものがHeads-up Notificationで表示されるようになる。

ガイドライン

personalに作りなさい

例えばメッセージ受信の場合、送信者の写真をLarge Iconを設定し、更に連絡先データを添付する(5.0ではNotificationに連絡先を関連付けできる)。

正しい場所へ案内しなさい
  • Notificationを選択した時、アプリはそのNotificationに表示されていたデータをユーザーが見たり操作したり出来るべき。
  • 大抵の場合は単一のデータと対応する。
  • スタックされたNotificationの場合は、一覧やサマリの画面。
  • アプリのトップではない場所を開く場合は、バックキーでトップレベルへ戻れるようにバックスタックを作ること
    詳しくはNavigationデザインのドキュメント参照
    http://developer.android.com/intl/ja/design/patterns/navigation.html#into-your-app
正しく通知の優先順位を設定し、管理する

AndroidではNotificationに優先度フラグを持っています。
このフラグでNotificationがどのように表示されるかが変わります。

優先度 内容
MAX 緊急。他の作業よりも先に解決するべき致命的な事柄を通知する。 電話着信, 警報, カーナビのturn-by-turn表示
HIGH 重要。ユーザーにとって特に興味深いメッセージなど。 重要なメール, 参加中のチャット, SMS
DEFAULT 通常。特に何もない場合はこれ。 その他, 従来のNotification
LOW 後回し。通知されるべきだが、緊急でないもの。 アプリのアップデート
MIN 瑣末。必ずしも必要ではないもの。 期限切れイベント, サジェスト, 天気予報, 周辺情報

HIGH以上だと、Heads-up Notificationになる(※priorityだけじゃなく、他の条件も絡む)。
MINだと、ステータスバーに表示すらされず、通知領域を開かないと見られない。

※ 広告出しまくるアプリが、無闇矢鱈にMAXとかHIGHな通知を出してきて、アンインストールされまくる未来が見える。

適切な優先度設定をする方法

DEFAULT, HIGH, MAX はユーザーに割り込みをかけ、ユーザー操作を中断させてしまうリスクがある優先度レベル。
割り込みレベルは以下の基準

  • 他人を巻き込む
  • 時間が重要。その時である必要がある。
  • 現実のユーザーの行動に直ちに影響を及ぼす可能性がある

LOW, MIN はユーザーにとって価値がないわけではない。早急な対応が必要なかったり、気がついた時に通知を開いて見てみても意味があるものとか。
基準は以下

  • 他の人を巻き込まない
  • 時間に関係ない
  • ユーザーが興味をもつかもしれない
カテゴリを設定する

Notificationが規定のカテゴリのどれかに該当するなら、それを設定する。
通知領域ではその情報をNotificationのランク付けやフィルタリングに使用します。

カテゴリはNotificationクラス(またはNotificationCompatクラス)の定数を参照。
http://developer.android.com/intl/ja/reference/android/app/Notification.html

Notificationをサマろう

既に同じタイプのNotificationがある時は、単に新しいNotificationを作るのではなく、サマリーのNotificationにまとめよう。
サマリのNotificationではどんなメールがpendingされているかわかるような説明をつけること。
※ 例えば、GmailはメールのカテゴリごとにNotificationをサマリにしている。

拡張レイアウトを使って、サマリのNotificationを開くとそれぞれのNotificationの詳細を見せることも出来る。

Notificationはオプションにする

Notificationは常にユーザーが制御できるべきです。
ユーザーがNotificationを無効にしたり設定を変更したり出来るべきです。
アラート音やバイブレーションを使用するかどうかなどを、アプリの設定項目に追加してください。

他と異なるアイコンを使う

ちらっと通知バーを見るだけで、ユーザーはどんなNotificationがあるのか識別できるべきです。

  • プリリンストールのGoogle謹製アプリのNotificationアイコンを参考にしてね
  • Notificationアイコンのドキュメント
    http://developer.android.com/intl/ja/design/style/iconography.html#notification
  • ActionボタンのアイコンはActionBarのを参考に http://developer.android.com/intl/ja/design/style/iconography.html#action-bar
  • 細かいデザインのアイコンは見辛いし判別しづらいので、シンプルなアイコンを
  • 色で他のアプリと区別するような画像は駄目。透明な背景に白地の画像であること。
  • 画像はにアルファを使用しないこと。アンチエイリアスとか半透明とか駄目。
    システムはアルファチャンネルをマスクで使うので、不透明なピクセルだけの画像でないといけない。

※訳注: targetSdkVersionが21の場合、ステータスバーにはNotificationのsmallIconの画像をマスクして自動で白地画像にしたものが表示される。
※アルファチャンネルをいじった画像を使えばNotification上とステータスバー上で違う形の画像出せたりしないか?
※NotificationはsmallIcon設定しない場合はそもそも表示されなくなってしまう。

LEDを適切に使う
  • 代替の端末にLEDは載ってる
  • 優先度(MAX, HIGH, DEFAULT)はLEDを光らせないといけない
  • LOW, MINは光らせちゃ駄目。

ユーザーを気遣ったNotificationを作る

※ユーザーの事を考えない(邪魔な通知や困らせるような)Notificationはアカンぞ。ちゃんと設計しろよ、という話。

Notificationを表示する時
  • ユーザーの関心や焦点は保護されるべきリソースである。
  • ユーザーが注意したり焦点を合わせるという事は、ユーザーのリソースを使った上に、ユーザーの作業を中断させる事になると認識しなければならない。
  • 通知がユーザーの作業を中断さたりする事に正当性があるかどうか自問してみましょう。
  • 正当性が見当たらないなら、通知機能をオプトインにしたり、優先度フラグをMINやLOWに調整しましょう。
  • 他の人が関係するような即時的なイベントの場合はちゃんとNotificationを使いましょう
    • リアルタイムのチャット中
    • カレンダー上の登録イベント(カレンダーに登録するイベントは大抵他の人が絡む)
Notificationを表示しない時
  • 即時性が必要ではないNotificationはオプトイン出来るようにしましょう
    • 例えば、SNSの投稿はそもそも内容が非同期。今すぐ見なければいけないものではない。
  • 現在アプリ上で表示している内容に関連するNotificationは作成するべきじゃない
    • 直接画面に表示さえせればいい
    • 例えば、今表示中のチャットの新規投稿は画面上に追加で表示されれば良く、Notificationは不要。
  • 低レベルな事のためにユーザーに割り込まない
    • 例えば、情報を保存したり同期したり、アプリの更新など、別にユーザーが介在しなくてもいい事
  • アプリが自前でエラーから回復できるなら、わざわざNotificationを出してユーザーの注意を奪うことはない
  • 宣伝の通知は出すな。
    • 単に他のアプリを起動させるためだけのNotificationは出すな
    • 通知は、利便性や、即時性、新しい情報を提供するべき
  • ユーザーに自分のブランドを表示するだけの余計なNotificationは出さない
    • 継続してそうゆう情報を提供するのなら、ホーム画面ウィジェットを開発するのが良い手段だ

Notificationのインタラクション

ステータスバーにアイコンが表示されていて〜云々 ※割愛

実行中表示

音楽再生や、ファイルのダウンロードやエンコードなどの長い処理についての継続的な通知を表示する。
ユーザーが削除することは出来ない。

メディア再生操作
  • 5.0ではロックスクリーンでの再生コントロールがDeprecatedになり表示されなくなった(※マジで!?)
  • でもNotificationが表示されるので、そっちのボタンで操作する。
  • この方がアプリでより詳細に制御が行える。
  • ロック状態かどうか関係なく、一貫した操作方法を提供できるようにもなる。
ダイアログとToast
Ranking and ordering

Notificationは基本的に時間順に並び、アプリによって与えられた優先度フラグで特別に配慮された順になる。

Notificationはロックスクリーンの重要な要素であり、ディスプレイが点灯するたびに表示される。
ロックスクリーンは非常に狭いので、Notificationの重要度や関連性を識別することはこれまで以上に重要です。
このため、Andoidはより洗練された仕分けアルゴリズムをNotificationのために持ち、以下の内容を考慮します。

  • タイムスタンプとアプリによって設定された優先度
  • 最近、通知音やバイブレーションでユーザーを煩わせたかどうか
    (つまり、電話がノイズ(通知音・バイブレーション)を発した時、ユーザーは「何が起こった?」かを知りたい。ロックスクリーンは一目見てそれがわかるようになっているべきだ。)
  • EXTRA_PEOPLEでNotificationに人(連絡先)が追加されており、特に、お気に入り設定された連絡先かどうか。
    ※連絡先で★を付けてお気に入り登録されている人。

例えば、GmailのNotificationはデフォルトの優先度なので、インスタントメッセージアプリのメッセージ(のNotification)はその下に来るようにソートされます。
しかし、新しいメッセージを受信すると、一時的に先頭に並びます。

ロックスクリーン上で

ロックスクリーン上でNotificationが表示されるようになったため、ユーザーのプライバシーが特に重要な検討事項になりました。
Notificationはしばしばsensitiveな情報を持つので、ディスプレイを点灯させた人誰にでも表示されてはいけません。

  • セキュアなロックスクリーン(PIN、パターンロック、パスワード)を持つ端末の場合、publicとprivateの2つのインターフェイスを持っている事になります。
    • Publicインターフェイスはロックスクリーン上に表示されるので誰でも見ることが出来ます。
    • Privateインターフェイスはロックスクリーンの向こう側の世界です。デバイス認証したユーザーにのみ明らかにされます。
ロックスクリーンに表示された情報のコントロール

ロックスクリーン上に表示する情報をNotificationの可視性レベルで選択できます。
可視性レベルを制御するために、Notification.Builder.setVisibility()で設定された、下記のいずれかの値を使用します。

  • VISIBILITY_PUBLIC
    • Notificationの全ての内容を表示します。可視性レベルが設定されなかった場合の システム のデフォルトです。
  • VISIBILITY_PRIVATE
    • ロックスクリーン上には、詳細は表示されずに、このNotificationが存在することだけを表示します(アイコンとアプリ名のみが表示されます)。
    • 詳細なNotificationとは異なる、ロックスクリーンのための代替のNotificationを設定できます。
      • Notification.publicVersionフィールド
      • Notification.Builder.setPublicVersion(Notification)
    • 例えば、SMS着信の通知なら、通常の詳細な情報を載せたNotificationはロックを解除しなければ見られないが、ロックスクリーン上のpublicVersionでは詳細を隠して「3件の新着メッセージがあります」といった内容にすることが出来る。
  • VISIBILITY_SECRET
    • 何も表示しません。アイコンすら。

※PUBLICがデフォルトって書いてあるけど、これは端末のシステム設定で「すべての通知内容を表示する」がデフォルトになっているという意味っぽい。Notification自体のvisibilityのデフォルトはPRIVATE。

Android WearでのNotification

TODO

Android API Differences Report

http://developer.android.com/intl/ja/sdk/api_diff/21/changes/changes-summary.html

  • Notification
    • 増えた定数
      • CATEGORY_xxx
      • VISIBILITY_xxx
      • COLOR_DEFAULT
      • AUDIO_ATTRIBUTES_DEFAULT
      • EXTRA_BACKGROUND_IMAGE_URI
      • EXTRA_BIG_TEXT
      • EXTRA_COMPACT_ACTIONS
      • EXTRA_MEDIA_SESSION
      • EXTRA_TEMPLATE
      • INTENT_CATEGORY_NOTIFICATION_PREFERENCES
    • 増えたフィールド
      • category
      • visibility
      • color
      • audioAttributes
      • publicVersion
      • headsUpContentView
    • deprecated
      • STREAM_DEFAULT
      • audioStreamType
      • tickerView
  • Notification.Buillder
    • 削除されたメソッド
      • setSound(Uri, int)
    • 追加されたメソッド
      • setCategory
      • setVisibility
      • setColor
      • setSound(Uri, AudioAttributes)
      • setPublicVersion
      • addPerson
    • deprecated
      • setTicker

※tickerが出なくなったりしてる。

Notifications | Android Developers

http://developer.android.com/guide/topics/ui/notifiers/notifications.html

実装関係のドキュメント。

その他メモ

NOTIFICATION_PREFERENCES

Notification.INTENT_CATEGORY_NOTIFICATION_PREFERENCES は、通知関係の設定画面であることを示すIntent-Filterのカテゴリ。
これを登録しておくと、通知長押しでギア(設定)アイコンが出てくるようになる。アイコンを押すと、そのActivityへ遷移する。
ただのカテゴリなので、複数のIntent-Filterに設定できるが、AndroidManifest.xml上で最初の1つだけが活きる。

AndroidManifest.xml
...
<intent-filter>
    <action android:name="android.intent.action.MAIN"/>
    <category android:name="android.intent.category.NOTIFICATION_PREFERENCES"/>
</intent-filter>
...

tickerText

※本には「tickerTextはDeprecated」って書いたけど、ドキュメントを改めて見かえしたら違っていたコンチクショウ。この節は入稿後書き足し。

5.0でtickerTextはもう表示されませんが、Deprecatedになってはいません。
tickerTextはもうステータスバーに表示するものではなく、アクセシビリティサービス向けにNotification内容のサマリを知らせるもの、という位置づけになっている様です。

Notification#ticketText

https://developer.android.com/reference/android/app/Notification.html#tickerText

As of the L release, this text is no longer shown on screen,
but it is still useful to accessibility services (where it serves as an audible announcement of the notification's appearance).

↓なんちゃって和訳

L(Lollipop)のリリースでは、このテキスト(tickerText)はもう画面に表示されません。しかし、まだアクセシビリティサービスにとって便利です(Notificationを音声で教えてくれるなど)。

Notification.Builder#setTicker(CharSequence)

https://developer.android.com/reference/android/app/Notification.Builder.html#setTicker(java.lang.CharSequence)

Set the "ticker" text which is sent to accessibility services.

setTicker()も、「アクセシビリティサービスに送信するテキストを設定する」だけ、という説明になっています。
Lollipopより前のドキュメントでは、ステータスバーに表示される旨が書かれていました。

https://web.archive.org/web/20140625214640/http://developer.android.com/reference/android/app/Notification.Builder.html

Set the "ticker" text which is displayed in the status bar when the notification first arrives.

tickerView

Deprecatedではないのは、あくまでtickerTextです。
ステータスバー表示のためのtickerViewはDeprecatedになっています。

https://android.googlesource.com/platform/frameworks/base/+/android-5.0.2_r1/core/java/android/app/Notification.java#237

同じく Notification.Builder#setTicker(CharSequence, RemoteViews) も同じ理由でDeprecatedです。
※tickerTextとtickerViewを一緒に設定するメソッド

https://android.googlesource.com/platform/frameworks/base/+/android-5.0.2_r1/core/java/android/app/Notification.java#2193