1. Прежде чем начать
API Google Home предоставляют разработчикам Android набор библиотек для работы с экосистемой Google Home. Благодаря этим новым API разработчики могут создавать приложения, которые позволяют беспрепятственно вводить в эксплуатацию и управлять устройствами умного дома.
В этом видео представлен краткий обзор мобильного приложения, которое вы будете создавать, поэтому следите за видео во время выполнения практического задания.
Google предоставляет разработчикам демонстрационное приложение для Android, позволяющее получить доступ к работающему примеру использования API Google Home. Данный практический пример основан на ветке демонстрационного приложения и покажет, как использовать API разрешений, ввода в эксплуатацию, устройств и структуры.
Предварительные требования
- Знание экосистемы Google Home ( Cloud-to-cloud и Matter ).
- Рабочая станция с установленной программой Android Studio (версия 2024.3.1 Ladybug или более поздняя).
- Для работы приложения требуется Android-смартфон, соответствующий требованиям API Home (см. раздел «Предварительные условия» ), с установленными сервисами Google Play и приложением Google Home . Эмулятор не подойдёт , для демонстрации приложения поддерживаются только физические Android-смартфоны.
- Совместимый концентратор Google Home , поддерживающий API Google Home .
- Дополнительно — устройство для умного дома, совместимое с API Google Home.
Что вы узнаете
- Как создать Android-приложение с использованием API Google Home, следуя лучшим практикам.
- Как использовать API-интерфейсы Device и Structure для представления и управления умным домом.
- Как использовать API ввода в эксплуатацию для добавления устройств в экосистему Google Home.
Дополнительно: обустройте свой дом
Перед использованием API Google Home вам необходимо настроить дом в своей учетной записи Google с помощью приложения Google Home и добавить несколько устройств. В этом разделе описывается, как это сделать с помощью Google Home Playground , который предоставляет виртуальные устройства для умного дома.
Откройте сайт home-playground.withgoogle.com в своем веб-браузере, войдите в систему с помощью своей учетной записи Google и проверьте, отображаются ли следующие эмулируемые устройства:
- розетка 1: штекер включения/выключения
- light2: Диммируемый светильник
- light3: Индикатор включения/выключения
- ac3: Кондиционер
- жалюзи4: Оконные покрытия
- стиральная машина5: Умная стиральная машина

Откройте приложение Google Home на своем мобильном устройстве, нажмите кнопку «Добавить » и выберите «Работает с Google Home». Найдите в списке «игровая площадка», затем выберите проект «Google Home Playground» и нажмите « Продолжить» .



В Google Home Playground отобразится страница авторизации учетной записи. Нажмите «Авторизовать» или «Войти через Google» . В мобильном приложении вы увидите все устройства, которые вы настроили через веб-приложение.


Выберите все устройства и завершите процесс настройки. Вернувшись на главную страницу, вы увидите все доступные устройства.

Устройства из этого списка, на которые распространяется поддержка Google Home, теперь доступны для использования с API Google Home.
2. Настройте свой проект.
На следующей диаграмме представлена архитектура приложения Home APIs:

- Код приложения: Основной код, над которым работают разработчики для создания пользовательского интерфейса приложения и логики взаимодействия с SDK Home APIs.
- Home APIs SDK: Предоставляемый Google Home APIs SDK работает с сервисом Home APIs в GMSCore для управления устройствами умного дома. Разработчики создают приложения, работающие с Home APIs, путем включения их в состав Home APIs SDK.
- GMSCore на Android: GMSCore, также известный как Google Play Services, — это платформа Google, предоставляющая основные системные сервисы, обеспечивающие ключевую функциональность на всех сертифицированных устройствах Android. Модуль Home в Google Play Services содержит сервисы, взаимодействующие с API Home.
Настройте Home SDK
Чтобы получить последнюю версию SDK, выполните действия, описанные в разделе «Настройка SDK» .
Скачайте пробную версию приложения.
Исходный код демонстрационного приложения доступен на GitHub. В этом практическом занятии используются примеры из ветки codelab-branch-1 демонстрационного приложения.
Перейдите в папку, где вы хотите сохранить проект, и клонируйте ветку codelab-branch-1 :
$ git clone -b codelab-branch-1 https://github.com/google-home/google-home-api-sample-app-android.git
Создайте демонстрационное приложение
Выполните шаги 1-5 в разделе «Создание приложения» .

Когда приложение успешно запустится на вашем телефоне, вы увидите главную страницу демонстрационного приложения. Однако вы не сможете войти в систему, пока не настроите аутентификацию OAuth и не реализуете недостающие компоненты с помощью API разрешений.
3. Настройка аутентификации
API Home используют OAuth 2.0 для предоставления доступа к устройствам в структуре. OAuth позволяет пользователю предоставлять разрешения приложению или сервису без необходимости раскрывать свои учетные данные для входа.
Следуйте инструкциям в разделе «Настройка согласия OAuth» , чтобы настроить экран согласия. Обязательно создайте хотя бы одну тестовую учетную запись.
Затем следуйте инструкциям в разделе «Настройка учетных данных OAuth» , чтобы создать учетные данные для приложения.
4. Инициализация и обработка прав доступа
В этом разделе вы узнаете, как инициализировать SDK и управлять правами доступа пользователей, заполнив недостающие элементы с помощью API разрешений.
Определите поддерживаемые типы и характеристики.
При разработке приложения необходимо явно указать, какие типы устройств и характеристики оно будет поддерживать. В примере приложения это делается путем определения статических списков в сопутствующем объекте в HomeApp.kt , на которые затем можно ссылаться по мере необходимости во всем приложении:
companion object {
// List of supported device types by this app:
val supportedTypes: List<DeviceTypeFactory<out DeviceType>> = listOf(
OnOffLightDevice,
DimmableLightDevice,
// ...
)
// List of supported device traits by this app:
val supportedTraits: List<TraitFactory<out Trait>> = listOf(
OnOff,
LevelControl,
// ...
)
}
См. раздел «Поддерживаемые типы устройств и индекс характеристик» на Android , чтобы увидеть все поддерживаемые типы устройств и характеристики.
Раскомментируйте шаги 4.1.1 и 4.1.2 в исходном файле HomeApp.kt , чтобы активировать исходный код, запрашивающий разрешение.
companion object {
// List of supported device types by this app:
val supportedTypes: List<DeviceTypeFactory<out DeviceType>> = listOf(
// TODO: 4.1.1 - Non-registered device types will be unsupported
// ContactSensorDevice,
// ColorTemperatureLightDevice,
// DimmableLightDevice,
// ExtendedColorLightDevice,
// GenericSwitchDevice,
// GoogleDisplayDevice,
// GoogleTVDevice,
// OccupancySensorDevice,
// OnOffLightDevice,
// OnOffLightSwitchDevice,
// OnOffPluginUnitDevice,
// OnOffSensorDevice,
// RootNodeDevice,
// SpeakerDevice,
// ThermostatDevice,
)
// List of supported device traits by this app:
val supportedTraits: List<TraitFactory<out Trait>> = listOf(
// TODO: 4.1.2 - Non-registered traits will be unsupported
// AreaAttendanceState,
// AreaPresenceState,
// Assistant,
// AssistantBroadcast,
// AssistantFulfillment,
// BasicInformation,
// BooleanState,
// OccupancySensing,
// OnOff,
// Notification,
// LevelControl,
// TemperatureControl,
// TemperatureMeasurement,
// Thermostat,
// Time,
// Volume,
)
}
Инициализируйте объект HomeClient.
Все приложения, использующие API Home, инициализируют объект HomeClient , который является основным интерфейсом для взаимодействия с API. Мы подготавливаем этот объект в инициализаторе класса HomeApp ( HomeApp.kt ).
// Registry to record device types and traits used in this app:
val registry = FactoryRegistry(
types = supportedTypes,
traits = supportedTraits
)
// Configuration options for the HomeClient:
val config = HomeConfig(
coroutineContext = Dispatchers.IO,
factoryRegistry = registry
)
// Initialize the HomeClient, which is the primary object to use all Home APIs:
homeClient = Home.getClient(context = context, homeConfig = config)
Сначала мы создаём FactoryRegistry используя поддерживаемые типы и характеристики, которые мы определили ранее. Затем, используя этот реестр, мы инициализируем HomeConfig , который содержит конфигурацию, необходимую для работы API. Далее мы используем вызов Home.getClient(...) для получения экземпляра HomeClient .
Взаимодействие с API Home будет осуществляться исключительно через объект HomeClient .
Используйте API разрешений
Аутентификация пользователей для API Home осуществляется через API разрешений. Исходный файл PermissionsManager.kt в демонстрационном приложении содержит код для аутентификации пользователей. Раскомментируйте содержимое функций checkPermissions(...) и requestPermissions(...) , чтобы включить разрешения для демонстрационного приложения.
Регистрация:
homeClient.registerActivityResultCallerForPermissions(activity)
Запуск:
try {
val result: PermissionsResult
result = homeClient.requestPermissions(forceLaunch = true)
when (result.status) {
PermissionsResultStatus.SUCCESS -> // Success Case
PermissionsResultStatus.CANCELLED -> // User Cancelled
PermissionsResultStatus.ERROR -> // Some Error
else -> // Unsupported Case
}
}
catch (e: HomeException) { ... }
Проверка:
try {
val state: PermissionsState
state = homeClient.hasPermissions().first { state ->
state != PermissionsState.PERMISSIONS_STATE_UNINITIALIZED
}
when (state) {
PermissionsState.GRANTED -> // Signed In
PermissionsState.NOT_GRANTED -> // Not Signed In
PermissionsState.PERMISSIONS_STATE_UNAVAILABLE -> // ...
PermissionsState.PERMISSIONS_STATE_UNINITIALIZED -> // ...
else -> // Unsupported case
}
}
catch (e: HomeException) { ... }
Подписка:
homeClient.hasPermissions().collect( { state ->
// Track the changes on state
} )
Раскомментируйте шаг 4.3.1 в PermissionsManager.kt , чтобы включить код, запрашивающий разрешения:
fun requestPermissions() {
scope.launch {
try {
// TODO: 4.3.1 - Request the permissions from the Permissions API
// // Request permissions from the Permissions API and record the result:
// val result: PermissionsResult = client.requestPermissions(forceLaunch = true)
// // Adjust the sign-in status according to permission result:
// if (result.status == PermissionsResultStatus.SUCCESS)
// isSignedIn.emit(true)
// // Report the permission result:
// reportPermissionResult(result)
}
catch (e: HomeException) { MainActivity.showError(this, e.message.toString()) }
}
}
Теперь запустите приложение на своем телефоне, следуя инструкциям и предоставив необходимые разрешения. Вы должны увидеть следующий процесс:





Сообщение "Загрузка" никогда не исчезает, но это потому, что мы еще не реализовали код, который считывает структуру и устройства. Мы сделаем это в следующем разделе.
5. Разберитесь в модели данных.
В API Home модель данных состоит из:
-
Structureпредставляет собой дом, включающий комнаты и бытовую технику. -
Roomявляется частью конструкции и содержит в себе оборудование. - Устройства (обозначаемые как
HomeDevice) могут быть привязаны к зданию (или дому) или к комнате в этом здании. - Устройства состоят из одного или нескольких экземпляров
DeviceType. -
DeviceTypeсостоит из экземпляровTrait. -
Traitсостоит из экземпляровAttribute(для чтения/записи), экземпляровCommand(для управления атрибутами) и экземпляровEvent(для чтения или подписки на записи о прошлых изменениях). - Экземпляры
Automationявляются частью структуры и используют метаданные дома и устройства для автоматизации задач в доме.

В этом разделе вы узнаете, как разработать исходный код, демонстрирующий использование API структуры для анализа и отображения структур вашего дома, комнат, устройств и так далее.
Прочитайте структуры
Архитектура Home API основана на Kotlin Flows для потоковой передачи объектов модели данных (например, Structure , HomeDevice и т. д.). Разработчики подписываются на Flow , чтобы получить все объекты, содержащиеся в объекте (например, Structure , Room и т. д.).
Чтобы получить все структуры, вызовите функцию structures() , которая возвращает поток структур. Затем вызовите функцию list для этого потока, чтобы получить все структуры, принадлежащие пользователю.
// Get the a snapshot of all structures from the current homeClient
val allStructures : Set<Structure> =
homeClient.structures() // HomeObjectsFlow<Structure>
.list() // Set<Structure>
В руководстве по архитектуре приложений настоятельно рекомендуется использовать современный подход реактивного программирования для улучшения потока данных и управления состоянием приложения.
Вот как в примере приложения реализован реактивный стиль кодирования:
- Модели представления (например,
StructureViewModelиDeviceViewModel, выступающие в качестве держателей состояния) подписываются на потоки данных из SDK Home API, чтобы получать изменения значений и поддерживать актуальность состояний. - Представления (например,
StructureViewиDeviceView) подписываются на модели представлений, чтобы получать состояния и отображать пользовательский интерфейс, отражающий эти изменения. - Когда пользователь нажимает кнопку на представлении (например, кнопку «Вкл.» на световом устройстве), события запускают функции модели представления, которые вызывают соответствующие функции API Home (например, команду «
On» трейтаOnOff).
На шаге 5.1.1 в HomeAppViewModel.kt мы подписываемся на события изменения структуры, вызывая функцию collect() . Раскомментируйте раздел, который обрабатывает structureSet , возвращаемый ответом от Structures API и передаваемый в StateFlow StructureViewModel's . Это позволит приложению отслеживать изменения состояния структуры:
private suspend fun subscribeToStructures() {
// TODO: 5.1.1 - Subscribe the structure data changes
// // Subscribe to structures returned by the Structures API:
// homeApp.homeClient.structures().collect { structureSet ->
// val structureVMList: MutableList<StructureViewModel> = mutableListOf()
// // Store structures in container ViewModels:
// for (structure in structureSet) {
// structureVMList.add(StructureViewModel(structure))
// }
// // Store the ViewModels:
// structureVMs.emit(structureVMList)
//
// // If a structure isn't selected yet, select the first structure from the list:
// if (selectedStructureVM.value == null && structureVMList.isNotEmpty())
// selectedStructureVM.emit(structureVMList.first())
//
// }
}
В DevicesView.kt приложение подписывается на StateFlow StructureViewModel'sStateFlow, который запускает перекомпозицию пользовательского интерфейса при изменении данных структуры. Раскомментируйте исходный код на шаге 5.1.2, чтобы отобразить список структур в виде выпадающего меню:
val structureVMs: List<StructureViewModel> = homeAppVM.structureVMs.collectAsState().value
...
DropdownMenu(expanded = expanded, onDismissRequest = { expanded = false }) {
// TODO: 5.1.2 - Show list of structures in DropdownMenu
// for (structure in structureVMs) {
// DropdownMenuItem(
// text = { Text(structure.name) },
// onClick = {
// scope.launch { homeAppVM.selectedStructureVM.emit(structure) }
// expanded = false
// }
// )
// }
}
...
Запустите приложение ещё раз. При нажатии на стрелку вы должны увидеть меню:

Разберите структуру
Следующий шаг — обойти домашние объекты в структуре. Извлечь комнаты из структуры:
val rooms: Set<Room>
rooms = structure.rooms().list()
Затем вы можете пройтись по комнатам, чтобы забрать устройства:
val devices: Set<HomeDevice>
devices = room.devices().list()
Важно: В модели данных Home API структура может содержать устройства, не привязанные к комнате , поэтому обязательно учитывайте в своем приложении и устройства без привязки к комнате.
val devicesWithoutRooms: MutableSet<HomeDevice> = mutableSetOf()
for (device in structure.devices().list())
if (device.roomId == null)
devicesWithoutRooms.add(device)
В существующем примере кода мы снова подписываемся на поток для получения актуального списка комнат и устройств. Проверьте код на шагах 5.2.1 и 5.2.2 в исходном файле StructureViewModel.kt и раскомментируйте его, чтобы включить подписку на данные о комнатах:
val roomVMs : MutableStateFlow<List<RoomViewModel>>
val deviceVMs : MutableStateFlow<List<DeviceViewModel>>
val deviceVMsWithoutRooms : MutableStateFlow<List<DeviceViewModel>>
private suspend fun subscribeToRooms() {
// TODO: 5.2.1 - Subscribe the room data changes
// // Subscribe to changes on rooms:
// structure.rooms().collect { roomSet ->
// val roomVMs = mutableListOf<RoomViewModel>()
// // Store rooms in container ViewModels:
// for (room in roomSet) {
// roomVMs.add(RoomViewModel(room))
// }
// // Store the ViewModels:
// this.roomVMs.emit(roomVMs)
// }
}
private suspend fun subscribeToDevices() {
// TODO: 5.2.2 - Subscribe the device data changes in a structure
// // Subscribe to changes on devices:
// structure.devices().collect { deviceSet ->
// val deviceVMs = mutableListOf<DeviceViewModel>()
// val deviceWithoutRoomVMs = mutableListOf<DeviceViewModel>()
// // Store devices in container ViewModels:
// for (device in deviceSet) {
// val deviceVM = DeviceViewModel(device)
// deviceVMs.add(deviceVM)
// // For any device that's not in a room, additionally keep track of a separate list:
// if (device.roomId == null)
// deviceWithoutRoomVMs.add(deviceVM)
// }
// // Store the ViewModels:
// this.deviceVMs.emit(deviceVMs)
// deviceVMsWithoutRooms.emit(deviceWithoutRoomVMs)
// }
}
Раскомментируйте шаги 5.2.3 и 5.2.4 в исходном файле DevicesView.kt , чтобы отобразить список комнат в виде меню:
val selectedRoomVMs: List<RoomViewModel> =
selectedStructureVM.roomVMs.collectAsState().value
...
for (roomVM in selectedRoomVMs) {
// TODO: 5.2.3 - Render the list of rooms
// RoomListItem(roomVM)
// TODO: 5.2.4 - Render the list of devices in a room
// val deviceVMsInRoom: List<DeviceViewModel> = roomVM.deviceVMs.collectAsState().value
//
// for (deviceVM in deviceVMsInRoom) {
// DeviceListItem(deviceVM, homeAppVM)
// }
}
Теперь, когда у вас есть эти устройства, мы научимся с ними работать.

6. Работа с устройствами
API Home используют объект HomeDevice для получения информации об устройстве и его возможностях. Разработчики могут подписываться на атрибуты устройства и использовать их для представления устройств умного дома в своих приложениях.
Чтение состояний устройства
Объект HomeDevice предоставляет набор статических значений, таких как имя устройства или состояние подключения. Разработчик может получить к ним доступ вскоре после получения устройства из API:
val id: String = device.id.id
val name: String = device.name
val connectivity: ConnectivityState =
device.sourceConnectivity.connectivityState
Для получения информации о возможностях устройства необходимо получить типы и характеристики из HomeDevice . Для этого можно подписаться на поток типов устройств следующим образом и получить характеристики из типов устройств:
device.types().collect { typeSet ->
var primaryType : DeviceType = UnknownDeviceType()
for (typeInSet in typeSet)
if (typeInSet.metadata.isPrimaryType)
primaryType = typeInSet
val traits: List<Trait> = mutableListOf()
for (trait in primaryType.traits())
if (trait.factory in myTraits)
traits.add(trait)
for (trait in traits)
parseTrait(trait, primaryType)
}
Каждое устройство содержит набор поддерживаемых DeviceType (встроенных возможностей), которые можно получить с помощью device.types() . Эти типы устройств содержат характеристики, которые можно получить с помощью type.traits() . Каждое устройство помечает один из своих типов как основной тип (который можно проверить с помощью type.metadata.isPrimaryType ), который следует отобразить в вашем приложении. Для обеспечения полноценного пользовательского опыта мы рекомендуем пройтись по всем возвращаемым типам и интегрировать все доступные вам характеристики.
Получив свойство, вы можете проанализировать его, используя функцию, подобную следующей, для интерпретации значений:
fun <T : Trait?> parseTrait(trait : T, type: DeviceType) {
val status : String = when (trait) {
is OnOff -> { if (trait.onOff) "On" else "Off" }
is LevelControl -> { trait.currentLevel.toString() }
is BooleanState -> {
when (type.factory) {
ContactSensorDevice -> {
if (trait.stateValue) "Closed"
else "Open"
}
else -> ...
}
}
else -> ...
}
}
Обратите внимание, что значение параметра может варьироваться в зависимости от типа устройства, использующего его (см. BooleanState в предыдущем примере), поэтому необходимо учитывать контекст каждого типа устройства, чтобы понять, что на самом деле означают его параметры.
Раскомментируйте шаги 6.1.1 и 6.1.2 в исходном файле DeviceViewModel.kt , чтобы получить состояния:
private suspend fun subscribeToType() {
// Subscribe to changes on device type, and the traits/attributes within:
device.types().collect { typeSet ->
// Container for the primary type for this device:
var primaryType : DeviceType = UnknownDeviceType()
...
// TODO: 6.1.1 - Determine the primary type for this device
// // Among all the types returned for this device, find the primary one:
// for (typeInSet in typeSet)
// if (typeInSet.metadata.isPrimaryType)
// primaryType = typeInSet
//
// // Optional: For devices with a single type that did not define a primary:
// if (primaryType is UnknownDeviceType && typeSet.size == 1)
// primaryType = typeSet.first()
// Container for list of supported traits present on the primary device type:
val supportedTraits: List<Trait> = getSupportedTraits(primaryType.traits())
...
}
fun getSupportedTraits(traits: Set<Trait>) : List<Trait> {
val supportedTraits: MutableList<Trait> = mutableListOf()
// TODO: 6.1.2 - Get only the supported traits for this device
// for (trait in traits)
// if (trait.factory in HomeApp.supportedTraits)
// supportedTraits.add(trait)
return supportedTraits
}
Раскомментируйте шаг 6.1.3 в DeviceView.kt , чтобы отобразить свойство OnOff, включая его имя и статус, в виде String :
Box (Modifier.padding(horizontal = 24.dp, vertical = 8.dp)) {
when (trait) {
is OnOff -> {
// TODO: 6.1.3 - Render controls based on the trait type
// Column (Modifier.fillMaxWidth()) {
// Text(trait.factory.toString(), fontSize = 20.sp)
// Text(DeviceViewModel.getTraitStatus(trait, type), fontSize = 16.sp)
// }
...
}
is LevelControl -> {
...
}
is BooleanState -> {
...
}
is OccupancySensing -> {
...
}
...
}
Если вы запустите приложение сейчас с поддерживаемыми типами устройств (например, с устройством Light), оно должно отобразить актуальное состояние всех устройств.

Выдавайте команды устройству
Для отправки команд устройствам API Home предоставляют удобные функции для объектов Trait, такие как trait.on() или trait.moveToLevel(...) :
fun <T : Trait?> issueCommand(trait : T) {
when (trait) {
is OnOff -> {
// trait.on()
// trait.off()
}
is LevelControl -> {
// trait.moveToLevel(...)
// trait.moveToLevelWithOnOff(...)
}
}
}
Совет: После определения типа характеристики воспользуйтесь функцией автозаполнения в Android Studio, чтобы увидеть, какие действия доступны для взаимодействия с этой характеристикой.
Раскомментируйте шаг 6.2.1 в DeviceView.kt , чтобы добавить функциональные элементы управления в приложение:
Box (Modifier.padding(horizontal = 24.dp, vertical = 8.dp)) {
when (trait) {
is OnOff -> {
....
// TODO: 6.2.1 - Render controls based on the trait type
// Switch (checked = (trait.onOff == true), modifier = Modifier.align(Alignment.CenterEnd),
// onCheckedChange = { state ->
// scope.launch { if (state) trait.on() else trait.off() }
// },
// enabled = isConnected
// )
}
Если вы запустите приложение сейчас, оно должно позволить вам управлять реальными физическими устройствами.
Если вы нажмете на кнопку включения/выключения на лампочке, устройство должно включиться.

Для получения дополнительной информации о том, как управлять устройствами, см. раздел «Управление устройствами на Android» .
7. Ввод в эксплуатацию устройств
API для ввода устройств в эксплуатацию позволяет разработчикам добавлять устройства в экосистему Google Home и делать их доступными для управления с помощью API Home. Поддерживаются только устройства Matter. В этом разделе мы рассмотрим, как включить ввод устройств в эксплуатацию в ваших приложениях.
Перед началом работы над этим разделом убедитесь, что выполнены следующие предварительные условия:
- В приложение Google Home добавлен Google Hub, поддерживающий Matter и расположенный в той же сети, что и ваш телефон Android.
- Вы создали проект разработчика в консоли разработчика Google Home с VID
0xFFF1и PID0x8000.
Если у вас есть физическое устройство Matter с QR-кодом для ввода в эксплуатацию, вы можете перейти к разделу «Включение API ввода в эксплуатацию ». В противном случае, перейдите к следующему разделу, где мы обсудим, как использовать приложение Matter Virtual Device (MVD) для создания виртуальных устройств, подлежащих вводу в эксплуатацию.
Дополнительно: Подготовьте устройство, подлежащее сдаче в эксплуатацию.
Простейший способ подготовить устройство Matter к вводу в эксплуатацию — использовать эмулированное устройство, предоставляемое приложением Matter Virtual Device (MVD).
После установки MVD и настройки брандмауэра запустите MVD:

Создайте устройство OnOff. Обратите внимание, что оно еще не введено в эксплуатацию — вы сделаете это позже в ходе этого практического занятия.

Включите API ввода в эксплуатацию.
API для ввода в эксплуатацию работает вне Activity приложения, поэтому ввод в эксплуатацию должен обрабатываться иначе, чем другие API Home. Для подготовки вашего приложения к вводу в эксплуатацию вам понадобятся две переменные.
Одна из переменных — ActivityResultLauncher , которая используется для отправки намерения ввода в эксплуатацию и управления обратным вызовом результата. Другая переменная — CommissioningResult , которая представляет собой объект, используемый для хранения результата ввода в эксплуатацию. См. следующий пример настройки ввода в эксплуатацию:
var launcher: ActivityResultLauncher<IntentSenderRequest>
lateinit var commissioningResult: CommissioningResult?
launcher = activity.registerForActivityResult(StartIntentSenderForResult()) { result ->
try {
commissioningResult = CommissioningResult.fromIntentSenderResult(
result.resultCode, result.data)
} catch (exception: ApiException) {
// Catch any issues
}
}
После настройки процесса ввода в эксплуатацию вам потребуется создать намерение ввода в эксплуатацию и запустить его с помощью средства запуска, созданного в предыдущем примере. Мы рекомендуем разместить намерение и средство запуска в отдельной функции, как показано ниже. Отдельная функция может быть привязана к элементу пользовательского интерфейса (например, к кнопке «+Добавить устройство» ) и вызываться в зависимости от запроса пользователя:
fun requestCommissioning() {
// Retrieve the onboarding payload used when commissioning devices:
val payload = activity.intent?.getStringExtra(Matter.EXTRA_ONBOARDING_PAYLOAD)
scope.launch {
// Create a commissioning request to store the device in Google's Fabric:
val request = CommissioningRequest.builder()
.setStoreToGoogleFabric(true)
.setOnboardingPayload(payload)
.build()
// Initialize client and sender for commissioning intent:
val client: CommissioningClient = Matter.getCommissioningClient(context)
val sender: IntentSender = client.commissionDevice(request).await()
// Launch the commissioning intent on the launcher:
launcher.launch(IntentSenderRequest.Builder(sender).build())
}
}
Раскомментируйте шаг 7.1.1 в CommissioningManager.kt , чтобы включить функцию ввода в эксплуатацию и обеспечить работу кнопки «+Добавить устройство» в демонстрационном приложении.
// Called by +Add Device button in DeviceView.kt
fun requestCommissioning() {
// Retrieve the onboarding payload used when commissioning devices:
val payload = activity.intent?.getStringExtra(Matter.EXTRA_ONBOARDING_PAYLOAD)
// TODO: 7.1.1 - Launch the commissioning intent
// scope.launch {
// // Create a commissioning request to store the device in Google's Fabric:
// val request = CommissioningRequest.builder()
// .setStoreToGoogleFabric(true)
// .setOnboardingPayload(payload)
// .build()
// // Initialize client and sender for commissioning intent:
// val client: CommissioningClient = Matter.getCommissioningClient(context)
// val sender: IntentSender = client.commissionDevice(request).await()
// // Launch the commissioning intent on the launcher:
// launcher.launch(IntentSenderRequest.Builder(sender).build())
// }
}
Запуск этой функции должен запустить процесс ввода в эксплуатацию, в результате чего отобразится экран, похожий на следующий снимок экрана:

Разберитесь в процессе ввода в эксплуатацию.
Процесс ввода в эксплуатацию включает в себя набор экранов, которые помогают пользователю добавить устройство в свою учетную запись Google:





Пользователей встретит сканер QR-кодов, который они смогут использовать для сканирования QR-кодов с устройств Matter. Затем процесс будет включать отображение пользовательского соглашения, обнаружение и ввод в эксплуатацию устройства, а также присвоение ему имени. После завершения процесса фокус вернется к приложению, и результат ввода в эксплуатацию будет передан в функцию обратного вызова, разработанную нами в предыдущем разделе.
Одним из преимуществ API для ввода устройств в эксплуатацию является то, что обработка пользовательского интерфейса осуществляется SDK, поэтому разработчики могут очень быстро приступить к работе. Это также обеспечивает пользователям единообразный опыт при добавлении устройств в различные приложения.
Чтобы узнать больше об API ввода в эксплуатацию, посетите страницу «API ввода в эксплуатацию на Android» .
8. Поздравляем!
Поздравляем! Вы успешно создали Android-приложение, используя API Google Home. В ходе этого практического занятия вы изучили API разрешений, устройств, структур и ввода в эксплуатацию. В следующем практическом занятии, «Создание сложных автоматизаций с использованием API Home на Android» , мы изучим API автоматизации и обнаружения и завершим создание приложения.
Мы надеемся, что вам понравится создавать приложения, которые позволяют творчески управлять устройствами в экосистеме Google Home.
Следующие шаги
- Перейдите к следующему этапу изучения API Home на Android, выполнив второе практическое задание из этой серии: Создание сложных автоматизаций с использованием API Home на Android .
- Вы можете связаться с нами с любыми рекомендациями или сообщить о любых проблемах через систему отслеживания проблем , в разделе поддержки умного дома.