Android의 Structure API

Structure API는 Android용 Home API를 통해 액세스할 수 있습니다. 다음 패키지를 앱으로 가져옵니다.

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

오류 처리

Home API의 모든 메서드는 HomeException를 발생시킬 수 있으므로 try-catch 블록을 사용하여 모든 호출에서 HomeException를 포착하는 것이 좋습니다.

HomeException를 처리할 때 error.code error.message 필드를 확인하여 무엇이 잘못되었는지 알아봅니다. 하위 오류 코드도 있을 수 있으므로 getSubErrorCodes() 메서드를 호출하여 결과를 확인하세요.

처리되지 않은 예외가 있으면 앱이 비정상 종료됩니다.

자세한 내용은 오류 처리를 참고하세요.

샘플 호출

구조 목록 가져오기

초기화되면 structures() 호출은 액세스할 수 있는 구조의 흐름을 반환합니다.

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

structures() API는 유효한 구조 목록을 즉시 반환하지 않을 수 있는 흐름입니다. 앱이 반응형이고 UI를 구동하기 위해 해당 흐름을 구독하는 경우 결국 유효한 구조 목록이 반환됩니다. 사용자의 휴대전화 연결이 끊어지거나 사용자가 앱에 대한 권한을 취소한 경우와 같이 빈 구조 목록이 반환될 수 있는 다른 상황도 있습니다. 앱에서 이러한 사례를 처리해야 합니다.

또는 반응형 프로그래밍 대신 명령형 프로그래밍이 강력하게 필요한 경우 터미널 흐름 연산자를 사용할 수 있습니다.

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

이 호출은 흐름을 통해 유효한 구조 목록이 전달되기를 기다리며, 앱에서 지정한 시간 내에 목록이 수신되지 않으면 시간이 초과됩니다.

구조 속성 가져오기

구조 목록을 사용하여 구조의 속성에 액세스할 수 있습니다.

// 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}")

이름으로 구조 찾기

구조체의 이름을 알고 있는 경우 name 속성을 사용하여 액세스할 수도 있습니다.

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

여기에서 각 구조의 속성, 방, 기기에 액세스할 수 있습니다.

여러 구조 작업

두 개 이상의 구조를 사용하려면 각 구조에 대한 별도의 참조를 가져옵니다.

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
}

회의실 목록 가져오기

구조를 사용하면 방 목록을 가져오고 방의 속성에 액세스할 수 있습니다.

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

채팅방 만들기

새 회의실을 만들려면 다음 단계를 따르세요.

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

방 삭제하기

또는 다음과 같이 채팅방을 삭제할 수 있습니다.

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

ID만으로 채팅방을 삭제할 수도 있습니다.

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

기기가 있는 방을 삭제해도 기기는 구조에 그대로 있지만 더 이상 방에 할당되지 않습니다.

기기를 다른 방으로 이동하기

구조가 있으면 해당 구조 내에서 기기를 다른 방으로 이동할 수 있습니다.

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

기기 및 방 ID만 있는 경우에도 기기를 이동할 수 있습니다.

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

방 이름 변경하기

setName() 메서드를 호출하여 방 이름을 변경합니다.

livingRoom.setName("Living Room")

이름이 유니코드 코드 포인트(문자) 제한인 60을 초과하면 잘리며 오류가 발생하지 않습니다. 개발자는 긴 이름을 처리해야 하며, 예를 들어 사용자에게 이름이 잘린다는 사실을 알릴지 여부를 결정할 수 있습니다.

Google Home 생태계에서 대부분의 기기 유형의 경우 사용자는 해당 유형의 모든 기기에 한 번에 권한을 부여할 수 있습니다. 도어락, 카메라, 초인종과 같은 민감하거나 제한된 기기 유형의 경우 사용자가 개별적으로 권한을 부여해야 합니다.

사용자가 민감하거나 제한된 기기 유형에 액세스할 수 있는 권한을 부여했는지 확인하려면 구조 수준 consentedDeviceTypes() 함수를 사용하세요.

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

자동화

구조를 통해 Automation API에 진입할 수 있습니다. Home API의 자동화에 관해 자세히 알아보려면 Android의 자동화 API 개요를 참고하세요.