Input vocale

L'input vocale ti consente di creare un'interfaccia a mani libere. Glass offre tre modi per utilizzare l'input vocale.

I comandi vocali principali avviano Glassware dalla scheda Home, i comandi vocali contestuali possono eseguire azioni all'interno di un'attività e l'attività di riconoscimento vocale del sistema ti consente di ricevere input vocali in formato libero dagli utenti.

Comandi vocali principali

Questi comandi vocali avviano Glassware dalla scheda Home (scheda Orologio). Quando dichiari un comando vocale principale, Glass crea automaticamente una voce di menu touch come elemento di riserva se gli utenti decidono di avviare il tuo Glassware toccando la scheda Home.

Per aggiungere un comando vocale al menu principale di Ok Glass:

  1. Crea una risorsa XML per il comando vocale in res/xml/<my_voice_trigger>.xml che utilizza uno dei comandi vocali esistenti definiti in VoiceTriggers.Command. Ad esempio, ecco come utilizzare "Inizia una corsa".

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

    Per creare un comando vocale che richieda all'utente di pronunciare una frase aggiuntiva prima di iniziare l'attività o il servizio, includi anche un elemento input. Ad esempio, potresti voler eseguire questa operazione se utilizzi la funzione "Pubblica un aggiornamento".

    <?xml version="1.0" encoding="utf-8"?>
    <trigger command="POST_AN_UPDATE">
        <input prompt="@string/glass_voice_prompt" />
    </trigger>
    
  2. Registra un filtro per intent utilizzando l'azione com.google.android.glass.action.VOICE_TRIGGER nel manifest Android. Il filtro per intent avvia la tua attività o il tuo servizio se rileva utenti che pronunciano il tuo comando vocale.

    <?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. Dichiara un attributo android:icon per la tua attività o servizio. In questo modo, Glass visualizzerà un'icona per il tuo Glassware nel menu touch ok, Glass.

    <activity |service
        android:icon="@drawable/my_icon" ...>
      ...
    </activity | service>
    
  4. Se il comando vocale utilizza un messaggio vocale e avvia un'attività, ottieni il testo trascritto con il seguente codice (ad esempio in onResume()):

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

    Se il comando vocale avvia un servizio, l'intent aggiuntivo è disponibile nel callback onStartCommand():

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

Impostazione dei vincoli

Se ti servono una o tutte le funzionalità seguenti per avviare il tuo Glassware, specificale nella risorsa res/xml/<my_voice_trigger>.xml. Se le funzionalità non sono disponibili, Glass disattiva il comando vocale:

  • camera
  • network
  • microphone

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

Comandi vocali contestuali

I comandi vocali contestuali consentono agli utenti di eseguire azioni dalle attività. Puoi creare comandi vocali contestuali con le API di menu standard di Android, ma gli utenti possono richiamare le voci di menu con comandi vocali anziché con il tocco.

Per attivare i comandi vocali contestuali per una determinata attività:

  1. Chiama il numero getWindow().requestFeature(WindowUtils.FEATURE_VOICE_COMMANDS) nell'attività desiderata per attivare i comandi vocali contestuali. Se questa funzionalità è attiva, il menu "ok Glass" viene visualizzato nell'area del piè di pagina dello schermo ogni volta che l'attività riceve lo stato attivo.

  2. Sostituisci onCreatePanelMenu() e gestisci la richiesta di assistenza in cui WindowUtils.FEATURE_VOICE_COMMANDS è attivo. Se questa opzione è attiva, puoi eseguire la configurazione del menu una tantum, ad esempio per gonfiare una risorsa del menu o chiamare i metodi di Menu.add() per creare il sistema di menu vocali.

  3. Sostituisci onMenuItemSelected() per gestire i comandi vocali quando gli utenti li pronunciano. Quando gli utenti hanno selezionato una voce di menu, il comando vocale "ok, Glass" ricompare automaticamente nella sezione piè di pagina dello schermo, pronto per accettare un nuovo comando vocale, purché l'attività rimanga attiva.

    Il codice seguente abilita i comandi vocali contestuali, gonfia una risorsa del menu quando opportuno e gestisce i comandi vocali quando vengono pronunciati:

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

    Ecco un esempio della risorsa di menu utilizzata dall'attività precedente. Nota come creare voci di menu nidificate per un sistema di menu vocale gerarchico. Nell'esempio seguente, la prima voce di menu è accessibile come: ok Glass, Fammi vedere i cani, 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. (Facoltativo) Esegui l'override di onPreparePanel() per verificare se WindowUtils.FEATURE_VOICE_COMMANDS è attivo. Se questa opzione è attiva, puoi configurare altri sistemi di configurazione del menu, ad esempio aggiungere e rimuovere alcune voci di menu in base ad alcuni criteri. Puoi anche attivare o disattivare i menu vocali contestuali (restituzione true) (restituzione false) in base ad alcuni criteri. Ad esempio:

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

Supporto dei menu vocali e touch contemporanei

Poiché i comandi vocali contestuali utilizzano le API di menu esistenti di Android, puoi riutilizzare gran parte del codice e delle risorse che hai già a disposizione per i menu touch e supportare contemporaneamente entrambi i tipi di menu.

Tutto ciò che devi fare è controllare la funzionalità Window.FEATURE_OPTIONS_PANEL, oltre alla funzionalità WindowUtils.FEATURE_VOICE_COMMANDS che stai già controllando in alcuni metodi, quindi aggiungere la logica per aprire il menu touch su alcune azioni degli utenti, ad esempio un tocco.

Ad esempio, puoi modificare l'attività precedente per aggiungere il supporto per menu touch come questo (le modifiche vengono commentate):

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

Con queste modifiche, puoi toccare o dire vetro per visualizzare il menu.

Utilizzo di comandi vocali non in elenco per lo sviluppo

Per distribuire i tuoi Glassware, devi utilizzare i comandi vocali principali approvati in VoiceTriggers.Command e i comandi vocali contestuali approvati in ContextualMenus.Command.

Se vuoi usare i comandi vocali non disponibili nel GDK, puoi richiedere un'autorizzazione Android nel tuo file AndroidManifest.xml:

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

Utilizzare i comandi vocali principali non in elenco

  1. Dichiara un valore stringa in res/values/strings.xml che definisce il nome dell'attivatore vocale. Facoltativamente, dichiara una richiesta di voce per visualizzare il riconoscimento vocale di Glassware prima di avviare il 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. Crea una risorsa XML per il trigger vocale in res/xml/<my_voice_trigger>.xml. Per i comandi vocali non in elenco, devi utilizzare l'attributo keyword invece dell'attributo command per i comandi vocali approvati. L'attributo keyword deve essere un riferimento alla risorsa stringa che definisce il comando vocale. Per un semplice trigger vocale che avvia immediatamente un'attività o un servizio, è sufficiente specificare l'elemento trigger:

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

    Per creare un trigger vocale che richieda all'utente di pronunciare una frase aggiuntiva prima di iniziare l'attività o il servizio, includi anche un elemento di input:

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

Usare comandi vocali contestuali non in elenco

Durante la creazione di voci di menu, utilizza del testo per il titolo della voce. Ad esempio:

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

Avvio del riconoscimento vocale


Il riconoscimento vocale di Glassware attende che gli utenti parlino e restituiscano il testo trascritto al termine. Per avviare l'attività:

  1. Chiamare startActivityForResult() con l'intent ACTION_RECOGNIZE_SPEECH. Quando avvii l'attività, sono supportati i seguenti intent aggiuntivi:
  2. Sostituisci il callback onActivityResult() per ricevere il testo trascritto dall'intent aggiuntivo EXTRA_RESULTS. Questo callback viene chiamato quando gli utenti hanno finito di parlare.

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