Interfejsy Structure API na Androidzie

Dostęp do interfejsów Structure API można uzyskać za pomocą interfejsów Home API na Androidzie. Zaimportuj te pakiety do swojej aplikacji:

import com.google.home.Home
import com.google.home.Id
import com.google.home.Structure

Obsługa błędów

Każda metoda w interfejsach Home API może zgłosić wyjątek HomeException, dlatego zalecamy używanie bloku try-catch do przechwytywania HomeException we wszystkich wywołaniach.

Podczas obsługi HomeException sprawdź pola error.code i error.message, aby dowiedzieć się, co poszło nie tak. Mogą też występować kody błędów podrzędnych as well, dlatego wywołaj metodę getSubErrorCodes() i sprawdź wynik.

Wszystkie nieobsłużone wyjątki spowodują awarię aplikacji.

Więcej informacji znajdziesz w sekcji Obsługa błędów.

Przykładowe wywołania

Pobieranie listy struktur

Po zainicjowaniu wywołanie structures() zwraca strumień struktur, do których masz dostęp:

// Get a flow of all structures accessible to the user
val allStructuresFlow: HomeObjectsFlow<Structure> = home.structures()

// Calling list() on a HomeObjectsFlow returns the first Set of elements.
val allStructures: Set<Structure> = allStructuresFlow.list()

Interfejs structures() API to strumień, który może nie zwrócić od razu prawidłowej listy struktur. Jeśli Twoja aplikacja jest reaktywna i subskrybuje ten strumień, aby sterować interfejsem, powinna w końcu otrzymać prawidłową listę struktur. Mogą też wystąpić inne sytuacje, w których zwracana jest pusta lista struktur, np. gdy telefon użytkownika utraci połączenie lub gdy użytkownik cofnie uprawnienia Twojej aplikacji. Musisz zadbać o obsługę tych przypadków w swojej aplikacji.

Jeśli zamiast programowania reaktywnego zdecydowanie preferujesz programowanie imperatywne, możesz użyć operatora strumienia terminala:

val everyStructure = withTimeout(5000) { home.structures().first { it.isNotEmpty() } }

To wywołanie czeka na prawidłową listę struktur, która ma się pojawić w strumieniu, i przekracza limit czasu, jeśli lista nie zostanie odebrana w określonym przez aplikację limicie czasu.

Pobieranie właściwości struktury

Gdy masz listę struktur, możesz uzyskać dostęp do ich właściwości:

// Get a flow on a structure. Flow emits new values on structure metadata changes: name.
val structureFlow: Flow<Structure> = home.structures().itemFlow(myStructureId)

// Get a snapshot of the structure.
val structure: Structure = structureFlow.first()

// Get structure properties
println("id ${structure.id}")
println("name ${structure.name}")

Znajdowanie struktury według nazwy

Jeśli znasz nazwę struktury, możesz też uzyskać do niej dostęp za pomocą właściwości name:

val myHome = home.structures().list().first { it.name == "My home" }

Stamtąd można uzyskać dostęp do właściwości, pomieszczeń i urządzeń każdej struktury.

Praca z wieloma strukturami

Aby używać więcej niż 1 struktury, uzyskaj osobne odniesienie do każdej z nich:

var structure1: Structure? = null
var structure2: Structure? = null

try {
  structure1 = home.structures().list().firstOrNull { it.name == "Main House" }
} catch (e: HomeException) {
  // Code for handling the exception
}
try {
  structure2 = home.structures().list().firstOrNull { it.name == "Guest Cottage" }
} catch (e: HomeException) {
  // Code for handling the exception
}

Pobieranie listy pomieszczeń

Gdy masz strukturę, możesz pobrać listę pomieszczeń i uzyskać dostęp do ich właściwości:

val allRoomsFlow: HomeObjectsFlow<Room> = structure.rooms()
val allRooms: Set<Room> = allRoomsFlow.list()
val room: Room = allRooms.first()

println("id ${room.id}")
println("name ${room.name}")

Tworzenie pomieszczenia

Aby utworzyć nowe pomieszczenie:

val testName = "Test Room Name"
val newRoom: Room = structure.createRoom(testName)

Usuwanie pomieszczenia

Możesz też usunąć pomieszczenie:

val roomToDelete = structure.rooms().list().filter { it.name == "room_id1" }.firstOrNull()
    structure.deleteRoom(roomToDelete!!)

Możesz też usunąć pomieszczenie, podając tylko jego identyfikator:

val roomToDelete1 = allRooms.filter { it.id == testRoomId }.firstOrNull()
structure.deleteRoom(roomToDelete1!!)

Jeśli usuniesz pomieszczenie z urządzeniami, urządzenia nadal będą w strukturze, ale nie będą już przypisane do pomieszczenia.

Przenoszenie urządzeń do innego pomieszczenia

Gdy masz strukturę, możesz przenieść urządzenia do innego pomieszczenia w tej strukturze:

val room2 = structure.rooms().get(Id("room_id_other_structure"))
    val device1 = structure.devices().get(Id("device_id1"))
    structure.moveDevicesToRoom(room2!!, listOf(device1!!))

Jeśli masz tylko identyfikatory urządzeń i pomieszczeń, możesz też przenieść urządzenia:

structure.moveDevicesToRoom(Id("room_id_other_structure"), listOf(Id("device_id1")))

Zmienianie nazwy pomieszczenia

Aby zmienić nazwę pomieszczenia, wywołaj metodę setName():

livingRoom.setName("Living Room")

Nazwy zostaną obcięte, jeśli przekroczą limit 60 punktów kodowych Unicode (znaków), i nie zostaną zgłoszone żadne błędy. Deweloperzy są odpowiedzialni za obsługę długich nazw i mogą na przykład zdecydować, czy chcą informować użytkowników, że nazwy zostaną obcięte.

W ekosystemie Google Home użytkownicy mogą przyznawać uprawnienia do wszystkich urządzeń danego typu naraz. W przypadku typów urządzeń, które wymagają szczególnej ochrony lub są objęte ograniczeniami, takich jak zamki, kamery czy dzwonki do drzwi, użytkownicy muszą przyznać uprawnienia do każdego z nich osobno.

Aby sprawdzić, czy użytkownik przyznał uprawnienia do dostępu do typu urządzenia, które wymaga szczególnej ochrony lub jest objęte ograniczeniami, użyj funkcji consentedDeviceTypes() na poziomie struktury:

import com.google.home.Structure
import com.google.home.DeviceType
import com.google.home.DeviceTypeFactory
import com.google.home.consentedDeviceTypes // Extension function from the SDK
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch

/**
 * Example of how an app may monitor which device types have been granted access by a user.
 */
fun monitorDeviceConsent(structure: Structure, myScope: CoroutineScope) {
    // Obtain the flow of consented device type factories
    val consentedTypesFlow: Flow<Set<DeviceTypeFactory<out DeviceType>>> =
        structure.consentedDeviceTypes()

    myScope.launch {
        consentedTypesFlow.collect { consentedSet ->
            // Check if the user has consented to share a specific restricted
            // type, such as a Doorbell or Camera.
            val hasCameraAccess = consentedSet.any {
                it.toString() == "matter.google.type.GoogleDoorbellDevice"
            }

            if (hasCameraAccess) {
                // Enable features that require camera access
            } else {
                // Inform the user or disable camera-specific features
            }
        }
    }
}

Automatyzacja

Punktem wejścia do interfejsu Automation API jest struktura. Więcej informacji o automatyzacji w interfejsach Home API znajdziesz w artykule Omówienie interfejsu Automation API na Androidzie.