2014年7月10日木曜日

Android Wear に Notification で出来ること

参考

概要
  • スマホと Wear が接続されていると、Notification が Wear にも表示(同期)される。
  • Wear では通知はカードとして表示され、このカードが表示されるところを context stream という。
  • これまでの通知でももちろん Wear に表示されるが、Wear 用に Notification を拡張することができる。


Notification を作る

Notification の作成には NotificationCompat.Builder を使う。これで作っておけば、システムがかってにスマホと Wear で通知の見た目を変えてくれる。

通知の発行には NotificationManagerCompat を使う(NotificationManager ではなく)。



■ SmallIcon だけの Notification
  1. int notificationId = 001;  
  2.   
  3. NotificationCompat.Builder notificationBuilder =  
  4.         new NotificationCompat.Builder(this)  
  5.         .setSmallIcon(R.drawable.ic_notif);  
  6.   
  7. // Notification を発行  
  8. NotificationManagerCompat notificationManager =  
  9.         NotificationManagerCompat.from(this);  
  10. notificationManager.notify(notificationId, notificationBuilder.build());  
スマホ


Wear(左: ホーム画面、右: タップした状態)


Wearのカードの右上に表示されるアイコンは setSmallIcon() で指定したものではなく、アプリアイコンになる。 タップしたときの背景色はどこから来てるのかよくわからない。アプリアイコンのカラーパレット?



■ タイトルとメッセージありの Notification
  1. int notificationId = 001;  
  2.   
  3. NotificationCompat.Builder notificationBuilder =  
  4.         new NotificationCompat.Builder(this)  
  5.         .setSmallIcon(R.drawable.ic_notif)  
  6.         .setContentTitle("タイトル")  
  7.         .setContentText("メッセージ")  
  8.   
  9. // Notification を発行  
  10. NotificationManagerCompat notificationManager =  
  11.         NotificationManagerCompat.from(this);  
  12. notificationManager.notify(notificationId, notificationBuilder.build());  
スマホ


Wear(左: ホーム画面、右: タップした状態)




■ Content Intent ありの Notification
  1. int notificationId = 001;  
  2.   
  3. // Content Intent 用の PendingIntent を作成  
  4. Intent intent = new Intent(this, MainActivity.class);  
  5. PendingIntent pendingIntent = PendingIntent.getActivity(this0, intent, 0);  
  6.   
  7. NotificationCompat.Builder notificationBuilder =  
  8.         new NotificationCompat.Builder(this)  
  9.         .setSmallIcon(R.drawable.ic_notif)  
  10.         .setContentTitle("タイトル")  
  11.         .setContentText("メッセージ")  
  12.         .setContentIntent(pendingIntent);  
  13.   
  14. // Notification を発行  
  15. NotificationManagerCompat notificationManager =  
  16.         NotificationManagerCompat.from(this);  
  17. notificationManager.notify(notificationId, notificationBuilder.build());  
スマホ


Wear(左: ホーム画面、中央: タップした状態、右: タップしたあと左にスワイプ)


setContentIntent() で PendingIntent を指定すると、Open on phone(携帯で開く)が追加され、それをタップすると指定した PendingIntent が実行される。



■ InboxStyle の Notification
  1. Intent intent = new Intent(this, MainActivity.class);  
  2. PendingIntent pendingIntent = PendingIntent.getActivity(this0, intent, 0);  
  3.   
  4. NotificationCompat.Builder notificationBuilder =  
  5.         new NotificationCompat.Builder(this)  
  6.         .setSmallIcon(R.drawable.ic_notif)  
  7.         .setContentTitle("タイトル")  
  8.         .setContentText("メッセージ")  
  9.         .setContentIntent(pendingIntent)  
  10.         .setStyle(new NotificationCompat.InboxStyle()  
  11.             .addLine("1行目")  
  12.             .addLine("2行目")  
  13.             .setContentTitle("インボックス タイトル")  
  14.             .setSummaryText("+3 more"));  
  15.   
  16. // Notification を発行  
  17. NotificationManagerCompat notificationManager =  
  18.         NotificationManagerCompat.from(this);  
  19. notificationManager.notify(notificationId, notificationBuilder.build());  
スマホ


Wear(左: ホーム画面、中央: タップした状態、右: タップしたあと左にスワイプ)




■ BigTextStyle の Notification
  1. Intent intent = new Intent(this, MainActivity.class);  
  2. PendingIntent pendingIntent = PendingIntent.getActivity(this0, intent, 0);  
  3.   
  4. NotificationCompat.Builder notificationBuilder =  
  5.         new NotificationCompat.Builder(this)  
  6.         .setSmallIcon(R.drawable.ic_notif)  
  7.         .setContentTitle("タイトル")  
  8.         .setContentText("メッセージ")  
  9.         .setContentIntent(pendingIntent)  
  10.         .setStyle(new NotificationCompat.BigTextStyle()  
  11.             .bigText(getString(R.string.long_text)  
  12.             .setContentTitle("ビッグテキスト")  
  13.             .setSummaryText("サマリー"));  
  14.   
  15. // Notification を発行  
  16. NotificationManagerCompat notificationManager =  
  17.         NotificationManagerCompat.from(this);  
  18. notificationManager.notify(notificationId, notificationBuilder.build());  
スマホ(上: 閉じてる状態、下: 開いた状態)



Wear(上: ホーム画面、中: タップした状態、下: 中でタップすると全文が見れる)






■ BigPictureStyle の Notification
  1. Intent intent = new Intent(this, MainActivity.class);  
  2. PendingIntent pendingIntent = PendingIntent.getActivity(this0, intent, 0);  
  3.   
  4. NotificationCompat.Builder notificationBuilder =  
  5.         new NotificationCompat.Builder(this)  
  6.         .setSmallIcon(R.drawable.ic_notif)  
  7.         .setContentTitle("タイトル")  
  8.         .setContentText("メッセージ")  
  9.         .setContentIntent(pendingIntent)  
  10.         .setStyle(new NotificationCompat.BigPictureStyle()  
  11.             .bigPicture(bitmap)  
  12.             .setContentTitle("ビッグピクチャー")  
  13.             .setSummaryText("サマリー"));  
  14.   
  15. // Notification を発行  
  16. NotificationManagerCompat notificationManager =  
  17.         NotificationManagerCompat.from(this);  
  18. notificationManager.notify(notificationId, notificationBuilder.build());  
スマホ(上: 閉じてる状態、下: 開いた状態)



Wear(上: ホーム画面、下: タップした状態)



bitPicture() で指定した画像が背景になる。カードがなく背景にセットされた画像を見れるページが追加される。
タイトルには BigPictureStyle.setContentTitle() が表示されるが、その下は setSummaryText() ではなく setContentText() が表示される。




Action ボタンを追加する

Gmail の Notification の Archive に相当するもの。


*アイコンがぼけているように見えますが、実際ぼけています。Open on phone と比較すると明らかにぼけています。

NotificationCompat.Builder の addAction() で、画像、テキスト、タップされたときの PendingIntent を指定する。
  1. Intent intent = new Intent(this, MainActivity.class);  
  2. PendingIntent pendingIntent = PendingIntent.getActivity(this0, intent, 0);  
  3.   
  4. // Action 用の PendingIntent を作成  
  5. Intent mapIntent = new Intent(Intent.ACTION_VIEW);  
  6. Uri geoUri = Uri.parse("geo:0,0?q=" + Uri.encode(location));  
  7. mapIntent.setData(geoUri);  
  8. PendingIntent mapPendingIntent = PendingIntent.getActivity(this0, mapIntent, 0);  
  9.   
  10. NotificationCompat.Builder notificationBuilder =  
  11.         new NotificationCompat.Builder(this)  
  12.                 .setSmallIcon(R.drawable.ic_notif)  
  13.                 .setContentTitle("タイトル")  
  14.                 .setContentText("メッセージ")  
  15.                 .setContentIntent(pendingIntent)  
  16.                 .addAction(R.drawable.ic_map, "Map", mapPendingIntent);  
  17.   
  18. // Notification を発行  
  19. NotificationManagerCompat notificationManager =  
  20.         NotificationManagerCompat.from(this);  
  21. notificationManager.notify(notificationId, notificationBuilder.build());  
addAction() の第1引数に指定するアイコンは ActionBar のアイコンと同じサイズにする。
つまり、 32dp x 32dp(内枠 24dp x 24dp)。

Wear 側で表示される画像は、スマホの解像度に一致したリソース。スマホが xxhdpi の場合、hdpi のリソースがあっても、xxhdpi のリソースが Wear に表示される。

スマホ


Wear(上: ホーム画面、下: タップした状態)






Wear だけのアクションを追加

Wear にだけ表示されるアクションを追加できる。スマホの Notification には表示されない。

WearableExtender.addAction() を使う。
このメソッドを Action を追加すると、Wearable では NotificationCompatBuilder.addAction() で指定された Action は表示されない。 そのため、別の機能を WearableExtender.addAction() で与えるというよりは、スマホ用に NotificationCompatBuilder.addAction() で指定した機能を、Wear では Wear 用に適したものに置き換えたい場合に使う。

例えば、Gmail の返信機能は、スマホでは返信画面を開くだけだが、Wear では音声入力の結果を返信できるようにしている。
  1. Intent intent = new Intent(this, MainActivity.class);  
  2. PendingIntent pendingIntent = PendingIntent.getActivity(this0, intent, 0);  
  3.   
  4. // Action 用の PendingIntent を作成  
  5. Intent mapIntent = new Intent(Intent.ACTION_VIEW);  
  6. Uri geoUri = Uri.parse("geo:0,0?q=" + Uri.encode(location));  
  7. mapIntent.setData(geoUri);  
  8. PendingIntent mapPendingIntent = PendingIntent.getActivity(this0, mapIntent, 0);  
  9.   
  10. // Wear 用 Action を作成  
  11. NotificationCompat.Action action =  
  12.         new NotificationCompat.Action.Builder(R.drawable.ic_map_for_wear,  
  13.                 "Map for Wear", mapPendingIntent)  
  14.                 .build();  
  15.   
  16. NotificationCompat.Builder notificationBuilder =  
  17.         new NotificationCompat.Builder(this)  
  18.                 .setSmallIcon(R.drawable.ic_notif)  
  19.                 .setContentTitle("タイトル")  
  20.                 .setContentText("メッセージ")  
  21.                 .setContentIntent(pendingIntent)  
  22.                 .addAction(R.drawable.ic_map, "Map for phone", mapPendingIntent)  
  23.                 .extend(new NotificationCompat.WearableExtender().addAction(action));  
  24.   
  25. // Notification を発行  
  26. NotificationManagerCompat notificationManager =  
  27.         NotificationManagerCompat.from(this);  
  28. notificationManager.notify(notificationId, notificationBuilder.build());  
Wear 用のアイコンには Action Bar の2倍、つまり 64dp x 64dp(内枠 48dp x 48dp)の画像を指定する。こうするとNotificationCompat.Builder.addAction() で Wear に表示していたときと違って画像がぼけない。

スマホ


Wear(上: ホーム画面、下: タップした状態)






背景画像を指定する

■ setLargeIcon() を使う

setLargeIcon() を使うと、カードをタップしたときの背景に利用される。
  1. NotificationCompat.Builder notificationBuilder =  
  2.         new NotificationCompat.Builder(this)  
  3.                 .setSmallIcon(R.drawable.ic_notif)  
  4.                 .setContentTitle("タイトル")  
  5.                 .setContentText("メッセージ")  
  6.                 .setContentIntent(pendingIntent)  
  7.                 .setLargeIcon(bitmap);  
BigPictureStyle を使った場合、setLargeIcon() を指定していても Wear の背景は BigPictureStyle.bigPicture() で指定した画像になる。

スマホ


Wear(左: ホーム画面、右: タップした状態)


■ WearableExtender.setBackground() を使う

スマホの Notification で LargeIcon を使いたくない場合は、NotificationCompat.WearableExtender の setBackground() を使う。
  1. NotificationCompat.WearableExtender wearableExtender =   
  2.         new NotificationCompat.WearableExtender()  
  3.                 .setBackground(BitmapFactory.decodeResource(  
  4.                 getResources(), R.drawable.sample));  
  5.   
  6. NotificationCompat.Builder notificationBuilder =  
  7.         new NotificationCompat.Builder(this)  
  8.                 .setSmallIcon(R.drawable.ic_notif)  
  9.                 .setContentTitle("タイトル")  
  10.                 .setContentText("メッセージ")  
  11.                 .setContentIntent(pendingIntent)  
  12.                 .extend(wearableExtender);  
スマホ


Wear(左: ホーム画面、右: タップした状態)





Wear のカードでアプリアイコンを表示しない

カードの右上に表示されるアプリアイコンを消すには、NotificationCompat.WearableExtender.setHintHideIcon() を使う。
  1. NotificationCompat.WearableExtender wearableExtender =   
  2.         new NotificationCompat.WearableExtender()  
  3.                 .setHintHideIcon(true);  
  4.   
  5. NotificationCompat.Builder notificationBuilder =  
  6.         new NotificationCompat.Builder(this)  
  7.                 .setSmallIcon(R.drawable.ic_notif)  
  8.                 .setContentTitle("タイトル")  
  9.                 .setContentText("メッセージ")  
  10.                 .setContentIntent(pendingIntent)  
  11.                 .extend(wearableExtender);  
Wear(左: ホーム画面、右: タップした状態)





Wear のカード内にアイコンを表示する

NotificationCompat.WearableExtender.setContentIcon() を使う。
  1. NotificationCompat.WearableExtender wearableExtender =   
  2.         new NotificationCompat.WearableExtender()  
  3.                 .setContentIcon(R.drawable.ic_droid);  
  4.   
  5. NotificationCompat.Builder notificationBuilder =  
  6.         new NotificationCompat.Builder(this)  
  7.                 .setSmallIcon(R.drawable.ic_notif)  
  8.                 .setContentTitle("タイトル")  
  9.                 .setContentText("メッセージ")  
  10.                 .setContentIntent(pendingIntent)  
  11.                 .extend(wearableExtender);  
ここでは、アプリアイコンサイズの画像を指定してみた。
ambient 時は白の tint がかかる。

Wear(上: ホーム画面、下: タップした状態)






Wear のカード内にアイコンを左に表示する

NotificationCompat.WearableExtender. setContentIconGravity() で GravityCompat.START を指定する。 指定できるのは START と END で、デフォルトは END。
  1. NotificationCompat.WearableExtender wearableExtender =   
  2.         new NotificationCompat.WearableExtender()  
  3.                 .setContentIcon(R.drawable.ic_droid)  
  4.                 .setContentIconGravity(GravityCompat.START);  
  5.   
  6. NotificationCompat.Builder notificationBuilder =  
  7.         new NotificationCompat.Builder(this)  
  8.                 .setSmallIcon(R.drawable.ic_notif)  
  9.                 .setContentTitle("タイトル")  
  10.                 .setContentText("メッセージ")  
  11.                 .setContentIntent(pendingIntent)  
  12.                 .extend(wearableExtender);  
Wear(上: ホーム画面、下: タップした状態)






カードの位置を変える

setGravity() を使う。指定できるのは Gravity.TOP、Gravity.CENTER_VERTICAL、Gravity.BOTTOM。デフォルトは BOTTOM。
  1. NotificationCompat.WearableExtender wearableExtender =   
  2.         new NotificationCompat.WearableExtender()  
  3.                 .setGravity(Gravity.TOP);  
  4.   
  5. NotificationCompat.Builder notificationBuilder =  
  6.         new NotificationCompat.Builder(this)  
  7.                 .setSmallIcon(R.drawable.ic_notif)  
  8.                 .setContentTitle("タイトル")  
  9.                 .setContentText("メッセージ")  
  10.                 .setContentIntent(pendingIntent)  
  11.                 .extend(wearableExtender);  
Wear(左: ホーム画面、右: タップした状態)

Gravity.TOP


Gravity.CENTER_VERTICAL





オリジナルのカードを表示する

これは Wear アプリから Notification を発行するときにだけ使えます。
setDisplayIntent() で、カードをタップしたときに表示する Activity を持った PendingIntent を指定します。

Wear 上のコードなので、NotificationCompat ではなく Notification を使っています。
  1. // この MainActivity は Wear アプリの MainActivity  
  2. Intent intent = new Intent(this, MainActivity.class);  
  3. PendingIntent pendingIntent = PendingIntent.getActivity(this0, intent, 0);  
  4.   
  5. // カードをタップしたときに表示される Activity  
  6. // ここでは ImageView 1つだけのレイアウト  
  7. Intent displayIntent = new Intent(this, DisplayActivity.class);  
  8. PendingIntent displayPendingIntent = PendingIntent.getActivity(this,  
  9.         0, displayIntent, PendingIntent.FLAG_UPDATE_CURRENT);  
  10.   
  11. NotificationCompat.WearableExtender wearableExtender =   
  12.         new NotificationCompat.WearableExtender()  
  13.                 .setDisplayIntent(displayPendingIntent);  
  14.   
  15. Notification.Builder notificationBuilder =  
  16.         new Notification.Builder(this)  
  17.                 .setSmallIcon(R.drawable.ic_notif)  
  18.                 .setContentTitle("タイトル")  
  19.                 .setContentText("メッセージ")  
  20.                 .setContentIntent(pendingIntent)  
  21.                 .extend(wearableExtender);  
  22.   
  23. NotificationManager notificationManager =   
  24.         (NotificationManager) getSystemService(NOTIFICATION_SERVICE);  
  25. notificationManager.notify(notificationId, notificationBuilder.build());  
Wear から Notification を発行する場合、setSmallIcon() で指定したアイコンがカードの右上に表示される。
setContentIntent() で指定した PendingIntent は Open(開く)という Action になる。

Wear(左: ホーム画面、右: タップした状態)





オリジナルのカードの大きさを変える

setCustomSizePreset()を使う。
指定できるのは、SIZE_DEFAULT、SIZE_FULL_SCREEN、SIZE_LEARGE、SIZE_MEDIUM、SIZE_SMALL、SIZE_XSMALL。
  1. NotificationCompat.WearableExtender wearableExtender =   
  2.         new NotificationCompat.WearableExtender()  
  3.                 .setDisplayIntent(displayPendingIntent)  
  4.                 .setCustomSizePreset(NotificationCompat.WearableExtender.SIZE_FULL_SCREEN);  
  5.   
  6. Notification.Builder notificationBuilder =  
  7.         new Notification.Builder(this)  
  8.                 .setSmallIcon(R.drawable.ic_notif)  
  9.                 .setContentTitle("タイトル")  
  10.                 .setContentText("メッセージ")  
  11.                 .setContentIntent(pendingIntent)  
  12.                 .extend(wearableExtender);  
Wear(左: ホーム画面、右: タップした状態)

SIZE_FULL_SCREEN


SIZE_LARGE


SIZE_MEDIUM


SIZE_SMALL


SIZE_XSMALL





Notification から音声入力を使う

Notification に返信するなどテキストを入力するアクションがある場合、Wear にはキーボードがない代わりに RemoteInput を使って、音声入力を使うことができる。

*エミュレータには音声入力がないので、AVDの設定で Hardware keyboard present を有効にしておくと、代わりにキーボードで入力できる。

RemoteInput は RemoteInput.Builder を使って作る。コントラクタには音声入力結果に紐づけるキー(文字列)を渡す。
  1. private static final String EXTRA_VOICE_REPLY = "extra_voice_reply";  
  2. ...  
  3.   
  4. String replyLabel = getResources().getString(R.string.reply_label);  
  5.   
  6. RemoteInput remoteInput = new RemoteInput.Builder(EXTRA_VOICE_REPLY)  
  7.         .setLabel(replyLabel)  
  8.         .build();  
setLabel() でラベルを指定すると、上部の青色部分に表示される。 複数の項目を入力させたい場合などのに便利。
例えば、"Ok google, remind me" というと、About what? と When? を別々に入力する画面になる。



RemoteInput を Notification に組み込むには、NotificationCompat.Action.Builder の addRemoteInput() を使う。
  1. // 音声入力の結果を受けとるための PendingIntent を作る  
  2. Intent replyIntent = new Intent(this, ReplyActivity.class);  
  3. PendingIntent replyPendingIntent =  
  4.         PendingIntent.getActivity(this0, replyIntent,  
  5.                 PendingIntent.FLAG_UPDATE_CURRENT);  
  6.   
  7. // RemoteInput 用の Action を作る  
  8. NotificationCompat.Action action =  
  9.         new NotificationCompat.Action.Builder(R.drawable.ic_reply,  
  10.                 "Reply message", replyPendingIntent)  
  11.                 .addRemoteInput(remoteInput)  
  12.                 .build();  
  13.   
  14. // WearableExtender に addAction() で RemoteInput の Action を追加  
  15. NotificationCompat.WearableExtender wearableExtender =  
  16.         new NotificationCompat.WearableExtender()  
  17.                 .addAction(action);  
  18.   
  19. Notification.Builder notificationBuilder =  
  20.         new Notification.Builder(this)  
  21.                 .setSmallIcon(R.drawable.ic_notif)  
  22.                 .setContentTitle("タイトル")  
  23.                 .setContentText("メッセージ")  
  24.                 .setContentIntent(pendingIntent)  
  25.                 .extend(wearableExtender);  
音声入力が正しく終ると、NotificationCompat.Action.Builder の第3引数に指定した PendingIntent が実行される。

PendingIntent に指定された Activity もしくは Service では、getIntent() で取得した Intent を RemoteInput.getResultsFromIntent() に渡して Bundle を取得し、RemoteInput に指定したキーで文字列を取り出す。
  1. /** 
  2.  * Activity.getIntent() を渡す 
  3.  */  
  4. private CharSequence getMessageText(Intent intent) {  
  5.         Bundle remoteInput = RemoteInput.getResultsFromIntent(intent);  
  6.         if (remoteInput != null) {  
  7.             return remoteInput.getCharSequence(EXTRA_VOICE_REPLY);  
  8.         }  
  9.         return null;  
  10. }  
* 音声入力の結果は ClipData として保存されているため、Intent.getExtras() を使わずに getResultsFromIntent() を使うこと。

Wear(上: ホーム画面、中: タップした状態、下: reply actionをタップ&入力した状態)




setLabel() を指定しない場合。





■ 音声入力時に選択肢を与える

選択肢をあらかじめ用意しておくこともできる。選択肢は5つまで。setChoices() で文字列の配列を渡して指定する。
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <resources>  
  3.     <string-array name="reply_choices">  
  4.         <item>Yes</item>  
  5.         <item>No</item>  
  6.         <item>Maybe</item>  
  7.     </string-array>  
  8. </resources>  
  1. public static final EXTRA_VOICE_REPLY = "extra_voice_reply";  
  2. ...  
  3.   
  4. String replyLabel = getResources().getString(R.string.reply_label);  
  5.   
  6. // 選択肢  
  7. String[] replyChoices = getResources().getStringArray(R.array.reply_choices);  
  8.   
  9. RemoteInput remoteInput = new RemoteInput.Builder(EXTRA_VOICE_REPLY)  
  10.         .setLabel(replyLabel)  
  11.         .setChoices(replyChoices)  
  12.         .build();  




■ 選択肢だけから選択させる

音声入力を使わず、選択肢だけから選択させることもできる。 そのためには、setAllowFreeFormInput() で false を指定する。
この場合、setChoices() で選択肢を指定しておかないと IllegalArgumentException になる。
  1. public static final EXTRA_VOICE_REPLY = "extra_voice_reply";  
  2. ...  
  3.   
  4. String replyLabel = getResources().getString(R.string.reply_label);  
  5.   
  6. // 選択肢  
  7. String[] replyChoices = getResources().getStringArray(R.array.reply_choices);  
  8.   
  9. RemoteInput remoteInput = new RemoteInput.Builder(EXTRA_VOICE_REPLY)  
  10.         .setLabel(replyLabel)  
  11.         .setChoices(replyChoices)  
  12.         .setAllowFreeFormInput(false)  
  13.         .build();  






Page を追加する

追加の情報を表示したい場合などに、Page を追加することができる。

例えば、ハングアウトのカードでは、メインのカードに最新のメッセージが表示され、次のページに最近の投稿メッセージが表示される。
Google Now の天気カードでは、メインのカードに今日の天気、次のページに明日から四日間の天気が表示される。



Page を追加するには NotificationCompat.WearableExtender の addPage()addPages() を使う。
  1. // メインの Notification の NotificationCompat.Builder を作る  
  2. NotificationCompat.Builder notificationBuilder =  
  3.         new NotificationCompat.Builder(this)  
  4.                 .setSmallIcon(R.drawable.ic_notif)  
  5.                 .setContentTitle("Page 1")  
  6.                 .setContentText("吾輩は猫である")  
  7.                 .setContentIntent(pendingIntent);  
  8.   
  9. // 2ページ目の Notification を作る  
  10. Notification secondPageNotification =  
  11.         new NotificationCompat.Builder(this)  
  12.                 .setContentTitle("Page 2")  
  13.                 .setContentText(getString(R.string.long_text))  
  14.                 .build();  
  15.   
  16. // addPage() で2ページ目を追加し、extend() で1ページ目を拡張する  
  17. Notification twoPageNotification =  
  18.         new NotificationCompat.WearableExtender()  
  19.                 .addPage(secondPageNotification)  
  20.                 .extend(notificationBuilder)  
  21.                 .build();  
  22.   
  23. // Notification を発行  
  24. NotificationManagerCompat notificationManager  
  25.          = NotificationManagerCompat.from(this);  
  26. notificationManager.notify(notificationId, twoPageNotification);  
スマホ


Wear(上: ホーム画面、中: タップした状態)







Notification をまとめる

同じような通知はまとめて表示することが推奨されているが、Wearでは個別の通知の中がみれないのは不便。
そこで、1つのカードにグループ化し、カードをタップするとそれぞれの Notification が個別のカードに別れるよう作ることができる。

Gmailのカードはまさにこの形になっている。

カードをグループ化するには NotificationCompat.Builder.setGroup() で同じ文字列を指定する。
  1. final static String GROUP_KEY_EMAILS = "group_key_emails";  
  2.   
  3. // Build the notification, setting the group appropriately  
  4. Notification notif = new NotificationCompat.Builder(mContext)  
  5.          .setContentTitle("New mail from " + sender1)  
  6.          .setContentText(subject1)  
  7.          .setSmallIcon(R.drawable.new_mail);  
  8.          .setGroup(GROUP_KEY_EMAILS)  
  9.          .build();  
  10.   
  11. // Issue the notification  
  12. NotificationManagerCompat notificationManager =  
  13.         NotificationManagerCompat.from(this);  
  14. notificationManager.notify(notificationId1, notif);  
setGroup() に同じ文字列を指定し、notify() で指定する ID は別にする。
  1. Notification notif2 = new NotificationCompat.Builder(mContext)  
  2.          .setContentTitle("New mail from " + sender2)  
  3.          .setContentText(subject2)  
  4.          .setSmallIcon(R.drawable.new_mail);  
  5.          .setGroup(GROUP_KEY_EMAILS)  
  6.          .build();  
  7.   
  8. notificationManager.notify(notificationId2, notif2);  
Wear(上: ホーム画面、中: タップした状態、下: 中をタップした状態)




グループ化されたカードがスタックされる順番は、新しく発行されたものが上になる(デフォルト)。
setSortKey() を使うと、順番を任意に指定することができる。


setGroup() を指定した Notification はスマホでは表示されないため、Summary Notification を用意する。 Summary Notification では setGroup() に同じ文字列を指定し、setGroupSummry() に true を指定する。この Summary Notification は Wear では表示されない。
  1. Notification summaryNotification = new NotificationCompat.Builder(mContext)  
  2.         .setContentTitle("2 new messages")  
  3.         .setSmallIcon(R.drawable.ic_notif)  
  4.         .setStyle(new NotificationCompat.InboxStyle()  
  5.                 .addLine(line1)  
  6.                 .addLine(line2)  
  7.                 .setBigContentTitle("2 new messages")  
  8.                 .setSummaryText(summary))  
  9.         .setGroup(GROUP_KEY_EMAILS)  
  10.         .setGroupSummary(true)  
  11.         .build();  
  12.   
  13. notificationManager.notify(notificationId3, summaryNotification);  
スマホ


Summary Notification は Wear に直接表示されることはないが、 NotificationCompat.WearableExtender を使ってスタック全体の背景やスタック全体に対する Action を指定できる。
  1. Bitmap background = BitmapFactory.decodeResource(getResources(),  
  2.         R.drawable.ic_background);  
  3.   
  4. NotificationCompat.WearableExtender wearableExtender =  
  5.         new NotificationCompat.WearableExtender()  
  6.                 .setBackground(background);  
  7.   
  8. // extend() で背景を指定  
  9. Notification summaryNotificationWithBackground =  
  10.         new NotificationCompat.Builder(mContext)  
  11.         .setContentTitle("2 new messages")  
  12.         ...  
  13.         .extend(wearableExtender)  
  14.         .setGroup(GROUP_KEY_EMAILS)  
  15.         .setGroupSummary(true)  
  16.         .build();  
Wear




0 件のコメント:

コメントを投稿