Structure APIs may be accessed through the Home APIs for Android. Import these packages into your app:
import com.google.home.Home
import com.google.home.Id
import com.google.home.Structure
Error handling
Any method in the Home APIs can throw a
HomeException, so we recommend that you use a try-catch block to
catch HomeException on all calls.
When handling HomeException, check its
error.code and
error.message fields to learn what went wrong. There may be sub-error codes
as well, so call the
getSubErrorCodes() method and check the result.
Any unhandled exceptions will result in your app crashing.
For more information, see Error handling.
Sample calls
Get a list of structures
Once initialized, a structures() call returns a Flow of structures
accessible to you:
// 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()
The structures() API is a flow that may not immediately return a valid
list of structures. If your app is reactive and subscribes to that flow to
drive the UI, a valid list of structures should eventually be returned.
There are other situations where an empty structure list could be returned, for
example if the user's phone loses connectivity or if the user
has revoked permissions to your app. You should be sure to handle these cases
in your app.
Alternatively, if imperative programming is strongly required instead of reactive programming, a terminal flow operator can be used:
val everyStructure = withTimeout(5000) { home.structures().first { it.isNotEmpty() } }
This call waits for a valid list of structures to come through the flow and times out if the list is not received within an app-designated timeout.
Get structure properties
With the list of structures in hand, you can access the properties for them:
// 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}")
Find a structure by name
If you know the name of a structure, you can also access it using the name
property:
val myHome = home.structures().list().first { it.name == "My home" }
From there, properties, rooms, and devices for each structure are accessible.
Work with multiple structures
To use more than one structure, get a separate reference to each structure:
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 }
Get a list of rooms
With a structure in hand, you can get a list of rooms and access the properties for them:
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}")
Create a room
To create a new room:
val testName = "Test Room Name" val newRoom: Room = structure.createRoom(testName)
Delete a room
Or, alternatively, you can delete a room:
val roomToDelete = structure.rooms().list().filter { it.name == "room_id1" }.firstOrNull() structure.deleteRoom(roomToDelete!!)
You can also delete a room with just an ID:
val roomToDelete1 = allRooms.filter { it.id == testRoomId }.firstOrNull() structure.deleteRoom(roomToDelete1!!)
If a room with devices is deleted, the devices will still be in the structure but no longer assigned to a room.
Move devices to a different room
Once you have a structure, you can move devices to a different room within that structure:
val room2 = structure.rooms().get(Id("room_id_other_structure")) val device1 = structure.devices().get(Id("device_id1")) structure.moveDevicesToRoom(room2!!, listOf(device1!!))
If you only have device and room IDs, you can also move devices:
structure.moveDevicesToRoom(Id("room_id_other_structure"), listOf(Id("device_id1")))
Change the name of a room
Call the setName()
method to change the name of a room:
livingRoom.setName("Living Room")
Names will be truncated if over the 60 Unicode code point (character) limit and no errors will be thrown. Developers are responsible for handling long names and, for example, can decide if they want to inform users names will be truncated.
View the device types a user has granted permissions for
In the Google Home ecosystem, for most device types, users can grant permissions for all devices of that type at once. For sensitive or restricted device types, such as locks, cameras, or doorbells, users must grant permission to them individually.
To determine whether a user has granted permission to access a sensitive or
restricted device type, use the Structure-level consentedDeviceTypes()
function:
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
}
}
}
}
Automations
The entry point to the Automation API is through a structure. To learn more about Automations in the Home APIs, see Automation API on Android overview.