通知アプリの実装
現在多くのアプリは、ユーザーに対して何らかの通知を行っています。Android Autoに対応した通知を行うと、内容は音声で読み上げられ、それに対して音声で返信もできます。
メッセージ系アプリの流れは以下のようになります。
- 通知を読み終わった時に発行されるPendingIntent(以下、既読Intent)と、返信した場合に発行されるPendingIntent(以下、返信Intent)を作成します。
- UnreadConversation.Builderを使用し、既読Intentと返信IntentをセットしたUnreadConversationオブジェクトを作成します。
- NotificationCompat.CarExtenderを作成し、UnreadConversationオブジェクトをセットします。
- NotificationCompat.Builderを使用して、CarExtenderオブジェクトをセットした通知を行います。
ここまでが通知の流れです。ただし、返信を期待しない場合は、返信Intentをセットする必要はありません。
こうした通知が行われると、Android Autoは通知を車載器に表示します。その通知が選択されると、内容が読み上げられ、既読Intentが発行されます。アプリは、BroadcastReceiverでそのIntentを受け取り、NotificationManagerCompat.cancel()を使用して、通知を削除するなどを行います。
ユーザーが返信した場合、返信Intentが発行されますので、やはりBroadcastReceiverでそのIntentを受け取り、処理します。このIntentには、RemoteInputを通じて音声入力された返信を、文字に直したものが入っています。
今回はBroadcastReceiverで行っていますが、ServiceのPendingIntentを発行してもらっても良いでしょう。
メタデータの設定
音楽系アプリとほぼ同じなので、割愛します。automotive_app_desc.xmlの内容を以下のように忘れず修正しておきましょう。
<automotiveApp> <uses name="notification" /> </automotiveApp>
BroadcastReceiverの作成
通知を読み終わったとき、返信が行われたときのそれぞれのIntentを受けとるBroadcastReceiverを作成します。
まず、manifestファイルに定義しましょう。
<application>
...
<receiver
android:name=".auto.MyMessageHeardReceiver"
android:enabled="true"
android:exported="false" >
<intent-filter>
<!-- Actionは、適宜修正してください -->
<action
android:name="com.example.messagesample.MY_ACTION_MESSAGE_HEARD" />
</intent-filter>
</receiver>
<receiver
android:name=".auto.MyMessageReplyReceiver"
android:enabled="true"
android:exported="true" >
<intent-filter>
<action
android:name="com.exapmle.messagesample.MY_ACTION_MESSAGE_REPLY" />
</intent-filter>
</receiver>
...
</application>
続いて、それぞれのBroadcastReceiverを作成します。
@Override
public void onReceive(Context context, Intent intent) {
int conversationId = NotificationHelper.getConversationId(intent);
// 通知は読まれたので、既読として通知を削除します。
// メールなどの場合、ここで既読フラグもつけましょう。
NotificationManagerCompat manager
= NotificationManagerCompat.from(context.getApplicationContext());
manager.cancel(conversationId);
}
@Override
public void onReceive(Context context, Intent intent) {
// 必要なら、会話の管理に使用します。
int conversationId = NotificationHelper.getConversationId(intent);
// ユーザーが音声入力したテキストを受けとる
CharSequence reply = NotificationHelper.getMessageText(intent);
if (reply != null) {
Log.d(getClass().getSimpleName(), reply.toString());
}
}
通知を行う
通知を行います。
今回はAndroid Auto用の情報しか設定していませんが、ユーザーは常にAndroid Autoにスマートフォンを接続しているわけではありませんから、対応する際には、スマートフォンで表示するための情報も付与しましょう。
public static void notifyMessage(Context context, String name, String message) {
// 通知用インテント
Intent msgHeardIntent = new Intent()
.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES)
.setAction(ACTION_MESSAGE_HEARD)
.putExtra(EXTRA_KEY_ID, HEAR_ID);
PendingIntent msgHeardPendingIntent =
PendingIntent.getBroadcast(context.getApplicationContext(),
HEAR_ID,
msgHeardIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
// 返信用インテント
Intent replyIntent = new Intent()
.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES)
.setAction(ACTION_MESSAGE_REPLY)
.putExtra(EXTRA_KEY_ID, REPLY_ID);
PendingIntent replyPendingIntent =
PendingIntent.getBroadcast(context.getApplicationContext(),
REPLY_ID,
replyIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
// 入力を受け付けるためのクラス
RemoteInput remoteInput = new RemoteInput.Builder(MY_VOICE_REPLY_KEY)
.setLabel(context.getString(R.string.app_name))
.build();
// 一連の会話をグループ化するためのクラス
UnreadConversation.Builder unreadConvBuilder =
new UnreadConversation.Builder(name)
// 既読用のPendingIntent
.setReadPendingIntent(msgHeardPendingIntent)
// 返信用のPendingIntent
.setReplyAction(replyPendingIntent, remoteInput)
// 通知内容
.addMessage(message)
// タイムスタンプをつけましょう
.setLatestTimestamp(System.currentTimeMillis());
NotificationCompat.Builder notificationBuilder =
new NotificationCompat.Builder(context.getApplicationContext())
.setSmallIcon(R.mipmap.ic_launcher)
.extend(new NotificationCompat.CarExtender()
.setUnreadConversation(unreadConvBuilder.build()));
NotificationManagerCompat manager
= NotificationManagerCompat.from(context.getApplicationContext());
manager.notify(HEAR_ID, notificationBuilder.build());
}
テスト
では、実際に動かしてみましょう。音楽系のアプリと同様、シミュレータをインストールします。音楽再生アプリ用のシミュレータと同じ場所に、messaging-simulator.apkがありますので、インストールしましょう。
また、このシミュレータが通知を受け取れるように設定しなければなりません。端末の「設定」から「音と通知」「通知へのアクセス」へと進み、「Messaging Sim」にチェックを入れましょう。
アプリから通知を行ったあと、シミュレータアプリを起動すると、このように表示されます。
この通知を選択すると、通知の内容が読まれます。
返信用のアイコンを押すと、返信内容がログに出力されます。どうもシミュレータでは、自由な返信を行えないようで、返信内容は"This is reply"で固定です。
まとめ
いかがでしたでしょうか。意外と簡単に対応できると感じられたのではないでしょうか。Android Autoは記事執筆時点で日本未発売ですが、それは他のサービスに先駆けるチャンスでもあります。特に通知を読み上げてくれる機能は、幅広いアプリに適用できます。Android Autoの今後の発展が楽しみです。
