1. Обзор
В первом практическом занятии по App Actions вы узнали, как расширить функциональность Google Assistant для примера фитнес-приложения, реализовав встроенные интенты (BII) из категории BII «Здоровье и фитнес».
Функция App Actions позволяет пользователям запускать определенные функции приложений непосредственно из Ассистента, задавая, например: « Привет, Google, начни пробежку в ExampleApp». Помимо запуска приложений, Ассистент может отображать пользователю интерактивный виджет Android для выполнения запросов для соответствующих BII-функций.

Что вы построите
В этом практическом занятии вы научитесь возвращать виджеты Android для выполнения запросов пользователей Google Ассистента. Вы также узнаете:
- Используйте параметры BII для персонализации виджетов.
- Добавьте в Assistant голосовые вступительные фразы, воспроизводимые с помощью функции преобразования текста в речь (TTS).
- Используйте справочник встроенных намерений , чтобы определить, какие встроенные намерения поддерживают выполнение виджетов.
Предварительные требования
Прежде чем продолжить, убедитесь, что ваша среда разработки готова для использования App Actions. Она должна включать в себя:
- Терминал для выполнения команд оболочки с установленным Git.
- Последняя стабильная версия Android Studio .
- Физическое или виртуальное устройство Android с доступом в Интернет.
- Учетная запись Google, которая авторизована в Android Studio, приложении Google и приложении Google Assistant.
Если вы используете физическое устройство, подключите его к локальному компьютеру разработчика.
2. Разберитесь, как это работает.
Google Ассистент использует понимание естественного языка (NLU) для чтения запроса пользователя и сопоставления его со встроенным намерением Ассистента (BII). Затем Ассистент сопоставляет намерение с возможностью (реализующей BII), которую вы регистрируете для этого намерения в своем приложении. Наконец, Ассистент выполняет запрос пользователя, отображая виджет Android, сгенерированный вашим приложением на основе данных, найденных в этой возможности.
В этом практическом задании вы определяете возможность, которая регистрирует поддержку BII GET_EXERCISE_OBSERVATION . В этой возможности вы указываете Ассистенту сгенерировать Android-интент для класса виджета FitActions , чтобы выполнить запросы для этого BII. Вы обновляете этот класс, чтобы сгенерировать персонализированный виджет для отображения Ассистентом пользователю, а также текстовое сопровождение для озвучивания Ассистентом.
Следующая диаграмма иллюстрирует этот процесс:

Виджет FitActions
В демонстрационном приложении FitActions содержится виджет с информацией о тренировке, который пользователи могут добавить на главный экран. Этот виджет отлично подходит для обработки запросов пользователей, запускающих BII-функцию GET_EXERCISE_OBSERVATION .
Как работает виджет
Когда пользователь добавляет виджет на главный экран, виджет отправляет запрос широковещательному приемнику устройства. Этот сервис получает информацию о виджете из определения приемника виджета в ресурсе AndroidManifest.xml приложения. Он использует эту информацию для генерации объекта RemoteViews , представляющего виджет.
В примере приложения определен виджет получателя widgets.StatsWidgetProvider , который соответствует классу StatsWidgetProvider :
<!-- app/src/main/AndroidManifest.xml -->
<receiver
android:name=".widgets.StatsWidgetProvider"
android:exported="false">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/stats_widget" />
</receiver>
Класс StatsWidgetProvider ( StatsWidgetProvider.kt ) управляет процессом создания объекта StatsWidget . Он выполняет следующие функции:
- Создание экземпляров виджетов и заполнение их данными об упражнениях из базы данных приложения.
- Форматирование данных о тренировках для повышения читаемости с помощью
formatDataAndSetWidget(). - Если данные о тренировке недоступны, используются значения по умолчанию, заданные с помощью
setNoActivityDataWidget().
Добавить поддержку помощника
В этом практическом задании вы обновите тестовое приложение, чтобы оно поддерживало функциональность App Actions. Эти изменения включают в себя:
- Настройка возможности BII
GET_EXERCISE_OBSERVATIONдля возврата экземпляра объектаStatsWidget. - Обновление класса
StatsWidgetдля использования функций App Actions, таких как:- Использование параметров BII позволяет пользователям просматривать статистику конкретных тренировок, задавая вопросы, например: «Привет, Google, покажи мне статистику моих пробежек в ExampleApp».
- Предоставление вводных строк для синтеза речи.
- Обработка особых случаев, например, когда пользовательский запрос не содержит параметра типа тренировки.
3. Подготовьте среду разработки.
Загрузите базовые файлы.
Выполните эту команду, чтобы клонировать репозиторий GitHub с примером приложения:
git clone --branch start-widget-codelab https://github.com/actions-on-google/appactions-fitness-kotlin.git
После клонирования репозитория выполните следующие действия, чтобы открыть его в Android Studio:
- В диалоговом окне «Добро пожаловать в Android Studio» нажмите «Импорт проекта» .
- Найдите и выберите папку, куда вы клонировали репозиторий.
Чтобы увидеть версию приложения, соответствующую пройденному практическому заданию, клонируйте репозиторий с примерами приложений, используя флаг --branch master .
Обновите идентификатор приложения Android.
Обновление идентификатора приложения позволяет однозначно идентифицировать приложение на вашем тестовом устройстве и избежать ошибки «Дублирующееся имя пакета», если приложение загружено в Play Console. Чтобы обновить идентификатор приложения, откройте файл app/build.gradle :
android {
...
defaultConfig {
applicationId "com.MYUNIQUENAME.android.fitactions"
...
}
}
Замените "MYUNIQUENAME" в поле applicationId на уникальное для вас имя.
Установите тестовый плагин
Плагин Google Assistant позволяет тестировать действия вашего приложения на тестовом устройстве. Он работает, отправляя информацию в Assistant через приложение Google на вашем устройстве Android. Если у вас еще нет плагина, установите его, выполнив следующие действия:
- Перейдите в меню Файл > Настройки ( в Android Studio > Настройки на MacOS).
- В разделе «Плагины» перейдите в Marketplace и найдите «Google Assistant». Вы также можете вручную загрузить и установить тестовый инструмент.
- Установите инструмент и перезапустите Android Studio.
Протестируйте приложение на своем устройстве.
Прежде чем вносить дальнейшие изменения в приложение, полезно ознакомиться с возможностями демонстрационного примера.
Запустите приложение на тестовом устройстве:
- В Android Studio выберите ваше физическое или виртуальное устройство и выберите Run > Run app или нажмите Run.
на панели инструментов. - Нажмите и удерживайте кнопку «Домой», чтобы настроить Ассистента и убедиться в его работоспособности. Вам потребуется войти в Ассистента на вашем устройстве, если вы еще этого не сделали.
Для получения дополнительной информации о виртуальных устройствах Android см. раздел «Создание и управление виртуальными устройствами» .
Кратко изучите приложение, чтобы увидеть, на что оно способно. Приложение автоматически заполняет 10 вариантов упражнений и отображает эту информацию при первом запуске.
Попробуйте существующий виджет.
- Нажмите кнопку «Домой» , чтобы перейти на главный экран вашего тестового устройства.
- Нажмите и удерживайте пустое место на главном экране и выберите «Виджеты» .
- Прокрутите список виджетов вниз до раздела FitActions .
- Нажмите и удерживайте значок FitActions, чтобы разместить его виджет на главном экране.

4. Добавьте действие приложения.
На этом шаге вы добавляете возможность BII GET_EXERCISE_OBSERVATION . Для этого добавьте новый элемент capability в shortcuts.xml . Эта возможность определяет, как запускается данная функция, как используются параметры BII и какие Android-интенты следует вызвать для выполнения запроса.
- Добавьте новый элемент
capabilityв ресурсshortcuts.xmlпримера проекта со следующей конфигурацией: Замените значение<!-- fitnessactions/app/src/main/res/xml/shortcuts.xml --> <capability android:name="actions.intent.GET_EXERCISE_OBSERVATION"> <app-widget android:identifier="GET_EXERCISE_OBSERVATION" android:targetClass="com.devrel.android.fitactions.widgets.StatsWidgetProvider" android:targetPackage="PUT_YOUR_APPLICATION_ID_HERE"> <parameter android:name="exerciseObservation.aboutExercise.name" android:key="aboutExerciseName" android:required="true"> </parameter> <extra android:name="hasTts" android:value="true"/> </app-widget> <!-- Add Fallback Intent--> </capability>android:targetPackage,PUT_YOUR_APPLICATION_ID_HERE, на ваш уникальныйapplicationId.
Эта возможность сопоставляет BII-объект GET_EXERCISE_OBSERVATION с намерением app-widget , так что при срабатывании BII-объекта виджет создается и отображается пользователю.
Перед запуском виджета Ассистент извлекает поддерживаемые параметры BII из запроса пользователя. Для этого практического занятия требуется параметр BII exerciseObservation.aboutExercise.name , который представляет собой запрошенный пользователем тип упражнения. Приложение поддерживает три типа упражнений: «бег», «ходьба» и «езда на велосипеде». Вы предоставляете встроенный список , чтобы сообщить Ассистенту о поддерживаемых значениях.
- Определите эти элементы инвентаризации, добавив следующую конфигурацию в
shortcuts.xml, выше параметраGET_EXERCISE_OBSERVATION:<!-- shortcuts.xml --> <!-- shortcuts are bound to the GET_EXERCISE_OBSERVATION capability and represent the types of exercises supported by the app. --> <shortcut android:shortcutId="running" android:shortcutShortLabel="@string/activity_running"> <capability-binding android:key="actions.intent.GET_EXERCISE_OBSERVATION"> <parameter-binding android:key="exerciseObservation.aboutExercise.name" android:value="@array/runningSynonyms"/> </capability-binding> </shortcut> <shortcut android:shortcutId="walking" android:shortcutShortLabel="@string/activity_walking"> <capability-binding android:key="actions.intent.GET_EXERCISE_OBSERVATION"> <parameter-binding android:key="exerciseObservation.aboutExercise.name" android:value="@array/walkingSynonyms"/> </capability-binding> </shortcut> <shortcut android:shortcutId="cycling" android:shortcutShortLabel="@string/activity_cycling"> <capability-binding android:key="actions.intent.GET_EXERCISE_OBSERVATION"> <parameter-binding android:key="exerciseObservation.aboutExercise.name" android:value="@array/cyclingSynonyms"/> </capability-binding> </shortcut> <capability android:name="actions.intent.GET_EXERCISE_OBSERVATION"> <!-- ... --> </capability>
Добавьте резервный вариант намерения
Резервные намерения обрабатывают ситуации, когда запрос пользователя не может быть выполнен, поскольку в запросе отсутствуют параметры, необходимые для данной возможности. Возможность GET_EXERCISE_OBSERVATION требует параметра exerciseObservation.aboutExercise.name , указанного атрибутом android:required="true" . В таких ситуациях Ассистент требует от вас определить резервное намерение, позволяющее выполнить запрос успешно, даже если в запросе не указаны параметры.
- В
shortcuts.xmlдобавьте резервный интент для возможностиGET_EXERCISE_OBSERVATION, используя следующую конфигурацию:<!-- shortcuts.xml --> <capability android:name="actions.intent.GET_EXERCISE_OBSERVATION"> <app-widget> <!-- ... --> </app-widget> <!-- Fallback intent with no parameters needed to successfully execute.--> <intent android:identifier="GET_EXERCISE_OBSERVATION_FALLBACK" android:action="android.intent.action.VIEW" android:targetClass="com.devrel.android.fitactions.widgets.StatsWidgetProvider"> </intent> </capability>
В данной конфигурации в качестве резервного варианта используется Android-интент без параметров в Extra данных.
5. Включите виджет для Ассистента.
После установки возможности GET_EXERCISE_OBSERVATION обновите класс виджета, чтобы он поддерживал голосовой вызов действий приложения.
Добавьте библиотеку расширений виджетов.
Библиотека расширений App Actions Widgets Extension расширяет возможности ваших виджетов для работы с голосовым помощником. В частности, она позволяет задавать пользовательское вступление в формате TTS для ваших виджетов.
- Добавьте зависимость библиотеки Widgets Extension в ресурс
/app/build.gradleпримера приложения: В появившемся в Android Studio окне предупреждения нажмите «Синхронизировать сейчас» . Синхронизация после каждого изменения// app/build.gradle dependencies { //... implementation "com.google.assistant.appactions:widgets:0.0.1" }build.gradleпомогает избежать ошибок при сборке приложения.
Добавить сервис виджетов
Сервис — это компонент приложения, способный выполнять длительные операции в фоновом режиме. Вашему приложению необходимо предоставлять сервис для обработки запросов виджетов.
- Добавьте службу в ресурс
AndroidManifest.xmlтестового приложения, используя следующую конфигурацию:<!-- AndroidManifest.xml --> <service android:name=".widgets.StatsWidgetProvider" android:enabled="true" android:exported="true"> <intent-filter> <action android:name="com.google.assistant.appactions.widgets.PIN_APP_WIDGET" /> </intent-filter> </service>
В случае голосового запроса, запускающего выполнение виджета, Ассистент использует этот сервис для отправки запросов в приложение. Сервис получает запрос вместе с данными BII. Сервис использует эти данные для создания объекта виджета RemoteView , который отображается в Ассистенте.
Обновите класс виджета
Теперь ваше приложение настроено на переадресацию запросов GET_EXERCISE_OBSERVATION в ваш класс виджета. Далее обновите класс StatsWidget.kt , чтобы создать экземпляр виджета, персонализированный под запрос пользователя, используя значения параметров BII.
- Откройте класс
StatsWidget.ktи импортируйте библиотеку расширения App Actions Widget Extension:// StatsWidget.kt // ... Other import statements import com.google.assistant.appactions.widgets.AppActionsWidgetExtension - Добавьте следующие приватные переменные, которые вы используете при определении информации, которая должна заполнять виджет:
// StatsWidget.kt private val hasBii: Boolean private val isFallbackIntent: Boolean private val aboutExerciseName: String private val exerciseType: FitActivity.Type - Добавьте функцию
init, чтобы класс мог использовать данные параметров виджета, переданные из Assistant:// StatsWidget.kt init { val optionsBundle = appWidgetManager.getAppWidgetOptions(appWidgetId) val bii = optionsBundle.getString(AppActionsWidgetExtension.EXTRA_APP_ACTIONS_BII) hasBii = !bii.isNullOrBlank() val params = optionsBundle.getBundle(AppActionsWidgetExtension.EXTRA_APP_ACTIONS_PARAMS) if (params != null) { isFallbackIntent = params.isEmpty if (isFallbackIntent) { aboutExerciseName = context.resources.getString(R.string.activity_unknown) } else { aboutExerciseName = params.get("aboutExerciseName") as String } } else { isFallbackIntent = false aboutExerciseName = context.resources.getString(R.string.activity_unknown) } exerciseType = FitActivity.Type.find(aboutExerciseName) }
Давайте рассмотрим, как эти обновления позволяют классу StatsWidget.kt реагировать на намерения Android, генерируемые возможностью GET_EXERCISE_OBSERVATION :
-
optionsBundle= Bundle- Объекты Bundle предназначены для использования на разных этапах процесса, между действиями с намерениями, а также для хранения временного состояния при изменении конфигурации. Assistant использует объекты
Bundleдля передачи данных конфигурации виджету.
- Объекты Bundle предназначены для использования на разных этапах процесса, между действиями с намерениями, а также для хранения временного состояния при изменении конфигурации. Assistant использует объекты
-
bii=actions.intent.GET_EXERCISE_OBSERVATION- Название BII можно получить из пакета, используя расширение
AppActionsWidgetExtension.
- Название BII можно получить из пакета, используя расширение
-
hasBii=true- Проверяет наличие BII.
-
params=Bundle[{aboutExerciseName=running}]- Специальный пакет (Bundle), генерируемый действиями приложения (App Actions), вложен в
Bundleпараметров виджета (Visitd options Bundle). Он содержит пары ключ/значение BII. В данном случае значениеrunningбыло извлечено из примера запроса: "Hey Google, show my running stats on ExampleApp".
- Специальный пакет (Bundle), генерируемый действиями приложения (App Actions), вложен в
-
isFallbackIntent=false- Проверяет наличие необходимых параметров BII в параметрах
Extras.
- Проверяет наличие необходимых параметров BII в параметрах
-
aboutExerciseName=running- Получает значение параметра
ExtrasдляaboutExerciseName.
- Получает значение параметра
-
exerciseType=RUNNING- Использует
aboutExerciseNameдля поиска соответствующего объекта типа в базе данных.
- Использует
Теперь, когда класс StatsWidget может обрабатывать входящие данные из Android-интентов App Actions, обновите логику создания виджета, чтобы проверять, был ли виджет запущен действием App Action.
- В
StatsWidget.ktзамените функциюupdateAppWidget()следующим кодом:// StatsWidget.kt fun updateAppWidget() { /** * Checks for App Actions BII invocation and if BII parameter data is present. * If parameter data is missing, use data from last exercise recorded to the * fitness tracking database. */ if (hasBii && !isFallbackIntent) { observeAndUpdateRequestedExercise() } else observeAndUpdateLastExercise() }
Приведённый выше код ссылается на новую функцию observeAndUpdateRequestedExercise . Эта функция генерирует данные виджета, используя данные параметра exerciseType , передаваемые из Android-интента App Actions.
- Добавьте функцию
observeAndUpdateRequestedExerciseсо следующим кодом:// StatsWidget.kt /** * Create and observe the last exerciseType activity LiveData. */ private fun observeAndUpdateRequestedExercise() { val activityData = repository.getLastActivities(1, exerciseType) activityData.observeOnce { activitiesStat -> if (activitiesStat.isNotEmpty()) { formatDataAndSetWidget(activitiesStat[0]) updateWidget() } else { setNoActivityDataWidget() updateWidget() } } }
В приведенном выше коде используйте существующий класс репозитория , найденный в приложении, для получения данных о физической активности из локальной базы данных приложения. Этот класс предоставляет API, упрощающий доступ к базе данных. Репозиторий работает, предоставляя объект LiveData при выполнении запросов к базе данных. В вашем коде вы отслеживаете этот LiveData для получения последних данных о физической активности.
Включить TTS
Вы можете указать текстовую строку преобразования в речь (TTS), которую Ассистент будет озвучивать при отображении вашего виджета. Мы рекомендуем включить её, чтобы обеспечить звуковой контекст для ваших виджетов. Эта функция предоставляется библиотекой расширений App Actions Widgets Extension, которая позволяет устанавливать текст и TTS-вступления, сопровождающие ваши виджеты в Ассистенте.
Удачное место для введения в технологию преобразования текста в речь — это функция formatDataAndSetWidget , которая форматирует данные об активности, возвращаемые из базы данных приложения.
- В
StatsWidget.ktдобавьте следующий код в функциюformatDataAndSetWidget:// StatsWidget.kt private fun formatDataAndSetWidget( activityStat: FitActivity, ) { // ... // Add conditional for hasBii for widget with data if (hasBii) { // Formats TTS speech and display text for Assistant val speechText = context.getString( R.string.widget_activity_speech, activityExerciseTypeFormatted, formattedDate, durationInMin, distanceInKm ) val displayText = context.getString( R.string.widget_activity_text, activityExerciseTypeFormatted, formattedDate ) setTts(speechText, displayText) } }
Приведённый выше код ссылается на два строковых ресурса: один для речи, а другой для текста. Рекомендации по стилю преобразования текста в речь (TTS) можно найти в разделе «Рекомендации по стилю преобразования текста в речь» нашего видео о виджетах. В примере также упоминается функция setTts , которая предоставляет информацию о TTS экземпляру виджета.
- Добавьте новую функцию
setTtsвStatsWidget.kt, используя следующий код:// StatsWidget.kt /** * Sets TTS to widget */ private fun setTts( speechText: String, displayText: String, ) { val appActionsWidgetExtension: AppActionsWidgetExtension = AppActionsWidgetExtension.newBuilder(appWidgetManager) .setResponseSpeech(speechText) // TTS to be played back to the user .setResponseText(displayText) // Response text to be displayed in Assistant .build() // Update widget with TTS appActionsWidgetExtension.updateWidget(appWidgetId) }
Наконец, завершите логику преобразования текста в речь, установив информацию о преобразовании текста в речь, когда база данных упражнений возвращает пустые данные для запрошенного типа тренировки.
- Обновите функцию
setNoActivityDataWidget()вStatsWidget.kt, добавив следующий код:// StatsWidget.kt private fun setNoActivityDataWidget() { // ... // Add conditional for hasBii for widget without data if (hasBii) { // formats speech and display text for Assistant // https://developers.google.com/assistant/app/widgets#library val speechText = context.getString(R.string.widget_no_activity_speech, aboutExerciseName) val displayText = context.getString(R.string.widget_no_activity_text) setTts(speechText, displayText) } }
6. Протестируйте действие приложения.
В процессе разработки используйте плагин Google Assistant для предварительного просмотра действий приложения Assistant на тестовом устройстве. С помощью этого инструмента вы можете настроить параметры намерения для действия приложения, чтобы проверить, как ваше действие обрабатывает различные способы, которыми пользователь может попросить Assistant его выполнить.
Создать предварительный просмотр
Чтобы протестировать действие вашего приложения с помощью плагина:
- Перейдите в меню Инструменты > Google Ассистент > Инструмент тестирования действий приложения . Возможно, вам потребуется войти в Android Studio, используя свою учетную запись Google.
- Нажмите «Создать предварительный просмотр» . При необходимости ознакомьтесь с политикой и условиями использования App Actions и примите их.
Проверьте ожидаемый тип упражнений.
В инструменте тестирования выполните следующие действия, чтобы получить виджет, отображающий информацию о последнем завершенном запуске приложения:
- На первом шаге, когда инструмент запрашивает выбор и настройку BII, выберите
actions.intent.GET_EXERCISE_OBSERVATION. - В поле exerciseObservation измените название упражнения по умолчанию с
climbingнаrun. - Нажмите «Запустить действие приложения» .

Попробуйте неожиданный вид упражнений.
Чтобы проверить неожиданный тип упражнений в инструменте тестирования:
- В поле exerciseObservation измените значение
nameсRunнаClimbing. - Нажмите «Запустить действие приложения» .
Ассистент должен вернуть виджет с информацией "Активность не найдена".

Проверьте резервный вариант намерения
Запросы, запускающие резервный вариант, должны возвращать виджет, отображающий информацию о последней зарегистрированной активности любого типа упражнений.
Чтобы проверить резервный вариант:
- В поле exerciseObservation удалите объект
aboutExercise. - Нажмите «Запустить действие приложения» .
Функция «Помощник» должна вернуть виджет, отображающий информацию о последнем завершенном упражнении.

7. Дальнейшие шаги
Поздравляем!
Теперь у вас есть возможность отвечать на запросы пользователей с помощью виджета Android с функцией Assistant.
Что мы рассмотрели
В этом практическом занятии вы научились:
- Добавить виджет приложения в BII.
- Измените виджет для доступа к параметрам из Android Extras.
Что дальше?
Отсюда вы можете попробовать внести дальнейшие улучшения в свое фитнес-приложение. Чтобы посмотреть готовый проект, перейдите в основной репозиторий на GitHub.
Вот несколько рекомендаций для дальнейшего изучения возможностей расширения функциональности этого приложения с помощью App Actions:
- Чтобы узнать больше о способах расширения функциональности ваших приложений для Google Ассистента, посетите раздел «Справочник по встроенным интентам в App Actions».
Чтобы продолжить работу с Actions on Google, ознакомьтесь с этими ресурсами:
- developers.google.com/assistant/app : Официальный сайт документации по действиям приложения Google Assistant.
- Указатель примеров приложений и кода для изучения возможностей App Actions.
- Действия в репозитории Google GitHub : примеры кода и библиотек.
- r/GoogleAssistantDev : Официальное сообщество Reddit для разработчиков, работающих с Google Assistant.
Подписывайтесь на нас в Твиттере @ActionsOnGoogle , чтобы быть в курсе наших последних объявлений, и делитесь своими разработками в Твиттере с хэштегом #appactions !
Опрос обратной связи
В заключение, пожалуйста, заполните этот опрос , чтобы оставить отзыв о вашем опыте работы с этим практическим занятием.