音声入力

音声入力により、本当のハンズフリー インターフェースを作成できます。Glass では、音声入力を利用する方法が 3 つあります。

メインの音声コマンドでは、ホームカードから Glassware を起動し、状況に応じた音声コマンドではアクティビティ内でアクションを実行できます。システムの音声認識アクティビティでは、ユーザーから自由形式の音声入力を受信できます。

主な音声コマンド

以下の音声コマンドで、ホームカード(時計カード)から Glassware が起動します。メインの音声コマンドを宣言すると、ユーザーがホームカードをタップして Glassware を起動すると、Glass が代替のタッチメニュー項目を自動的に作成します。

オークグラスの音声メインメニューに音声コマンドを追加するには:

  1. VoiceTriggers.Command で定義されている既存の音声コマンドのいずれかを使用する、res/xml/<my_voice_trigger>.xml の音声コマンド用の XML リソースを作成します。以下は、「ランニングを開始」の使用方法です。

    <?xml version="1.0" encoding="utf-8"?>
    <trigger command="START_A_RUN" />
    

    アクティビティやサービスの開始前にユーザーに追加のフレーズを発するように促す音声コマンドを作成するには、input 要素も組み込みます。たとえば、「更新を投稿する」を使用している場合などに使用できます。

    <?xml version="1.0" encoding="utf-8"?>
    <trigger command="POST_AN_UPDATE">
        <input prompt="@string/glass_voice_prompt" />
    </trigger>
    
  2. Android マニフェストの com.google.android.glass.action.VOICE_TRIGGER アクションを使用してインテント フィルタを登録します。インテント フィルタは、ユーザーが音声コマンドを話しかけていることを検出すると、アクティビティまたはサービスを開始します。

    <?xml version="1.0" encoding="utf-8"?>
    <application ...>
        <activity | service ...>
            <intent-filter>
                <action android:name=
                        "com.google.android.glass.action.VOICE_TRIGGER" />
            </intent-filter>
            <meta-data android:name="com.google.android.glass.VoiceTrigger"
                android:resource="@xml/my_voice_trigger" />
        </activity | service>
        // ...
    </application>
    
  3. アクティビティまたはサービスの android:icon 属性を宣言します。 これにより、Glass の [ok glass] タッチメニューに Glassware のアイコンを表示できます。

    <activity |service
        android:icon="@drawable/my_icon" ...>
      ...
    </activity | service>
    
  4. 音声コマンドを使用してアクティビティを開始する場合、次のコード(onResume() など)で音声文字変換されたテキストを取得します。

    ArrayList<String> voiceResults = getIntent().getExtras()
            .getStringArrayList(RecognizerIntent.EXTRA_RESULTS);
    

    音声コマンドでサービスが開始されると、onStartCommand() コールバックでインテント エクストラを利用できます。

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        ArrayList<String> voiceResults = intent.getExtras()
                .getStringArrayList(RecognizerIntent.EXTRA_RESULTS);
        // ...
    }
    

制約の設定

Glassware を起動するために次の機能のいずれかまたはすべてが必要な場合は、res/xml/<my_voice_trigger>.xml リソースで指定します。この機能が利用できない場合、Glass は音声コマンドを無効にします。

  • camera
  • network
  • microphone

    <trigger command="POST_AN_UPDATE">
        <constraints
            camera="true"
            network="true" />
    </trigger>
    

状況に応じた音声コマンド

状況に応じた音声コマンドを使用して、ユーザーはアクティビティからアクションを実行できます。標準の Android メニュー API を使用してコンテキスト音声コマンドを作成できますが、ユーザーはタップではなく音声コマンドでメニュー項目を呼び出せます。

特定のアクティビティでコンテキスト音声コマンドを有効にするには:

  1. 目的のアクティビティで getWindow().requestFeature(WindowUtils.FEATURE_VOICE_COMMANDS) を呼び出して、コンテキスト音声コマンドを有効にします。この機能を有効にすると、このアクティビティがフォーカスを受け取るたびに、画面のフッター領域に「OK glass」メニューが表示されます。

  2. onCreatePanelMenu() をオーバーライドし、WindowUtils.FEATURE_VOICE_COMMANDS が有効になっているケースを処理します。有効にした場合、ここで 1 回限りのメニュー設定を行います。たとえば、メニュー リソースをインフレートするか、Menu.add() メソッドを呼び出して音声メニュー システムを作成します。

  3. ユーザーが発話したときに音声コマンドを処理するように、onMenuItemSelected() をオーバーライドします。ユーザーがメニュー項目を選択すると、「ok glass」という音声コマンドが画面のフッター セクションに自動的に再表示され、アクティビティがフォーカスされている間は新しい音声コマンドを受け入れられます。

    次のコードは、コンテキストを考慮した音声コマンドを有効化し、必要に応じてメニュー リソースをインフレートして、発話されたときに音声コマンドを処理します。

    public class ContextualMenuActivity extends Activity {
    
        @Override
        protected void onCreate(Bundle bundle) {
            super.onCreate(bundle);
    
            // Requests a voice menu on this activity. As for any other
            // window feature, be sure to request this before
            // setContentView() is called
            getWindow().requestFeature(WindowUtils.FEATURE_VOICE_COMMANDS);
            setContentView(R.layout.activity_main);
        }
    
        @Override
        public boolean onCreatePanelMenu(int featureId, Menu menu) {
            if (featureId == WindowUtils.FEATURE_VOICE_COMMANDS) {
                getMenuInflater().inflate(R.menu.main, menu);
                return true;
            }
            // Pass through to super to setup touch menu.
            return super.onCreatePanelMenu(featureId, menu);
        }
    
        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            getMenuInflater().inflate(R.menu.main, menu);
            return true;
        }
    
        @Override
        public boolean onMenuItemSelected(int featureId, MenuItem item) {
            if (featureId == WindowUtils.FEATURE_VOICE_COMMANDS) {
                switch (item.getItemId()) {
                    case R.id.dogs_menu_item:
                        // handle top-level dogs menu item
                        break;
                    case R.id.cats_menu_item:
                        // handle top-level cats menu item
                        break;
                    case R.id.lab_menu_item:
                        // handle second-level labrador menu item
                        break;
                    case R.id.golden_menu_item:
                        // handle second-level golden menu item
                        break;
                    case R.id.calico_menu_item:
                        // handle second-level calico menu item
                        break;
                    case R.id.cheshire_menu_item:
                        // handle second-level cheshire menu item
                        break;
                    default:
                        return true;
                }
                return true;
            }
            // Good practice to pass through to super if not handled
            return super.onMenuItemSelected(featureId, item);
        }
    }
    

    前のアクティビティで使用されたメニュー リソースの例を次に示します。階層型音声メニュー システム用にネストされたメニュー項目を作成する方法に注意してください。次の例では、最初のメニュー項目に ok glass, Show me dogs, Labrador としてアクセスできます。

    <menu xmlns:android="http://schemas.android.com/apk/res/android">
        <!-- Use the constants defined in the ContextualMenus.Command enum-->
        <item
            android:id="@+id/dogs_menu_item"
            android:title="@string/show_me_dogs">
            <menu>
                <item
                    android:id="@+id/lab_menu_item"
                    android:title="@string/labrador" />
                <item
                    android:id="@+id/golden_menu_item"
                    android:title="@string/golden" />
            </menu>
        </item>
        <item
            android:id="@+id/cats_menu_item"
            android:title="@string/show_me_cats">
            <menu>
                <item
                    android:id="@+id/cheshire_menu_item"
                    android:title="@string/cheshire" />
                <item
                    android:id="@+id/calico_menu_item"
                    android:title="@string/calico" />
            </menu>
        </item>
    </menu>
    
    <menu xmlns:android="http://schemas.android.com/apk/res/android">
        <!-- Use the constants defined in the ContextualMenus.Command enum-->
        <item
            android:id="@+id/play_menu_item"
            android:title="PLAY_MUSIC" />
        <item
            android:id="@+id/pause_menu_item"
            android:title="PAUSE_MUSIC" />
    </menu>
    
  4. (省略可)onPreparePanel() をオーバーライドして、WindowUtils.FEATURE_VOICE_COMMANDS が有効かどうかを確認します。有効にした場合、ここで他のロジックを使ってメニュー システムをセットアップできます。たとえば、特定の基準に基づいて特定のメニュー項目を追加または削除できます。一部の基準に基づいて、コンテキスト音声メニューのオンとオフ(true)とオフ(false )を切り替えることもできます。例:

        private boolean mVoiceMenuEnabled;
        ...
        @Override
        public boolean onPreparePanel(int featureId, View view, Menu menu) {
            if (featureId == WindowUtils.FEATURE_VOICE_COMMANDS) {
            // toggle this boolean on and off based on some criteria
                return mVoiceMenuEnabled;
            }
            // Good practice to call through to super for other cases
            return super.onPreparePanel(featureId, view, menu);
        }
    

音声メニューとタップメニューを同時にサポート

コンテキスト音声コマンドは、既存の Android メニュー API を使用するため、既存の多くのコードとリソースをタッチメニューに再利用でき、両方のタイプのメニューを同時にサポートできます。

いくつかのメソッドですでにチェックしている WindowUtils.FEATURE_VOICE_COMMANDS 機能に加えて Window.FEATURE_OPTIONS_PANEL 機能を確認し、タップなどのユーザー アクションでタップメニューを開くロジックを追加するだけです。

たとえば、前のアクティビティの例を変更して、次のようなタッチメニューのサポートを追加できます(変更はコメント付きです)。

// 1. Check for Window.FEATURE_OPTIONS_PANEL
// to inflate the same menu resource for touch menus.
@Override
public boolean onCreatePanelMenu(int featureId, Menu menu) {
    if (featureId == WindowUtils.FEATURE_VOICE_COMMANDS ||
            featureId == Window.FEATURE_OPTIONS_PANEL) {
    ...
}

// 2. Check for Window.FEATURE_OPTIONS_PANEL
// to handle touch menu item selections.
@Override
public boolean onMenuItemSelected(int featureId, MenuItem item) {
    if (featureId == WindowUtils.FEATURE_VOICE_COMMANDS ||
            featureId == Window.FEATURE_OPTIONS_PANEL) {
    ...
}

この変更により、「ok glass」をタップまたは話しかけることで、メニューを表示できます。

限定公開の音声コマンドによる開発

Glassware を配布する場合は、承認済みのメイン音声コマンド(VoiceTriggers.Command)と承認済みのコンテキスト音声コマンド(ContextualMenus.Command)を使用してください。

GDK では利用できない音声コマンドを使用する場合は、AndroidManifest.xml ファイルで Android の権限をリクエストできます。

<uses-permission
     android:name="com.google.android.glass.permission.DEVELOPMENT" />

リストにないメインの音声コマンドを使用する

  1. 音声トリガーの名前を定義する文字列値を res/values/strings.xml で宣言します。オプションで、Glassware を起動する前に音声認識 Glassware を表示する音声プロンプトを宣言します。

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <string name="glass_voice_trigger">read me a story</string>
        <string name="glass_voice_prompt">what story?</string>
    </resources>
    
  2. res/xml/<my_voice_trigger>.xml で音声トリガーの XML リソースを作成します。リストに含まれない音声コマンドの場合は、承認済みの音声コマンドに使用される command 属性ではなく、keyword 属性を使用する必要があります。keyword 属性は、音声コマンドを定義する文字列リソースへの参照にする必要があります。アクティビティまたはサービスをすぐに開始する単純な音声トリガーの場合は、trigger 要素を指定するだけです。

    <?xml version="1.0" encoding="utf-8"?>
    <trigger keyword="@string/glass_voice_trigger" />
    

    アクティビティやサービスの開始前にユーザーに追加のフレーズを発するように促す音声トリガーを作成するには、入力要素も含めます。

    <?xml version="1.0" encoding="utf-8"?>
    <trigger keyword="@string/glass_voice_trigger">
        <input prompt="@string/glass_voice_prompt" />
    </trigger>
    

状況に応じた音声コマンドでリストに載っていないものを使用する

メニュー項目を作成する際は、メニュー項目のタイトルに任意のテキストを使用します。例:

<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- Use the constants defined in the ContextualMenus.Command enum-->
    <item
        android:id="@+id/pizza_menu_item"
        android:title="@string/find_pizza" />
</menu>

音声認識を開始します


音声認識 Glassware は、ユーザーが話すのを待ってから、文字起こしされたテキストを返します。アクティビティを開始するには:

  1. ACTION_RECOGNIZE_SPEECH インテントを指定して startActivityForResult() を呼び出します。アクティビティを開始する際に、次のインテント エクストラがサポートされています。
  2. 音声文字変換されたテキストを EXTRA_RESULTS インテント エクストラから受け取るように onActivityResult() コールバックをオーバーライドします。このコールバックは、ユーザーが話し終わると呼び出されます。

    private static final int SPEECH_REQUEST = 0;
    
    private void displaySpeechRecognizer() {
        Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
        startActivityForResult(intent, SPEECH_REQUEST);
    }
    
    @Override
    protected void onActivityResult(int requestCode, int resultCode,
            Intent data) {
        if (requestCode == SPEECH_REQUEST && resultCode == RESULT_OK) {
            List<String> results = data.getStringArrayListExtra(
                    RecognizerIntent.EXTRA_RESULTS);
            String spokenText = results.get(0);
            // Do something with spokenText.
        }
        super.onActivityResult(requestCode, resultCode, data);
    }