SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

Yahoo! JAPAN 黒帯シリーズ

Android Autoのはじめ方

Yahoo! JAPAN 黒帯シリーズ 第3回 ~ 「Android技術黒帯」による車載用Androidプラットフォームの解説

通知アプリの実装

 現在多くのアプリは、ユーザーに対して何らかの通知を行っています。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を作成します。

既読用のBroadcastReceiver
@Override
public void onReceive(Context context, Intent intent) {

    int conversationId = NotificationHelper.getConversationId(intent);

    // 通知は読まれたので、既読として通知を削除します。
    // メールなどの場合、ここで既読フラグもつけましょう。
    NotificationManagerCompat manager
            = NotificationManagerCompat.from(context.getApplicationContext());

    manager.cancel(conversationId);
}
返信用のBroadcastReceiver
@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の今後の発展が楽しみです。

この記事は参考になりましたか?

連載通知を行うには会員登録(無料)が必要です。
既に会員の方はを行ってください。
Yahoo! JAPAN 黒帯シリーズ連載記事一覧

もっと読む

この記事の著者

森 洋之(ヤフー株式会社)(モリ ヒロユキ)

ヤフー株式会社 ヤフオク!カンパニー開発本部 サービス開発部 黒帯 Android 技術1982年広島県生まれ。Androidアプリの個人開発などを経て、2012年ヤフー株式会社入社。「ヤフオク!」などのAndroidアプリ開発に携わる。2014年10月にAndroid技術の分野で黒帯に認定される。...

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/8711 2015/06/19 14:00

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー