Создайте мобильное приложение с помощью Home API на Android. Создайте мобильное приложение с помощью Home API на Android.

1. Прежде чем начать

API Google Home предоставляют набор библиотек для разработчиков Android, чтобы они могли подключиться к экосистеме Google Home. С помощью этих новых API разработчики могут создавать приложения, которые легко вводят в эксплуатацию и контролируют устройства умного дома.

Google предоставляет Android Sample App для разработчиков, которые хотят получить доступ к рабочему примеру с использованием API Google Home. Эта кодовая лаборатория основана на ветви Sample App, которая проведет вас через то, как использовать API Permissions, Commissioning, Device и Structure.

Предпосылки

Чему вы научитесь

  • Как создать приложение для Android с использованием API Google Home с использованием лучших практик.
  • Как использовать API устройств и структур для представления и управления умным домом.
  • Как использовать Commissioning API для добавления устройств в экосистему Google Home.

Дополнительно: обустройте свой дом

Перед использованием API Google Home вам необходимо настроить дом в вашем аккаунте Google с помощью приложения Google Home и добавить несколько устройств. В этом разделе обсуждается, как это сделать с помощью Google Home Playground , который предоставляет виртуальные интеллектуальные домашние устройства.

Откройте home-playground.withgoogle.com в своем веб-браузере, войдите в свою учетную запись Google и посмотрите, появятся ли следующие эмулируемые устройства:

  • розетка1: вилка вкл/выкл
  • light2: Регулируемый свет
  • light3: Вкл/Выкл свет
  • ac3: Кондиционер
  • blinds4: Оконное покрытие
  • washer5: Умная стиральная машина

914d23a42b72df8f.png

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

e9ec257b0d9b1ed2.png29fd7416e274d216.pngd974573af0611fd8.png

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

13108a3a15440151.png8791a6d33748f7c8.png

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

2b021202e6fd1750.png

Поддерживаемые устройства из списка теперь доступны для использования с API Google Home.

2. Настройте свой проект

Следующая диаграмма иллюстрирует архитектуру приложения Home API:

Архитектура API Home для приложения Android

  • Код приложения: основной код, над которым работают разработчики для создания пользовательского интерфейса приложения и логики взаимодействия с SDK Home API.
  • Home APIs SDK: Home APIs SDK, предоставляемый Google, работает с Home APIs Service в GMSCore для управления умными домашними устройствами. Разработчики создают приложения, которые работают с Home APIs, объединяя их с Home APIs SDK.
  • GMSCore на Android: GMSCore, также известный как Google Play services, — это платформа Google, которая предоставляет основные системные службы, обеспечивая ключевые функции на всех сертифицированных устройствах Android. Домашний модуль служб Google Play содержит службы, которые взаимодействуют с API Home.

Настройте Home SDK

Чтобы получить последнюю версию SDK, следуйте инструкциям в разделе Настройка SDK .

Получить образец приложения

Исходный код для Sample App доступен на GitHub. Эта codelab использует примеры из ветки codelab-branch-1 Sample App.

Перейдите туда, где вы хотите сохранить проект, и клонируйте ветку codelab-branch-1 :

$ git clone -b codelab-branch-1 https://github.com/google-home/google-home-api-sample-app-android.git

Создайте пример приложения

Выполните шаги 1–5 в разделе «Создание приложения» .

32f2b3c0cd80fcf1.png

Когда приложение успешно запустится на вашем телефоне, вы увидите главную страницу Sample App. Но вы не сможете войти, пока не настроите аутентификацию OAuth и не реализуете недостающие части с помощью API Permission.

3. Настройте аутентификацию

API Home используют OAuth 2.0 для предоставления доступа к устройствам в структуре. OAuth позволяет пользователю предоставлять разрешение приложению или службе без необходимости раскрывать свои учетные данные для входа.

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

Затем следуйте инструкциям в разделе Настройка учетных данных OAuth , чтобы создать учетные данные для приложения.

4. Инициализация и обработка разрешений

В этом разделе вы узнаете, как инициализировать SDK и управлять разрешениями пользователей, заполнив недостающие части с помощью API разрешений.

Определите поддерживаемые типы и характеристики

При разработке приложения вам необходимо явно указать, какие типы устройств и характеристики приложение будет поддерживать. В Sample App мы делаем это, определяя статические списки в объекте-компаньоне в 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

Все приложения, использующие Home API, инициализируют объект 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 Permissions. Исходный файл PermissionsManager.kt приложения Sample App содержит код для аутентификации пользователя. Раскомментируйте содержимое функций checkPermissions(...) и requestPermissions(...) , чтобы включить разрешения для приложения Sample App.

Регистрация:

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

Теперь запустите приложение на своем телефоне, следуя инструкциям и разрешите разрешения. Вы должны увидеть следующий поток:

c263dcee4e945bf1.pngf518cfd1fdb8a9d8.png59937372f28c472f.png383073ae57d2ced4.png89f774a2ba6898ae.png

Сообщение "Загрузка" никогда не исчезает, но это потому, что мы не реализовали код, который считывает структуру и устройства. Мы сделаем это в следующем разделе.

5. Понять модель данных

В API Home модель данных состоит из:

  • Structure представляет собой дом, содержащий комнаты и устройства.
  • Room является частью конструкции и содержит устройства.
  • Устройства (определяемые как HomeDevice ) могут быть назначены строению (или дому) или комнате в строении.
  • Устройства состоят из одного или нескольких экземпляров DeviceType .
  • DeviceType состоит из экземпляров Trait .
  • Trait состоит из экземпляров Attribute (для чтения/записи), экземпляров Command (для управления атрибутами) и экземпляров Event (для чтения или подписки на записи прошлых изменений).
  • Экземпляры Automation являются частью структуры и используют метаданные и устройства дома для автоматизации задач в доме.

76d35b44d5a8035e.png

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

Прочитать структуры

Дизайн API Home основан на 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 , возвращаемому ответом API Structures и доставляемому в 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 приложение подписывается на 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
//          }
//      )
//  }
}
...

Запустите приложение еще раз. Вы должны увидеть меню, когда нажмете на стрелку:

f1fc2be1cb6436b6.png

Анализ структуры

Следующий шаг — пройтись по объектам дома в структуре. Извлечь комнаты из структуры:

val rooms: Set<Room>
rooms = structure.rooms().list()

Затем вы можете перемещаться по комнатам, чтобы извлечь устройства:

val devices: Set<HomeDevice>
devices = room.devices().list()

Важно: в модели данных API Home структура может содержать устройства, которые не назначены ни одной комнате , поэтому обязательно включите в свое приложение также и устройства без комнат:

val devicesWithoutRooms: MutableSet<HomeDevice> = mutableSetOf()

for (device in structure.devices().list())
if (!device.isInRoom)
  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.isInRoom)
//               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)
//   }
}

Теперь, когда у вас есть устройства, мы научимся с ними работать.

e715ddda50e04839.png

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), оно должно отображать актуальные состояния для всех устройств.

1bd8b3b2796c4c7a.png

Выдача команд устройству

Для выдачи команд устройствам 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
//   )
}

Если вы запустите приложение сейчас, оно позволит вам управлять реальными физическими устройствами.

Если вы нажмете кнопку «Вкл/Выкл» на лампочке, устройство должно включиться.

c8ed3ecf5031546e.png

Дополнительную информацию об управлении устройствами см. в разделе Управление устройствами на Android .

7. Комиссионные устройства

Commissioning API позволяет разработчикам добавлять устройства в экосистему Google Home и делать их доступными для управления с помощью Home API. Поддерживаются только устройства Matter. В этом разделе мы рассмотрим, как можно включить комиссию устройств в своих приложениях.

Прежде чем приступить к работе с этим разделом, убедитесь, что выполнены следующие предварительные условия:

Если у вас есть физическое устройство Matter с QR-кодом для ввода в эксплуатацию, вы можете перейти к разделу Включить API ввода в эксплуатацию . В противном случае перейдите к следующему разделу, где мы обсудим, как можно использовать приложение Matter Virtual Device (MVD) для создания виртуальных устройств с возможностью ввода в эксплуатацию.

Необязательно: Подготовьте устройство, подлежащее комиссии

Самый простой способ подготовить комиссионное устройство Matter — использовать эмулированное устройство, предоставляемое приложением Matter Virtual Device (MVD).

После установки MVD и настройки брандмауэра запустите MVD:

b20283893073ac1b.png

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

5f4855b808312898.png

Включить API ввода в эксплуатацию

Commissioning API работает вне Activity приложения, поэтому Commissioning необходимо обрабатывать иначе, чем другие Home API. Чтобы подготовить приложение к Commissioning, вам нужны две переменные.

Одна переменная — 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())
// }
}

Запуск этой функции должен запустить процесс ввода в эксплуатацию, который должен отобразить экран, похожий на следующий снимок экрана:

baae45588f460664.png

Понять процесс ввода в эксплуатацию

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

2fb0404820d4a035.png3cbfa8ff9cfd5ee4.pnga177c197ee7a67bf.png3fdef24672c77c0.pngdec8e599f9aa119.png

Пользователям будет представлен сканер QR-кодов, который они смогут использовать для сканирования QR-кодов с устройств Matter. Затем поток пройдет через отображение Пользовательского соглашения, обнаружение и ввод в эксплуатацию устройства, а также присвоение имени устройству. После завершения потока он снова переключится на приложение и передаст результат ввода в эксплуатацию в функцию обратного вызова, которую мы разработали в предыдущем разделе.

Одним из преимуществ Commissioning API является то, что поток UX обрабатывается SDK, поэтому разработчики могут приступить к работе очень быстро. Это также дает пользователям единообразный опыт при добавлении устройств в разных приложениях.

Чтобы узнать больше об API ввода в эксплуатацию, посетите страницу API ввода в эксплуатацию на Android .

8. Поздравляю!

Поздравляем! Вы успешно создали приложение Android с использованием API Google Home. В ходе этой практической работы вы изучили разрешения, устройства, структуры и API ввода в эксплуатацию. В следующей практической работе « Создание расширенных автоматизаций с использованием API Home на Android» мы изучим API автоматизации и обнаружения и завершим приложение.

Мы надеемся, что вам понравится создавать приложения, которые творчески управляют устройствами в экосистеме Google Home.

Следующие шаги