[この記事は Ian Lake、デベロッパー アドボケートによる Android Developers Blog の記事 "Notifications in Android N " を元に翻訳・加筆したものです。詳しくは元記事をご覧ください。]
Android の通知の多くは、Android 向けアプリとユーザーとの間の成功の保証がないインタラクションであると言えます。快適なユーザー エクスペリエンスを実現するために、Android N では、通知の外観の変更、カスタムビューのサポート強化、ダイレクト リプライの機能拡張、新しい MessagingStyle、バンドル通知といった機能が追加されています。
新しい外観で同じ通知
最初にあげるべき最もわかりやすい変更点は、通知のデフォルトのルック アンド フィールが大きく変更されたことです。通知内に広がっていたさまざまなフィールドは、アプリのアイコンと名前が表示された新しいヘッダー行に格納されるようになります。この変更で、スペース内にタイトル、テキスト、大きなアイコンができるだけ目立つように表示されるようになっています。その結果、通知が少しだけ大きくなり、読みやすくなりました。
ヘッダーが 1 行になったことで、そこに表示される情報の重要性が増します。Android N では、デフォルトで時間が表示されなくなります。 メッセージング アプリのように時間が重要になる通知の場合では、setShowWhen(true) で時間の表示を有効化できます。さらに、コンテンツ情報や番号よりもサブテキストが優先されるようになります。Android N デバイスでは番号は表示されなくなり、以前のバージョンの Android でサブテキストがない場合に限り、コンテンツ情報が表示されます。いずれの場合でも、サブテキストには意味のある便利な情報を使用してください。たとえば、ユーザーが 1 つしかアカウントを持っていない場合は、サブテキストにアカウントのメールアドレスを表示しないようにします。
また、通知アクションのデザインも見直されており、通知の下に別のバーが表示されるようになっています。
新しい通知には、アイコンが表示されていないことにお気づきかもしれません。通知シェードの限られたスペースにアイコンを入れるのではなく、ラベルが大きくなっています。ただし、通知アクション アイコンは必須のままであり、古いバージョンの Android や Android Wear などのデバイスでは引き続き使用されます。
NotificationCompat.Builder やそこで提供されている標準スタイルを使って通知を構築している場合、コードを変更することなく、デフォルトで新しいルック アンド フィールが反映されます。
カスタムビューのサポート強化
上記の方法ではなく、カスタムの RemoteViews を使って通知を作成している場合、新しいスタイルに適応させるのは困難な場合があります。新しいヘッダー、展開動作、アクション、大きなアイコンは、通知のメインのテキストとタイトルとは別々の要素として配置されるため、すべての要素を提供できる新しい DecoratedCustomViewStyle と DecoratedMediaCustomViewStyle が導入されています。これによって、新しく追加された setCustomContentView() メソッドを利用してコンテンツ部分のみを作成すればいいようになっています。
また、今後ルック アンド フィールが変更されても、スタイルのアップデートはプラットフォーム側で行われ、アプリ側ではコードの変更が必要なくなるため、対応するのが簡単になります。
ダイレクト リプライ
通知アクションからは、既に Activity の起動に加え、Service や BroadcastReceiver によるバックグラウンドでの作業を行うことができるようになっています。今回はさらに、ダイレクト リプライ を使って通知アクション内でインライン テキスト入力が可能なアクションを作成できるようになりました。
ダイレクト リプライでは、もともと Android Wear 向けに導入されたものと同じ RemoteInput API を使用して、Action がユーザーから直接入力を受け取れるようになっています。
RemoteInput 自体には、キーなどの情報が含まれています。後ほど、このキーを使用して入力やユーザーが入力を開始する前に表示されるヒントのテキストを取得できます。
// Where should direct replies be put in the intent bundle (can be any string)
private static final String KEY_TEXT_REPLY = "key_text_reply";
// Create the RemoteInput specifying this key
String replyLabel = getString(R.string.reply_label);
RemoteInput remoteInput = new RemoteInput.Builder(KEY_TEXT_REPLY)
.setLabel(replyLabel)
.build();
構築した RemoteInput は、addRemoteInput() メソッドでアクションにアタッチすることができます。Android Wear 2.0 用にスマート リプライ の選択肢を生成する setAllowGeneratedReplies(true) を呼び出し、ユーザーがすばやく簡単に応答できるようにすることも検討するとよいでしょう。
// Add to your action, enabling Direct Reply for it
NotificationCompat.Action action =
new NotificationCompat.Action.Builder(R.drawable.reply, replyLabel, pendingIntent)
.addRemoteInput(remoteInput)
.setAllowGeneratedReplies(true)
.build();
なお、ダイレクト リプライをサポートしていない Marshmallow 以前のデバイスでは、Action に渡す pendingIntent は Activity である必要があります(ユーザーに応答を入力してもらうために、ロック画面を解除して Activity を開始し、入力フィールドにフォーカスを当てるためです)。Android N デバイスの場合は、ロック画面からでもバックグラウンドでテキスト入力を処理できるように、Service(別のスレッドで処理する必要がある場合)または BroadcastReceiver(UI スレッドで動作する場合)である必要があります(システム設定からは、ロックされたデバイスでのダイレクト リプライの有効、無効を制御することができます)。
その後、Service や BroadcastReceiver で RemoteInput.getResultsFromIntent() メソッドを使い、入力されたテキストを抽出できます。
private CharSequence getMessageText(Intent intent) {
Bundle remoteInput = RemoteInput.getResultsFromIntent(intent);
if (remoteInput != null) {
return remoteInput.getCharSequence(KEY_TEXT_REPLY);
}
return null;
}
テキストを処理した後は、通知を更新する必要があります 。これがトリガーとなって、ダイレクト リプライの UI が非表示になります。この際に、リプライが正常に受信され、処理されたことをユーザーが確認できるようにする必要があります。
ほとんどのテンプレートでは、この処理に新しく追加された setRemoteInputHistory() メソッドを使用しています。このメソッドは、通知の下部にリプライを追加します。他のユーザーのリプライなどによってメイン コンテンツが更新されるまでは、履歴にリプライを追加するようにします。
ただし、会話をやり取りするようなメッセージング アプリを開発している場合は、MessagingStyle を使用してメッセージを追加するとよいでしょう。
MessagingStyle
ダイレクト リプライと新しく追加された MessagingStyle は、継続的にやり取りされる会話の表示に最適です。
このスタイルは、addMessage() メソッドで追加できる複数のメッセージ用の組み込みフォーマットです。各メッセージには、テキスト本文、タイムスタンプ、メッセージの送信者を渡すことができます(これによってグループでの会話がしやすくなります)。
builder.setStyle(new NotificationCompat.MessagingStyle("Me")
.setConversationTitle("Team lunch")
.addMessage("Hi", timestampMillis1, null) // Pass in null for user.
.addMessage("What's up?", timestampMillis2, "Coworker")
.addMessage("Not much", timestampMillis3, null)
.addMessage("How about lunch?", timestampMillis4, "Coworker"));
このスタイルは、現在のユーザーのメッセージを区別して示し、その名前も表示(このケースでは「Me」を表示)することに特化しています。オプションで会話のタイトルも設定できます。BigTextStyle を使ってこれを手動で実現することもできますが、このスタイルを Android Wear 2.0 で使用すると、ユーザーは即座にインラインで応答を受信できます。展開した通知ビューを処理する手間が省けるため、Wear に完全対応したアプリを構築しなくてもシームレスな操作を提供できます。
バンドル通知
新しい外観、ダイレクト リプライ、MessagingStyle と、今までのあらゆるベスト プラクティス を活用して通知を作成した後は、全般的な通知の操作性について検討します。とりわけ、複数の通知を送信する(たとえば、継続する会話の 1 件ごとや、新しいメールのスレッドごとに通知する)場合はこれが重要になります。
バンドル通知 は、ユーザーが別の通知を参照している際に 1 件だけサマリーを表示したい場合にも、あるいはすべての通知を同時に処理したり、まとめられた通知を展開して個々の通知を処理したい場合にも最適です(これには、アクションやダイレクト リプライも含まれます)。
Android Wear で通知のスタック を開発したことがある場合、それとまったく同じ API を使うことができ、各通知に setGroup() を追加するだけで、通知を 1 つにまとめることができます。グループは 1 つに限る必要はないので、通知は好きなようにまとめることができます。たとえば、メールアプリではアカウントごとに通知をまとめるとよいかもしれません。
また、サマリー通知 を作成することも重要です。サマリー通知は、setGroupSummary(true) で指定できます。Marshmallow 以前のデバイスで表示される通知はサマリー通知のみ なので、(おわかりと思いますが)個々の通知をすべてまとめる必要があります。その際には、InboxStyle を使うとよいでしょう。ただしこれは必須ではありません。Android N 以上のデバイスでは、サマリー通知から一部の情報(サブテキスト、コンテンツ インテント、削除インテント)が抽出され、バンドル通知用の折りたたまれた通知になります。そのため、すべての API レベルでサマリー通知を作成する必要があります。
Android N デバイスでは、全般的なユーザー エクスペリエンスを改善するために、グループのない通知を 4 つ以上送信すると、自動的に通知がまとめられます 。
N は Notification(通知)の N
Android の通知は常に進化し続けています。Gingerbread のころのシングルタップ ターゲットから、展開可能な通知、アクション、MediaStyle、最新のダイレクト リプライやバンドル通知などの機能に至るまで、通知は Android の総合的なユーザー エクスペリエンスにおいて重要な役割を果たしています。
ぜひ、多くの新しいツール(と下方互換性を維持するための NotificationCompat )をご活用ください。#BuildBetterApps での皆様からの報告を楽しみにしています。
さらに情報を得るには、Android Development Patterns Collection をフォローしてください。
Posted by Yuichi Araki - Developer Relations Team