1. Prima di iniziare
Le API Google Home forniscono un insieme di librerie che consentono agli sviluppatori Android di accedere all'ecosistema Google Home. Con queste nuove API, gli sviluppatori possono creare app che commissionano e controllano facilmente i dispositivi per la smart home.
Google fornisce un'app di esempio per Android per gli sviluppatori che vogliono accedere a un esempio funzionante che utilizza le API Google Home. Questo codelab si basa su un ramo dell'app di esempio che illustra come utilizzare le API Permissions, Commissioning, Device e Structure.
Prerequisiti
- Conoscenza dell'ecosistema Google Home (cloud-to-cloud e Matter).
- Una workstation con Android Studio (2024.3.1 Ladybug o versioni successive) installato.
- Uno smartphone Android che soddisfi i requisiti delle API Home (vedi Prerequisiti) con Google Play Services e l'app Google Home installati.
- Un Google Nest Hub compatibile che supporta le API Google Home.
- Facoltativo: un dispositivo per la smart home compatibile con le API Google Home.
Obiettivi didattici
- Come creare un'app per Android utilizzando le API Google Home con le best practice.
- Come utilizzare le API Device e Structure per rappresentare e controllare una smart home.
- Come utilizzare le API di messa in servizio per aggiungere dispositivi all'ecosistema Google Home.
(Facoltativo) Configurare la casa
Prima di utilizzare le API Google Home, devi configurare una casa sul tuo Account Google utilizzando l'app Google Home e aggiungere alcuni dispositivi. Questa sezione spiega come eseguire questa operazione utilizzando Google Home Playground, che fornisce dispositivi per la smart home virtuali.
Apri home-playground.withgoogle.com nel browser web, accedi con il tuo Account Google e controlla se vengono visualizzati i seguenti dispositivi emulati:
- presa1: spina On/Off
- light2: luce dimmerabile
- light3: luce On/Off
- ac3: aria condizionata
- blinds4: Copertura finestra
- washer5: lavatrice smart
Apri l'app Google Home sul tuo dispositivo mobile, tocca il pulsante Aggiungi e seleziona Compatibile con Google Home. Cerca "playground" nell'elenco, quindi seleziona il progetto "Google Home Playground" e tocca Continua.
Google Home Playground mostrerà una pagina di autorizzazione dell'account. Tocca Autorizza o Accedi con Google. Nell'app mobile vedrai tutti i dispositivi configurati dall'app web.
Seleziona tutti i dispositivi e completa la procedura di configurazione. Tornando alla home page, vedrai tutti i dispositivi disponibili.
I dispositivi supportati nell'elenco ora possono essere utilizzati con le API Google Home.
2. Configura il progetto
Il seguente diagramma illustra l'architettura di un'app per le API Home:
- Codice dell'app:il codice di base su cui lavorano gli sviluppatori per creare l'interfaccia utente dell'app e la logica per interagire con l'SDK delle API Home.
- SDK Home APIs: l'SDK Home APIs fornito da Google funziona con il servizio Home APIs in GMSCore per controllare i dispositivi per la smart home. Gli sviluppatori creano app compatibili con le API Home raggruppandole con l'SDK delle API Home.
- GMSCore su Android:GMSCore, noto anche come Google Play Services, è una piattaforma Google che fornisce servizi di sistema di base, attivando funzionalità chiave su tutti i dispositivi Android certificati. Il modulo Home di Google Play Services contiene i servizi che interagiscono con le API Home.
Configurare l'SDK Home
Segui i passaggi descritti in Configurare l'SDK per ottenere l'SDK più recente.
Ottieni l'app di esempio
Il codice sorgente dell'app di esempio è disponibile su GitHub. Questo codelab utilizza gli esempi del ramo codelab-branch-1
dell'app di esempio.
Vai alla posizione in cui vuoi salvare il progetto e clona il ramo codelab-branch-1
:
$ git clone -b codelab-branch-1 https://github.com/google-home/google-home-api-sample-app-android.git
Crea l'app di esempio
Esegui i passaggi da 1 a 5 in Creare l'app.
Quando l'app è in esecuzione correttamente sullo smartphone, viene visualizzata la pagina principale dell'app di esempio. Tuttavia, non potrai accedere finché non avrai configurato l'autenticazione OAuth e implementato i componenti mancanti utilizzando l'API Permission.
3. Configurare l'autenticazione
Le API Home utilizzano OAuth 2.0 per concedere l'accesso ai dispositivi della struttura. OAuth consente a un utente di concedere l'autorizzazione a un'app o a un servizio senza dover esporre le proprie credenziali di accesso.
Segui le istruzioni riportate in Configurare il consenso OAuth per configurare la schermata per il consenso. Assicurati di creare almeno un account di test.
Poi segui le istruzioni riportate in Configurare le credenziali OAuth per creare le credenziali per l'app.
4. Autorizzazioni di inizializzazione e gestione
In questa sezione imparerai a inizializzare l'SDK e a gestire le autorizzazioni utente completando i componenti mancanti utilizzando l'API Permissions.
Definire tipi e tratti supportati
Quando sviluppi un'app, devi indicare esplicitamente i tipi di dispositivi e le caratteristiche che l'app supporterà. Nell'app di esempio, lo facciamo definendo elenchi statici nell'oggetto companion in HomeApp.kt
, a cui poi possiamo fare riferimento in tutta l'app in base alle esigenze:
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,
// ...
)
}
Consulta Tipi di dispositivi supportati e Indice di tratti su Android per visualizzare tutti i tipi e i tratti dei dispositivi supportati.
Rimuovi il commento dai passaggi 4.1.1 e 4.1.2 nel file di origine HomeApp.kt
per attivare il codice sorgente che richiede l'autorizzazione.
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,
)
}
Inizializzare l'oggetto HomeClient
Tutte le app che utilizzano le API Home inizializzano un oggetto HomeClient
, che è l'interfaccia principale per interagire con le API. Prepariamo questo oggetto nell'inizializzatore della classe 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)
Innanzitutto, creiamo un FactoryRegistry
utilizzando i tipi e gli attributi supportati che abbiamo definito in precedenza. Poi, utilizzando questo registry, inizializziamo un HomeConfig
, che contiene la configurazione necessaria per eseguire le API. Successivamente, utilizziamo la chiamata Home.getClient(...)
per acquisire l'istanza HomeClient
.
Le nostre interazioni con le API Home avverranno tutte tramite questo oggetto HomeClient
.
Utilizzare l'API Permissions
L'autenticazione utente per le API Home viene eseguita tramite l'API Permissions. Il file di origine PermissionsManager.kt
dell'app di esempio contiene il codice per l'autenticazione utente. Rimuovi il commento dai contenuti delle funzioni checkPermissions(...)
e requestPermissions(...)
per attivare le autorizzazioni per l'app di esempio.
Registrazione:
homeClient.registerActivityResultCallerForPermissions(activity)
Lancio:
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) { ... }
Verifica in corso:
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) { ... }
Sottoscrizione:
homeClient.hasPermissions().collect( { state ->
// Track the changes on state
} )
Rimuovi il commento dal passaggio 4.3.1 in PermissionsManager.kt
per attivare il codice che richiede le autorizzazioni:
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()) }
}
}
Ora esegui l'app sul tuo smartphone, seguendo i passaggi e consentendo le autorizzazioni. Dovresti visualizzare il seguente flusso:
Il messaggio "Caricamento" non scompare mai, ma questo perché non abbiamo implementato il codice che legge la struttura e i dispositivi. Lo faremo nella prossima sezione.
5. Informazioni sul modello di dati
Nelle API Home, il modello di dati è composto da:
Structure
rappresenta una casa contenente stanze e dispositivi.Room
fa parte di una struttura e contiene dispositivi.- I dispositivi (definiti come
HomeDevice
) possono essere assegnati a una struttura (o casa) o a una stanza all'interno della struttura. - I dispositivi sono composti da una o più istanze
DeviceType
. DeviceType
è composto daTrait
istanze.Trait
è composto da istanzeAttribute
(per la lettura/scrittura), istanzeCommand
(per il controllo degli attributi) e istanzeEvent
(per la lettura o l'iscrizione ai record delle modifiche passate).- Le istanze
Automation
fanno parte di una casa e utilizzano i metadati e i dispositivi della casa per automatizzare le attività al suo interno.
In questa sezione imparerai a sviluppare il codice sorgente per mostrare come utilizzare l'API Structure per analizzare e visualizzare le strutture, le camere, i dispositivi e così via della tua casa.
Leggi strutture
Il design delle API Home si basa su Kotlin Flows per trasmettere in streaming gli oggetti del modello di dati (ad esempio Structure
, HomeDevice
e così via). Gli sviluppatori si abbonano a un Flow
per ottenere tutti gli oggetti contenuti nell'oggetto (ad esempio un Structure
, un Room
e così via).
Per recuperare tutte le strutture, chiama la funzione structures()
, che restituisce un flusso di strutture. Quindi, chiama la funzione di elenco nel flusso per ottenere tutte le strutture di proprietà dell'utente.
// Get the a snapshot of all structures from the current homeClient
val allStructures : Set<Structure> =
homeClient.structures() // HomeObjectsFlow<Structure>
.list() // Set<Structure>
La Guida all'architettura delle app consiglia vivamente di adottare un approccio di programmazione reattiva moderno per migliorare il flusso di dati e la gestione dello stato dell'app.
Ecco come l'app di esempio rispetta lo stile di programmazione reattivo:
- I modelli di visualizzazione (come
StructureViewModel
eDeviceViewModel
, come detentori dello stato) si iscrivono ai flussi dall'SDK delle API Home per ricevere le modifiche ai valori e mantenere gli stati più recenti. - Le visualizzazioni (come
StructureView
eDeviceView
) si iscrivono ai modelli di visualizzazione per ricevere gli stati e eseguire il rendering dell'interfaccia utente in modo da riflettere queste modifiche. - Quando un utente fa clic su un pulsante in una visualizzazione (ad esempio il pulsante "On" di un dispositivo di illuminazione), gli eventi attivano le funzioni del modello di visualizzazione, che chiamano le funzioni delle API Home di risposta (ad esempio il comando
On
del trattoOnOff
).
Nel passaggio 5.1.1 in HomeAppViewModel.kt
, ci abboniamo agli eventi di modifica della struttura chiamando la funzione collect()
. Rimuovi il commento dalla sezione che attraversa il structureSet
restituito dalla risposta dell'API Structures e inviato in StructureViewModel's
StateFlow
. In questo modo l'app può monitorare le modifiche dello stato della struttura:
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())
//
// }
}
In DevicesView.kt
, l'app si iscrive a StructureViewModel'sStateFlow,
, che attiva la ricompozione dell'interfaccia utente quando i dati della struttura cambiano. Rimuovi il commento dal codice sorgente nel passaggio 5.1.2 per visualizzare l'elenco delle strutture come menu a discesa:
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
// }
// )
// }
}
...
Esegui di nuovo l'app. Dovresti vedere il menu quando tocchi la freccia:
Analizza la struttura
Il passaggio successivo consiste nell'esplorare gli oggetti della casa in una struttura. Recupera le camere della struttura:
val rooms: Set<Room>
rooms = structure.rooms().list()
Puoi quindi spostarti tra le stanze per recuperare i dispositivi:
val devices: Set<HomeDevice>
devices = room.devices().list()
Importante:nel modello di dati delle API Home, una struttura può contenere dispositivi che non sono assegnati a una stanza, quindi assicurati di acquisire anche i dispositivi senza stanze nella tua app:
val devicesWithoutRooms: MutableSet<HomeDevice> = mutableSetOf()
for (device in structure.devices().list())
if (!device.isInRoom)
devicesWithoutRooms.add(device)
Anche nel codice di esempio esistente, ci abboniamo a un flusso per ottenere l'elenco più recente di stanze e dispositivi. Controlla il codice nei passaggi 5.2.1 e 5.2.2 nel file di origine StructureViewModel.kt
e rimuovi il commento per attivare l'abbonamento ai dati della stanza:
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)
// }
}
Rimuovi il commento dai passaggi 5.2.3 e 5.2.4 nel file di origine DevicesView.kt
per visualizzare l'elenco delle camere come menu:
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)
// }
}
Ora che hai i dispositivi, impareremo a utilizzarli.
6. Lavorare con i dispositivi
Le API Home utilizzano un oggetto HomeDevice
per acquisire il dispositivo e le sue funzionalità. Gli sviluppatori possono iscriversi agli attributi dei dispositivi e utilizzarli per rappresentare i dispositivi per la smart home nelle loro app.
Leggere gli stati dei dispositivi
L'oggetto HomeDevice
presenta un insieme di valori statici, come il nome del dispositivo o lo stato della connettività. In qualità di sviluppatore, puoi recuperarli subito dopo aver ottenuto il dispositivo dalle API:
val id: String = device.id.id
val name: String = device.name
val connectivity: ConnectivityState =
device.sourceConnectivity.connectivityState
Per ottenere le funzionalità del dispositivo, devi recuperare i tipi e le caratteristiche da HomeDevice
. Per farlo, puoi iscriverti al flusso di tipo di dispositivo come segue e recuperare le caratteristiche dai tipi di dispositivo:
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)
}
Ogni dispositivo contiene un insieme di DeviceType
supportati (funzionalità in bundle), che puoi recuperare utilizzando device.types()
. Questi tipi di dispositivi contengono tratti che possono essere recuperati utilizzando type.traits()
. Ogni dispositivo contrassegna uno dei suoi tipi come tipo principale (che può essere controllato utilizzando type.metadata.isPrimaryType
) che devi rappresentare nella tua app. Per offrire un'esperienza completa agli utenti, ti consigliamo di esaminare tutti i tipi restituiti e di integrare tutti i tratti a tua disposizione.
Dopo aver recuperato un tratto, puoi analizzarlo utilizzando una funzione come la seguente per interpretare i valori:
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 -> ...
}
}
Tieni presente che possono esserci variazioni in ciò che rappresenta un tratto, a seconda del tipo di dispositivo che lo include (vedi BooleanState
nell'esempio precedente), quindi devi conoscere il contesto di ogni tipo di dispositivo per capire cosa rappresentano realmente i relativi tratti.
Rimuovi il commento dai passaggi 6.1.1 e 6.1.2 nel file di origine DeviceViewModel.kt
per recuperare gli stati:
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
}
Rimuovi il commento dal passaggio 6.1.3 in DeviceView.kt
per visualizzare un tratto OnOff, inclusi il nome e lo stato, come 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 -> {
...
}
...
}
Se esegui l'app ora con i tipi di dispositivi supportati (ad esempio un dispositivo Light), dovresti visualizzare gli stati aggiornati di tutti i dispositivi.
Emettere comandi al dispositivo
Per emettere comandi ai dispositivi, le API Home forniscono funzioni di utilità sugli oggetti Trait come trait.on()
o trait.moveToLevel(...)
:
fun <T : Trait?> issueCommand(trait : T) {
when (trait) {
is OnOff -> {
// trait.on()
// trait.off()
}
is LevelControl -> {
// trait.moveToLevel(...)
// trait.moveToLevelWithOnOff(...)
}
}
}
Suggerimento:una volta determinato il tipo di tratto, utilizza la funzionalità di completamento automatico di Android Studio per vedere quali tipi di azioni sono disponibili per interagire con il tratto.
Rimuovi il commento dal passaggio 6.2.1 in DeviceView.kt
per aggiungere controlli funzionali nell'app:
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
// )
}
Se esegui l'app ora, dovresti riuscire a controllare dispositivi fisici reali.
Se tocchi il controllo On/Off sulla lampadina, il dispositivo dovrebbe accendersi.
Per ulteriori informazioni su come controllare i dispositivi, vedi Controllare i dispositivi su Android.
7. Configurare i dispositivi
L'API Commissioning consente agli sviluppatori di aggiungere dispositivi all'ecosistema Google Home e di renderli disponibili per il controllo tramite le API Home. Sono supportati solo i dispositivi Matter. In questa sezione vedremo come abilitare la messa in servizio dei dispositivi nelle tue app.
Prima di iniziare questa sezione, assicurati che siano soddisfatti i seguenti prerequisiti:
- Un hub Google compatibile con Matter connesso alla stessa rete del tuo smartphone Android è stato aggiunto all'app Google Home.
- Hai creato un progetto per gli sviluppatori nella Console per gli sviluppatori di Google Home con il VID
0xFFF1
e il PID0x8000
.
Se hai un dispositivo Matter fisico con un codice QR per la messa in servizio, puoi andare alla sezione Abilitare l'API di messa in servizio. In caso contrario, vai alla sezione successiva, dove viene spiegato come utilizzare l'app Matter Virtual Device (MVD) per creare dispositivi virtuali commissionabili.
(Facoltativo) Preparare un dispositivo di messa in servizio Matter
Il modo più semplice per preparare un dispositivo di messa in servizio Matter è utilizzare un dispositivo virtuale fornito dall'app Matter Virtual Device (MVD).
Dopo aver installato l'MVD e configurato il firewall, esegui l'MVD:
Crea un dispositivo OnOff. Tieni presente che non è ancora stato commissionato: lo farai in un secondo momento in questo codelab.
Abilita l'API Commissioning
L'API Commissioning funziona al di fuori dell'attività dell'app, pertanto la messa in servizio deve essere gestita in modo diverso rispetto alle altre API Home. Per preparare l'app per la messa in servizio, sono necessarie due variabili.
Una variabile è ActivityResultLauncher
, che viene utilizzata per inviare l'intent di messa in servizio e per gestire il callback del risultato. L'altra variabile è CommissioningResult
, l'oggetto utilizzato per memorizzare il risultato della messa in servizio. Consulta l'esempio seguente per scoprire come configurare la messa in servizio:
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
}
}
Una volta configurato il flusso di messa in servizio, dovrai creare l'intent di messa in servizio e avviarlo utilizzando il programma di lancio che abbiamo creato nell'esempio precedente. Ti consigliamo di posizionare l'intent e il programma di avvio in una funzione dedicata come la seguente. Una funzione dedicata può essere collegata a un elemento dell'interfaccia utente (ad esempio un pulsante +Aggiungi dispositivo) e richiamata in base alla richiesta dell'utente:
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())
}
}
Rimuovi il commento dal passaggio 7.1.1 in CommissioningManager.kt
per attivare la funzionalità di messa in servizio e far funzionare il pulsante + Aggiungi dispositivo nell'app di esempio.
// 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())
// }
}
L'esecuzione di questa funzione dovrebbe avviare il flusso di messa in servizio, che dovrebbe mostrare una schermata simile allo screenshot seguente:
Informazioni sul flusso di messa in servizio
Il flusso di messa in servizio include una serie di schermate che guidano l'utente nell'aggiunta di un dispositivo al proprio Account Google:
Gli utenti vedranno uno scanner di codici QR che possono utilizzare per scansionare i codici QR dei dispositivi Matter. Il flusso prevede poi la visualizzazione del Contratto utente, il rilevamento e la messa in servizio del dispositivo e la sua denominazione. Al termine, il flusso tornerà a concentrarsi sull'app e passerà il risultato della messa in servizio alla funzione di callback che abbiamo creato nella sezione precedente.
Un vantaggio delle API di messa in servizio è che il flusso dell'esperienza utente viene gestito dall'SDK, pertanto gli sviluppatori possono iniziare a utilizzare l'app molto rapidamente. Inoltre, offre agli utenti un'esperienza coerente quando aggiungono dispositivi in app diverse.
Per saperne di più sull'API di messa in servizio, visita la pagina API di messa in servizio su Android.
8. Complimenti!
Complimenti! Hai creato un'app per Android utilizzando le API Google Home. In questo codelab hai esplorato le API Permissions, Devices, Structures e Commissioning. Nel prossimo codelab, Creare automazioni avanzate utilizzando le API Home su Android Codelab, esploreremo le API Automation e Discovery e completeremo l'app.
Ci auguriamo che ti piaccia creare app che controllino in modo creativo i dispositivi all'interno dell'ecosistema Google Home.
Passaggi successivi
- Per continuare il tuo percorso di apprendimento delle API Home su Android, completa il secondo codelab di questa serie: Creare automazioni avanzate utilizzando le API Home su Android.
- Puoi contattarci per ricevere consigli o segnalare eventuali problemi tramite l'argomento dell'assistenza per la smart home del tracker dei problemi.