Голосовой ввод позволяет создать по-настоящему интерфейс без помощи рук. Glass предлагает три способа использования голосового ввода.
Основные голосовые команды запускают Glassware с домашней карты, контекстные голосовые команды могут выполнять действия внутри действия, а функция распознавания речи системы позволяет получать голосовой ввод в произвольной форме от пользователей.
Основные голосовые команды
Эти голосовые команды запускают Glassware с домашней карты (карты часов). Когда вы объявляете основную голосовую команду, Glass автоматически создает пункт сенсорного меню в качестве запасного варианта, если пользователи решат запустить Glassware, нажав на карточку «Домой».
Чтобы добавить голосовую команду в главное меню ok glass voice:
Создайте ресурс XML для голосовой команды в
res/xml/<my_voice_trigger>.xml
который использует одну из существующих голосовых команд, определенных вVoiceTriggers.Command
. Например, вот как использовать «Начать пробежку».<?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>
Зарегистрируйте фильтр намерений, используя действие
com.google.android.glass.action.VOICE_TRIGGER
в манифесте Android. Фильтр намерений запускает ваше действие или службу, если обнаруживает, что пользователи произносят вашу голосовую команду.<?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>
Объявите атрибут
android:icon
для вашего действия или службы. Это позволяет Glass отображать значок вашей посуды в сенсорном меню «ОК, стекло» .<activity |service android:icon="@drawable/my_icon" ...> ... </activity | service>
Если ваша голосовая команда использует голосовую подсказку и запускает действие, получите любой расшифрованный текст с помощью следующего кода (например, в
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>
Контекстные голосовые команды
Контекстные голосовые команды позволяют пользователям выполнять действия из действий. Вы создаете контекстные голосовые команды с помощью стандартных API-интерфейсов меню Android, но пользователи могут вызывать пункты меню с помощью голосовых команд, а не касания.
Чтобы включить контекстные голосовые команды для определенного действия:
Вызовите
getWindow().requestFeature(
WindowUtils.FEATURE_VOICE_COMMANDS
)
в нужном действии, чтобы включить контекстные голосовые команды. Если эта функция включена, меню «ОК» появляется в нижней части экрана всякий раз, когда это действие получает фокус.Переопределите
onCreatePanelMenu()
и обработайте случай, когдаWindowUtils.FEATURE_VOICE_COMMANDS
включен. Если этот параметр включен, здесь вы выполняете однократную настройку меню, например, наполнение ресурса меню или вызов методовMenu.add()
для создания системы голосового меню.Переопределите
onMenuItemSelected()
для обработки голосовых команд, когда пользователи их произносят. Когда пользователи завершают выбор пункта меню, голосовая команда «ОК, стакан» автоматически появляется в нижней части экрана, готовая принять новую голосовую команду, пока действие остается в фокусе.Следующий код включает контекстные голосовые команды, при необходимости расширяет ресурс меню и обрабатывает голосовые команды при их произнесении:
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); } }
Вот пример ресурса меню, использованного предыдущим действием. Обратите внимание, как можно создавать вложенные пункты меню для иерархической системы голосового меню. В следующем примере доступ к первому пункту меню можно получить как: ок стекло, Покажи мне собак, Лабрадор .
<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>
(Необязательно) Переопределить
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); }
Одновременная поддержка голосового и сенсорного меню
Поскольку контекстные голосовые команды используют существующие API-интерфейсы меню Android, вы можете повторно использовать большую часть кода и ресурсов, которые у вас уже есть для сенсорных меню, и одновременно поддерживать оба типа меню.
Все, что вам нужно сделать, это проверить наличие функции Window.FEATURE_OPTIONS_PANEL
в дополнение к функции WindowUtils.FEATURE_VOICE_COMMANDS
, которую вы уже проверяете в нескольких методах, а затем добавить логику для открытия сенсорного меню при некоторых действиях пользователя, например касании. .
Например, вы можете изменить предыдущий пример активности, чтобы добавить поддержку таких сенсорных меню (изменения прокомментированы):
// 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) {
...
}
Благодаря этим изменениям вы можете нажать или сказать «ОК» , чтобы отобразить меню.
Использование скрытых голосовых команд для разработки
Если вы хотите распространять свою стеклянную посуду, вы должны использовать утвержденные основные голосовые команды в VoiceTriggers.Command
и утвержденные контекстные голосовые команды в ContextualMenus.Command
.
Если вы хотите использовать голосовые команды, которых нет в GDK, вы можете запросить разрешение Android в файле AndroidManifest.xml
:
<uses-permission
android:name="com.google.android.glass.permission.DEVELOPMENT" />
Использование скрытых основных голосовых команд
Объявите строковое значение в
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>
Создайте ресурс XML для голосового триггера в
res/xml/<my_voice_trigger>.xml
. Для голосовых команд, не включенных в список, следует использовать атрибутkeyword
вместо атрибутаcommand
, используемого для утвержденных голосовых команд. Атрибут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 ожидает, пока пользователи заговорят, и возвращает расшифрованный текст после того, как они закончат. Чтобы начать действие:
- Вызовите
startActivityForResult()
с намерениемACTION_RECOGNIZE_SPEECH
. При запуске действия поддерживаются следующие дополнительные намерения: Переопределите обратный вызов
onActivityResult()
, чтобы получить расшифрованный текст из дополнительного намеренияEXTRA_RESULTS
. Этот обратный вызов вызывается, когда пользователи заканчивают говорить.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); }