La entrada de voz te permite crear una interfaz verdaderamente manos libres. Glass te ofrece tres formas de usar la entrada de voz.
Los comandos de voz principales inician Glassware desde la tarjeta de inicio, los comandos de voz contextuales pueden ejecutar acciones dentro de una actividad, y la actividad de reconocimiento de voz del sistema te permite recibir entradas de voz de formato libre de los usuarios.
Comandos por voz principales
Estos comandos por voz inician Glassware desde la tarjeta de inicio (tarjeta de reloj). Cuando declaras un comando por voz principal, Glass crea automáticamente un elemento de menú táctil como resguardo en caso de que los usuarios decidan iniciar tu dispositivo Glassware presionando la tarjeta de inicio.
Para agregar un comando por voz al menú principal de voz ok Glass, haz lo siguiente:
Crea un recurso XML para el comando por voz en
res/xml/<my_voice_trigger>.xml
que use uno de los comandos de voz existentes definidos enVoiceTriggers.Command
. Por ejemplo, a continuación se indica cómo usar "Iniciar una ejecución".<?xml version="1.0" encoding="utf-8"?> <trigger command="START_A_RUN" />
Para crear un comando por voz que le pida al usuario que diga una frase adicional antes de iniciar tu actividad o servicio, incluye también un elemento
input
. Por ejemplo, es posible que quieras hacerlo si usas la opción "Publicar una actualización".<?xml version="1.0" encoding="utf-8"?> <trigger command="POST_AN_UPDATE"> <input prompt="@string/glass_voice_prompt" /> </trigger>
Registra un filtro de intents con la acción
com.google.android.glass.action.VOICE_TRIGGER
en tu manifiesto de Android. El filtro de intents inicia tu actividad o servicio si detecta que los usuarios dicen tu comando por voz.<?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>
Declara un atributo
android:icon
para tu actividad o servicio. Esto permite que Glass muestre un ícono para tu Glassware en el menú táctil ok, Glass.<activity |service android:icon="@drawable/my_icon" ...> ... </activity | service>
Si tu comando por voz usa un mensaje de voz y, luego, inicia una actividad, obtén cualquier texto transcrito con el siguiente código (como en
onResume()
):ArrayList<String> voiceResults = getIntent().getExtras() .getStringArrayList(RecognizerIntent.EXTRA_RESULTS);
Si el comando por voz inicia un servicio, el intent adicional está disponible en la devolución de llamada
onStartCommand()
:@Override public int onStartCommand(Intent intent, int flags, int startId) { ArrayList<String> voiceResults = intent.getExtras() .getStringArrayList(RecognizerIntent.EXTRA_RESULTS); // ... }
Establece restricciones
Si necesitas una o todas de las siguientes funciones para iniciar tu Glassware, especifícalas en el recurso res/xml/<my_voice_trigger>.xml
.
Si las funciones no están disponibles, Glass inhabilita el comando por voz:
camera
network
microphone
<trigger command="POST_AN_UPDATE"> <constraints camera="true" network="true" /> </trigger>
Comandos por voz contextuales
Los comandos por voz contextuales permiten a los usuarios realizar acciones desde actividades. Puedes compilar comandos contextuales de voz con las API de menú estándar de Android, pero los usuarios pueden invocar los elementos de menú con comandos por voz en lugar de controles táctiles.
Para habilitar los comandos contextuales de voz para una actividad en particular:
Llama a
getWindow().requestFeature(
WindowUtils.FEATURE_VOICE_COMMANDS
)
en la actividad deseada para habilitar los comandos por voz contextuales. Cuando esta función está habilitada, el menú "ok Glass" aparece en el área del pie de página de la pantalla cada vez que esta actividad recibe el foco.Anula
onCreatePanelMenu()
y controla el caso en el queWindowUtils.FEATURE_VOICE_COMMANDS
esté habilitado. Si la opción está habilitada, aquí es donde realizas la configuración de menú única, como aumentar un recurso de menú o llamar a los métodosMenu.add()
para crear tu sistema de menú de voz.Anula
onMenuItemSelected()
para controlar los comandos por voz cuando los usuarios los digan. Cuando los usuarios terminan de seleccionar un elemento de menú, el comando por voz "ok, Glass" vuelve a aparecer automáticamente en la sección de pie de página de la pantalla, listo para aceptar un nuevo comando por voz, siempre que la actividad permanezca enfocada.El siguiente código habilita los comandos por voz contextuales, aumenta un recurso de menú cuando corresponde y controla los comandos por voz cuando se pronuncian:
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); } }
A continuación, se muestra un ejemplo del recurso de menú que se usó en la actividad anterior. Observa cómo puedes crear elementos de menú anidados para un sistema de menú de voz jerárquico. En el siguiente ejemplo, se puede acceder al primer elemento del menú de la siguiente manera: 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>
Anula
onPreparePanel()
(opcional) y verifica siWindowUtils.FEATURE_VOICE_COMMANDS
está habilitado o no. Si está habilitado, aquí puedes hacer otra lógica para configurar el sistema del menú, como agregar y quitar ciertos elementos del menú en función de algunos criterios. También puedes activar o desactivar los menús contextuales de voz contextual (mostrartrue
) y mostrar (mostrarfalse
) según algunos criterios. Por ejemplo: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); }
Cómo agregar compatibilidad con menús táctiles y de voz de forma simultánea
Debido a que los comandos de voz contextuales usan las API del menú de Android existentes, puedes reutilizar gran parte del código y los recursos que ya tienes para los menús táctiles y admitir simultáneamente ambos tipos de menús.
Lo único que debes hacer es comprobar la función Window.FEATURE_OPTIONS_PANEL
además de la función WindowUtils.FEATURE_VOICE_COMMANDS
que ya verificaste en algunos métodos y, luego, agregar lógica para abrir el menú táctil en alguna acción del usuario, como presionar una opción.
Por ejemplo, puedes cambiar el ejemplo de actividad anterior para agregar compatibilidad con menús táctiles como este (los cambios se comentan):
// 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 estos cambios, puedes presionar o decir ok Glass para mostrar el menú.
Usa comandos por voz no listados para el desarrollo
Cuando desees distribuir tu cristalería, debes usar los comandos por voz principales aprobados en VoiceTriggers.Command
y los comandos por voz contextuales aprobados en ContextualMenus.Command
.
Si deseas usar comandos por voz que no están disponibles en GDK, puedes solicitar un permiso de Android en tu archivo AndroidManifest.xml
:
<uses-permission
android:name="com.google.android.glass.permission.DEVELOPMENT" />
Usa comandos por voz principales no listados
Declara un valor de string en
res/values/strings.xml
que defina el nombre de tu activador de voz. De manera opcional, puedes declarar un mensaje de voz para mostrar la pantalla de reconocimiento de voz antes de iniciarla.<?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>
Crea un recurso XML para el activador de voz en
res/xml/<my_voice_trigger>.xml
. Para los comandos de voz no listados, debes usar el atributokeyword
en lugar del atributocommand
que se usa en los comandos de voz aprobados. El atributokeyword
debe ser una referencia al recurso de strings que define el comando por voz. Para un activador de voz simple que inicie una actividad o un servicio de inmediato, simplemente especifica el elementotrigger
:<?xml version="1.0" encoding="utf-8"?> <trigger keyword="@string/glass_voice_trigger" />
Para crear un activador de voz que le pida al usuario que diga una frase adicional antes de iniciar tu actividad o servicio, incluye también un elemento de entrada:
<?xml version="1.0" encoding="utf-8"?> <trigger keyword="@string/glass_voice_trigger"> <input prompt="@string/glass_voice_prompt" /> </trigger>
Usa comandos por voz contextuales no listados
Cuando crees elementos de menú, usa cualquier texto para el título del elemento. Por ejemplo:
<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>
Iniciando reconocimiento de voz
El reconocimiento de voz de Glassware espera a que los usuarios hablen y muestra el texto transcrito una vez que terminan. Para iniciar la actividad, haz lo siguiente:
- Llama a
startActivityForResult()
con el intentACTION_RECOGNIZE_SPEECH
. Cuando inicias la actividad, se admiten los siguientes extras de intents: Anula la devolución de llamada
onActivityResult()
para recibir el texto transcrito del intent adicionalEXTRA_RESULTS
. Se llama a esta devolución de llamada cuando los usuarios terminan de hablar.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); }