Android 上的 Structure API

您可以透過 Android 版 Home API 存取 Structure 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() 呼叫會傳回您可存取的結構體 Flow:

// 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 個 Unicode 碼點 (字元) 的限制,系統會截斷名稱,且不會擲回錯誤。開發人員有責任處理長名稱,例如決定是否要通知使用者名稱會遭到截斷。

在 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 總覽」。