Rozpoznawanie mowy

Rozpoznawanie mowy pozwala stworzyć całkowicie bezdotykowy interfejs. Google Glass oferuje 3 metody wprowadzania głosowego.

Główne polecenia głosowe uruchamiają oprogramowanie Glassware na karcie głównej, kontekstowe polecenia głosowe mogą wykonywać działania w ramach aktywności, a systemowe rozpoznawanie mowy umożliwia użytkownikowi odbieranie własnych komunikatów głosowych.

Główne polecenia głosowe

Te polecenia głosowe uruchamiają Glassware na karcie głównej (karta zegara). Gdy zadeklarujesz główne polecenie głosowe, Google Glass automatycznie utworzy jako element zastępczy menu dotykowego, jeśli użytkownicy postanowią uruchomić urządzenie Glass za pomocą dotknięcia karty głównej.

Aby dodać polecenie głosowe do menu głównego OK Google:

  1. Utwórz zasób XML dla polecenia głosowego w res/xml/<my_voice_trigger>.xml, które korzysta z jednego z dotychczasowych poleceń głosowych zdefiniowanych w VoiceTriggers.Command. Oto przykład użycia polecenia „Rozpocznij bieg”.

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

    Aby utworzyć polecenie głosowe, które poprosi użytkownika o wypowiedzenie dodatkowych słów przed rozpoczęciem aktywności lub usługi, dodaj też element input. Może Ci się to przydać na przykład wtedy, gdy używasz opcji „Opublikuj aktualizację”.

    <?xml version="1.0" encoding="utf-8"?>
    <trigger command="POST_AN_UPDATE">
        <input prompt="@string/glass_voice_prompt" />
    </trigger>
    
  2. Zarejestruj filtr intencji, używając działania com.google.android.glass.action.VOICE_TRIGGER w pliku manifestu Androida. Filtr intencji uruchamia Twoją aktywność lub usługę, jeśli wykryje, że użytkownik wydaje polecenie głosowe.

    <?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. Zadeklaruj atrybut android:icon swojej aktywności lub usługi. Dzięki temu Google Glass może wyświetlić ikonę szkła Glass w menu ok, Glass.

    <activity |service
        android:icon="@drawable/my_icon" ...>
      ...
    </activity | service>
    
  4. Jeśli polecenie głosowe użyje polecenia głosowego i uruchomi aktywność, pobierz dowolny transkrypcję tekstu za pomocą tego kodu (na przykład w onResume()):

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

    Jeśli polecenie głosowe uruchomi usługę, intencja dodatkowa będzie dostępna w wywołaniu zwrotnym onStartCommand():

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

Ustawianie ograniczeń

Jeśli do uruchamiania Glassware potrzebujesz co najmniej jednej z tych funkcji, wskaż je w zasobie res/xml/<my_voice_trigger>.xml. Jeśli funkcje są niedostępne, Google Glass wyłączy polecenie głosowe:

  • camera
  • network
  • microphone

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

Kontekstowe polecenia głosowe

Kontekstowe polecenia głosowe pozwalają użytkownikom wykonywać czynności pochodzące z aktywności. Kontekstowe polecenia głosowe tworzy się za pomocą standardowych interfejsów API menu na Androidzie, ale użytkownicy mogą wywoływać pozycje menu za pomocą poleceń głosowych zamiast dotyku.

Aby włączyć kontekstowe polecenia głosowe związane z określoną aktywnością:

  1. Wywołaj getWindow().requestFeature(WindowUtils.FEATURE_VOICE_COMMANDS) w odpowiedniej aktywności, aby włączyć kontekstowe polecenia głosowe. Gdy ta funkcja jest włączona, menu „OK Glass” pojawia się w stopce ekranu, gdy zadanie zostanie zaznaczone.

  2. Zastąp onCreatePanelMenu() i rozpatruj zgłoszenia, w których włączono WindowUtils.FEATURE_VOICE_COMMANDS. Jeśli włączysz tę opcję, tutaj możesz przeprowadzić jednorazową konfigurację menu, na przykład zawyżyć zasób menu lub wywołać metody Menu.add(), aby utworzyć system menu głosowego.

  3. Zastąp onMenuItemSelected() obsługą poleceń głosowych, gdy użytkownicy je wypowiadają. Gdy użytkownik wybierze opcję z menu, polecenie głosowe "ok, Glass" automatycznie pojawi się w sekcji stopki ekranu, gdzie będzie można zaakceptować nowe polecenie. Będą one aktywne, dopóki aktywność będzie aktywna.

    Ten kod włącza kontekstowe polecenia głosowe, w razie potrzeby zapełnia zasób menu i obsługuje polecenia głosowe:

    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);
        }
    }
    

    Oto przykład zasobu menu używanego w poprzedniej aktywności. Zwróć uwagę, że możesz tworzyć zagnieżdżone pozycje menu dla hierarchicznego systemu menu głosowego. W przykładzie poniżej pierwsza pozycja w menu jest widoczna jako: OK, Glass, Pokaż psy, 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. (Opcjonalnie) Zastąp onPreparePanel(), sprawdzając, czy opcja WindowUtils.FEATURE_VOICE_COMMANDS jest włączona. Po włączeniu tej funkcji możesz używać innych funkcji do konfigurowania systemu menu, takich jak dodawanie i usuwanie określonych pozycji menu na podstawie pewnych kryteriów. W zależności od wybranych kryteriów możesz też włączyć kontekstowe menu głosowe (powrót true) i wyłączenie (powrót false). Przykład:

        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);
        }
    

Obsługują jednocześnie menu głosu i dotyku

Kontekstowe polecenia głosowe korzystają z istniejących interfejsów API menu Androida, możesz więc ponownie wykorzystać dużą ilość kodu i zasobów, które już masz na potrzeby menu dotykowych, i jednocześnie obsługiwać oba typy menu.

Wystarczy sprawdzić funkcję Window.FEATURE_OPTIONS_PANEL oprócz funkcji WindowUtils.FEATURE_VOICE_COMMANDS, która jest już sprawdzana na kilka sposobów, a następnie dodać logikę, aby otworzyć menu dotykowe dla niektórych działań użytkownika, takich jak kliknięcie.

Możesz na przykład zmienić poprzednią aktywność, by dodać obsługę menu dotykowych w ten sposób (zmiany są komentowane):

// 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) {
    ...
}

Po wprowadzeniu tych zmian możesz kliknąć lub powiedzieć OK, aby wyświetlić menu.

Korzystanie z niepublicznych poleceń głosowych na potrzeby programowania

Aby rozpowszechniać aplikację Glassware, musisz używać zatwierdzonych poleceń głównych w VoiceTriggers.Command, a zatwierdzonych kontekstowych poleceń głosowych w ContextualMenus.Command.

Jeśli chcesz używać poleceń głosowych niedostępnych w GDK, możesz poprosić o uprawnienia Androida w pliku AndroidManifest.xml:

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

Korzystanie z głównych poleceń głosowych niepublicznych

  1. Zadeklaruj wartość ciągu znaków w res/values/strings.xml, która określa nazwę aktywatora głosu. Opcjonalnie przed rozpoczęciem korzystania z Google Glass zadeklaruj komunikat głosowy, by wyświetlał rozpoznawanie mowy.

    <?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. Utwórz zasób XML dla aktywatora głosowego w: res/xml/<my_voice_trigger>.xml. W przypadku niewymienionych poleceń głosowych należy użyć atrybutu keyword zamiast atrybutu command używanego do zatwierdzonych poleceń głosowych. Atrybut keyword powinien być odwołaniem do zasobu ciągu znaków definiującego polecenie głosowe. Aby użyć prostego polecenia głosowego, które rozpoczyna działanie od razu, spowoduje to określenie elementu trigger:

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

    Aby utworzyć regułę głosową, która poprosi użytkownika o wypowiedzenie dodatkowego wyrażenia przed rozpoczęciem aktywności lub usługi, dodaj też element wprowadzania danych:

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

Używanie niepublicznych poleceń głosowych

Podczas tworzenia pozycji menu użyj dowolnego tekstu. Przykład:

<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>

Rozpoczynam rozpoznawanie mowy


Moduł rozpoznawania mowy Google czeka, aż użytkownicy coś powiedzą, i zwróci transkrypcję tekstu, gdy skończy. Aby rozpocząć aktywność:

  1. Wywołaj startActivityForResult() z intencją ACTION_RECOGNIZE_SPEECH. Po rozpoczęciu aktywności obsługiwane są te dodatki dodatkowe:
  2. Zastąp wywołanie zwrotne onActivityResult(), aby otrzymać transkrypcję tekstu z intencji EXTRA_RESULTS. To wywołanie zwrotne jest wywoływane, gdy użytkownik skończy mówić.

    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);
    }