音声操作は、ユーザーの音声でトリガーされる特別な Android アクティビティであり、音声で操作を完了できます。 一方、通常のアクティビティ インテントは、アクションを起動してタップ操作で完了するように設計されています。
たとえば、Android の「DIAL」インテントは、電話アプリケーションによって実装されますが、インテントは電話アプリの電話番号をプリロードするだけで、ユーザーは実際にボタンをタップして通話を開始する必要があります。
音声操作を指定する
アプリは、android.intent.category.VOICE カテゴリを通じて、Android マニフェスト ファイルで音声操作アクティビティを指定します。
次の例は、音声操作アクティビティを指定する方法を示しています。
<activity android:name="org.example.MyVoiceActivity">
<intent-filter>
<action android:name="org.example.MY_ACTION_INTENT" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.VOICE" />
</intent-filter>
</activity>
次の例は、対応するタッチ操作アクティビティを指定する方法を示しています。
<activity android:name="org.example.MyTouchActivity">
<intent-filter>
<action android:name="org.example.MY_ACTION_INTENT" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
音声操作に対応する
アプリは、インテントを受け取ると、適切なインタラクションを決定する必要があります。どれが適しているかは、アプリの性質、つまりユーザーにどの程度のインタラクションを求めるか、単にアクションを完了するのがどれほど安全かなどによって決まります。
音声操作による承認
多くの場合、ユーザーはリクエストの結果として発生するアクションを確認する必要があります。たとえば、タクシーの予約リクエストには、リクエストの詳細(時刻、場所、目的地)をすべて含めることもできますが、費用や到着時間などの詳細は、ユーザーに確認する必要があります。
次の例は、音声確認による音声操作を処理する方法を示しています。
class MyVoiceActivity extends Activity {
class Confirm extends VoiceInteractor.ConfirmationRequest {
public Confirm(String ttsPrompt, String visualPrompt) {
VoiceInteractor.Prompt prompt = new VoiceInteractor.Prompt(
new String[] {ttsPrompt}, visualPrompt);
super(prompt, null);
}
@Override
public void onConfirmationResult(
boolean confirmed, Bundle null) {
if (confirmed) {
doAction();
}
finish();
}
};
@Override
public void onResume() {
if (isVoiceInteraction()) {
String ttsPrompt = getConfirmationTts();
String visualPrompt = getConfirmationDisplayText();
getVoiceInteractor().sendRequest(new Confirm(ttsPrompt, visualPrompt));
} else {
finish();
}
}
}
この例では、アクティビティが音声操作として開始されたときに確認をリクエストします。まず、isVoiceInteraction() を呼び出して音声アクティビティであることを確認します。VoiceInteractionor.ConfirmationRequest のサブクラスは、ユーザーからの非同期確認(受け入れられるか拒否されるか)を処理して、アクションを完了する必要があるかどうかを判断します。
この場合、ユーザーは音声でプロンプトを受け取り、口頭で承認するよう求められます(例: yes または no)。アクティビティは、結果を示すコールバックを受け取ります。
確認なしで承認
場合によっては、インテントがユーザーの音声から発信されていることを知るだけで十分であり、そのインテントを確認するためにそれ以上の情報は必要ないことを意味します。たとえば、電話をかける、メールを送信するなどの対応は妥当なと考えられます。
isVoiceInteractionRoot()
呼び出しにより、インテントがユーザーの音声から発信されていることを確認できます。isVoiceInteraction()
は、別のアプリの音声操作アクティビティがユーザーのインテントなしで音声アクティビティを起動した場合でも true を返しますが、isVoiceInteractionRoot()
は、Google 検索アプリでユーザーの音声操作によってアクティビティを直接開始した場合にのみ true を返します。
次の例は、確認なしで音声操作を処理する方法を示しています。
class MyVoiceActivity extends Activity {
@Override
public void onResume() {
if (isVoiceInteractionRoot()) {
// Interaction started by the users voice
doAction();
}
finish();
}
}
アクティビティが音声アクティビティではない場合は、タップ操作で完了する必要があります。 音声操作は、必要に応じて「フォールバック」してコミュニケーションに触れるようにする必要があります。
音声操作を終了する
アプリがユーザーに質問した後、アプリは finish()
を呼び出してダイアログ プレートを閉じる必要があります。そうしないと、空のダイアログ プレートが引き続き画面下部に表示されます。そのため、画面スペースが占有されてユーザーが混乱します。
ユーザーをアクティビティに残す場合は、新しい通常のアクティビティを開始し、音声操作アクティビティを終了します。Intent.FLAG_ACTIVITY_NEW_TASK
フラグを使用してアクティビティを開始し、音声操作のタスクを終了します。
class MyVoiceActivity extends Activity {
@Override
public void onResume() {
if (isVoiceInteractionRoot()) {
doAction();
}
// Start my main non-voice Activity
Intent intent = new Intent(this, MyMainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
finish();
}
}
完了ステータスを送信しています
音声操作の個々の完了状況を伝えることは、ユーザーの各アクションを価値のあるアシスト エクスペリエンスを提供するうえで不可欠です。次に例を示します。
- 一部の操作の結果は、今後使用するためにユーザーに提供される場合があります。たとえば、レストランの予約の予約情報は、Google Now または [予約] クエリからリマインダー カードとして自動的に利用可能になります。
- アクティビティは、アクション URI への参照を示すコンテキスト URI(デバイスのコンテンツ プロバイダ URI、またはウェブ URL ディープリンクなど)を返すよう選択できます。 これにより、アプリは、操作が前の操作に続く操作であることを認識できます(例: 先ほど設定したアラームのキャンセルや、直前に撮影した写真の共有など)。
- 操作を完了できなかったことを示します。システムの信頼性を高めるうえで重要な点は、責任をもってエラーまたは対話の制限に対処することです。たとえば、ログインフローやクレジット カードによる支払いは、音声では不可能な場合があります。これは、自動車環境において目の自由な操作に対処する場合に特に重要です。
次の例は、操作の完了ステータスを報告する方法を示しています。
class MyVoiceActivity extends Activity {
@Override
public void onResume() {
if (isVoiceInteraction()) {
Bundle status = new Bundle();
VoiceInteractor.Request request = null;
if (doAction(status)) {
request = new VoiceInteractor.CompleteVoiceRequest(
"Success", status);
} else {
request = new VoiceInteractor.AbortVoiceRequest(
"Too Complex", status);
}
getVoiceInteractor().sendRequest(request);
}
finish();
}
}
マルチモーダル インタラクション
ユーザーは、さまざまな理由(音声認識の問題、多くのオプションのリストからの選択など)でアクションを完了するときに、音声とタップのインタラクションを組み合わせることがよくあります。そのため、両方のインタラクション モダリティをサポートすることが重要になります。
音声アクティビティでは、音声で操作するときに最小限のタップ インターフェースを表示する必要があります。次の点にご注意ください:
- 現在のやり取りを完了するために必要なコントロールのみを表示します。アクティビティ ビューで使用できるタッチ ディスプレイの一部が、音声操作バーを表示するために縮小されている場合があります。アプリケーションにはアプリバーを表示しません。
- 音声インタラクションが保留中であるときにユーザーがタップで操作した場合(ユーザーが音声ではなくボタンで確認する場合など)は、VoiceInteractionor.Request.cancel を呼び出して音声操作を停止します。
- ユーザーがタップ操作に切り替えたら、タップ操作を続行する必要があります。