1. Te damos la bienvenida
Matter se creó con el objetivo de unificar los estándares de IoT y conecta dispositivos de casa inteligente en varios ecosistemas, como Google Home, Zigbee, Bluetooth Mesh, Z-Wave y muchos más.
Los dispositivos móviles son un punto de interacción central con los dispositivos de casa inteligente. Si quieres compilar tus propias apps para Android compatibles con dispositivos Matter, podemos ayudarte a comenzar rápidamente.
La app de ejemplo de Google Home para Matter (GHSA para Matter) muestra las APIs del SDK de Home para dispositivos móviles, lo que permite a los usuarios crear y compartir dispositivos. También puedes usar la app de ejemplo como herramienta de aprendizaje a fin de comprender mejor los conceptos clave de Matter, así como para depurar y solucionar problemas de interacción con dispositivos Matter.
Actividades
En este Codelab, descargarás el código fuente de la app de ejemplo y aprenderás a usar el SDK para dispositivos móviles de Home a fin de asignar y compartir dispositivos. También aprenderás a usar las bibliotecas de asignación y Clúster del repositorio de Matter (connectedhomeip
).
Después de descargar la app de ejemplo, revisaremos el código fuente en Android Studio y, luego, implementaremos las siguientes APIs del SDK de Home Mobile:
También obtendrás más información sobre los conceptos de asignación, las telas de Matter y cómo controlar los dispositivos Matter.
Requisitos
Antes de comenzar, asegúrate de completar los siguientes pasos:
- Revisa la Guía de ejemplo de la app de Google Home para Matter.
- Descarga Android Studio.
- Debes tener disponible un dispositivo con Android O (8.1, nivel de API 27) o versiones posteriores. Para asegurarte de que tu dispositivo tenga la compatibilidad más reciente con Matter, consulta la guía Verifica módulos y servicios de Matter.
- Compila un dispositivo Matter con funciones de activación y desactivación. Esta app de ejemplo funciona con un dispositivo virtual y un ESP32.
- Crea un dispositivo virtual de Matter con la app de
rootnode_dimmablelight_bCwGYSDpoe
. Cuando crees una integración de Matter en Home Developer Console, usa0xFFF1
como ID de proveedor y0x8000
como ID de producto. - Compila un dispositivo Espressif con el
all-clusters-app
. Cuando crees una integración de Matter en Home Developer Console, usa0xFFF1
como tu ID de proveedor y0x8001
como tu ID de producto.
- Crea un dispositivo virtual de Matter con la app de
- Consulta cómo configurar los Servicios de Google Play.
No necesitas un concentrador (por ejemplo, un Google Nest Hub (2a gen.)) para asignar y controlar dispositivos con la app de ejemplo.
2. Prepárate
El repositorio de GitHub de la app de ejemplo incluye bibliotecas de terceros del repositorio de Matter (connectedhomeip
). Estas bibliotecas nativas superan los 50 MB y requieren el uso de Git Large File Storage (LFS).
La app de inicio del codelab se encuentra en la rama codelab
. Para comenzar a trabajar con el código fuente del codelab, puedes descargar el archivo ZIP. Este archivo ZIP incluye las bibliotecas nativas del SDK de Matter sin la necesidad de usar LFS de Git:
Usarás este archivo ZIP codelab
para compilar una muestra funcional.
Versiones de Codelab
La rama codelab
está etiquetada con la versión 1.2.2 de la app de ejemplo. Para comparar las actualizaciones a medida que avanzas en cada paso, puedes descargar el código fuente completo de esta versión.
Si deseas clonar el repositorio de GitHub, sigue las instrucciones en el archivo README de la app de ejemplo.
Dependencias
Te guiaremos a través del código fuente necesario para compartir y poner en marcha los dispositivos, pero puede ser útil tener en cuenta las siguientes dependencias antes de comenzar:
- SDK de Home Mobile.
implementation 'com.google.android.gms:play-services-home:16.0.0'
- Bibliotecas de SDK de Matter.
// Native libs implementation fileTree(dir: "third_party/connectedhomeip/libs", include: ["*.jar", "*.so"])
- Material Design. Para obtener más información, consulta MDC-103 de Android: Temas de Material con color, elevación y tipo (Kotlin) y Material Theme Builder.
implementation 'com.google.android.material:material:1.5.0'
- Proto DataStore, que se usa para conservar los datos de apps. Los repositorios y repositorios de Datastore se almacenan en
java/data
, incluidos esquemas para dispositivos y preferencias de usuario. Para obtener más información sobre DataStore, consulta Cómo trabajar con Proto DataStore.implementation "androidx.datastore:datastore:$dataStoreVersion" implementation 'androidx.datastore:datastore-core:1.0.0' implementation 'com.google.protobuf:protobuf-javalite:3.18.0'
- Hilt para conservar datos y admitir la inserción de dependencias
kapt 'com.google.dagger:hilt-compiler:2.41' implementation 'com.google.dagger:hilt-android:2.41'
Código fuente
La interfaz de usuario y la mayor parte de la funcionalidad ya se crearon para usted.
En este codelab, agregaremos la función Matter a los siguientes archivos:
java/commissioning/AppCommissioningService
: Te permite asignar dispositivos a la estructura de desarrollo.java/screens/HomeFragment
yjava/screens/HomeViewModel.kt
: Incluyen la funcionalidad de asignación del SDK de Home para dispositivos móviles.java/screens/DeviceViewModel
: Incluye las llamadas a la API de Share Device.
Cada archivo se comenta con el bloque de código que usted modificará, por ejemplo:
// CODELAB: add commissioningFunction()
Esto te permite ubicar rápidamente la sección correspondiente en el codelab.
3. Comisión para Google
Para poder controlar los dispositivos y permitirles comunicarse entre sí dentro de la misma estructura, es necesario que un comisionado la encargue, en este caso, esta aplicación de ejemplo, la app de ejemplo de Google Home.
Es importante comprender los siguientes conceptos sobre la asignación de Matter:
- Las telas permiten que los dispositivos se comuniquen entre sí.
- Los fabricantes mantienen un conjunto compartido de credenciales únicas.
- Los ecosistemas son responsables de emitir certificados raíz de confianza y asignar ID de tejido y ID de nodos únicos. Un ecosistema es el servicio de backend de un comisionado, por ejemplo, el Home Graph para el ecosistema de Google Home.
- Los dispositivos se pueden asignar a más de un tejido (función de varios administradores).
Para cobrar un dispositivo, deberás usar la API de CommissioningClient. Una llamada a .commissionDevice()
muestra un IntentSender, que inicia la actividad adecuada en los Servicios de Google Play:
interface CommissioningClient { Task<IntentSender> commissionDevice(CommissioningRequest request); }
En las siguientes secciones, revisaremos el código mínimo necesario para asignar dispositivos a la estructura de Google.
Paso 1: Selector de actividades
Para controlar IntentSender
desde CommissioningClient
, puedes usar un ActivityResultLauncher:
private lateinit var commissioningLauncher: ActivityResultLauncher<IntentSenderRequest>
commissioningLauncher = registerForActivityResult( StartIntentSenderForResult() ) { result: ActivityResult -> if (result.resultCode == RESULT_OK) { Timber.d(TAG, "Commissioning succeeded.") } else { Timber.d(TAG, "Commissioning failed. " + result.resultCode) } }
Paso 2: Función de puesta en marcha
Este es un ejemplo básico que usa la API de CommissioningClient para asignar un dispositivo a la estructura de Google.
- El proceso de asignación comienza con la función
commissionDevice()
. Primero, se define unCommissioningRequest
. Con esta configuración predeterminada, los dispositivos se encargan solo a la estructura de Android local. Matter
es el punto de entrada del SDK de Home para dispositivos móviles. En la próxima llamada,.getCommissioningClient
obtiene un CommissioningClient dethis
(Actividad)..commissionDevice()
aceptaCommissioningRequest
.- Por último, se llama a
.addOnSuccessListener
para procesarCommissioningResult
e iniciar la actividad Dispositivo de comisión de los Servicios de Google Play (GPS).
private fun commissionDevice() { val request: CommissioningRequest = CommissioningRequest.builder().build() Matter.getCommissioningClient(this) .commissionDevice(request) .addOnSuccessListener { result -> commissioningLauncher.launch(IntentSenderRequest.Builder(result).build()) } }
Puedes aprovechar Android Fabric local en la configuración de Android para simplificar el proceso de puesta en marcha de sus dispositivos a otras telas.
A continuación, aprenderás cómo asignar un dispositivo a una estructura de desarrollo.
Para obtener una descripción general de la interfaz de usuario durante el proceso de asignación, consulta la Guía de ejemplo de la app de Google Home para Matter.
4. Comisión a una estructura de desarrollo
Los dispositivos se pueden asignar a más de un tejido. Para administrar las vinculaciones de confianza, los dispositivos almacenan un FabricTable
que contiene varios miembros de FabricInfo
, por ejemplo:
- Identificación de Fabric
- ID de nodo asignado por la estructura al dispositivo
- ID de proveedor
- ID de Fabric
- Credenciales operativas del dispositivo
El administrador de dominio administrativo (ADM) define las credenciales de tejido. En la situación anterior, los Servicios de Google Play son el ecosistema que actúa como una autoridad certificadora raíz (CA) de confianza. Cuando se encargan dispositivos a la estructura local de Android, todos los dispositivos incluyen el mismo conjunto de credenciales de tela y el mismo conjunto de CA.
Servicios de encargo personalizados
A fin de asignar la estructura local de Android, usamos los parámetros predeterminados para compilar CommissioningRequest
en la API de CommissioningClient:
val request: CommissioningRequest = CommissioningRequest.builder().build()
Si quieres controlar y administrar dispositivos nuevos desde tu app, debes crear una estructura de desarrollo local y obtener las credenciales operativas para asignar dispositivos. En este caso, tu app se convierte en un ecosistema independiente y único que asigna a los dispositivos las credenciales de nodo adecuadas.
Puedes informar a Home Mobile SDK que deseas asignar dispositivos a tu propia red pasando un servicio personalizado a CommissioningRequest:
class CommissioningRequest { static CommissioningRequest.Builder builder(); class Builder { Builder setCommissioningService(@Nullable ComponentName commissioningService); CommissioningRequest build(); } }
En los próximos pasos, modificaremos la función commissionDevice()
para usar un servicio personalizado. También agregaremos un selector de actividades al fragmento de la página principal y usaremos objetos LiveData para administrar el flujo de la API.
Paso 1: Crea un selector de actividades de GPS
Primero, crearemos un selector de actividades para controlar IntentSender
desde la API de CommissioningClient.
- Abre
HomeFragment
en la carpetajava/screens/home/
. - Reemplaza el comentario
// CODELAB: commissionDeviceLauncher declaration
por la siguiente declaración:// The ActivityResult launcher that launches the "commissionDevice" activity in Google Play // Services. private lateinit var commissionDeviceLauncher: ActivityResultLauncher<IntentSenderRequest>
- Reemplaza el comentario
// CODELAB: commissionDeviceLauncher definition
por el siguiente código para registrar y controlar el resultado de la actividad de puesta en marcha:commissionDeviceLauncher = registerForActivityResult(ActivityResultContracts.StartIntentSenderForResult()) { result -> // Commission Device Step 5. // The Commission Device activity in GPS has completed. val resultCode = result.resultCode if (resultCode == Activity.RESULT_OK) { Timber.d("CommissionDevice: Success") // We now need to capture the device information for the app's fabric. // Once this completes, a call is made to the viewModel to persist the information // about that device in the app. showNewDeviceAlertDialog(result) } else { viewModel.commissionDeviceFailed(resultCode) } } ```
Paso 2: Crea objetos LiveData
La devolución de llamada exitosa de la API de .commissionDevice()
proporciona la IntentSender
que se usará para iniciar la actividad del dispositivo de comisión en los Servicios de Google Play. En el HomeViewModel
, crearemos dos objetos LiveData para informar sobre el resultado de esta llamada a la API:
commissionDeviceStatus
para realizar un seguimiento deTaskStatus
commissionDeviceIntentSender
para controlar el resultado de la llamada a.commissionDevice()
Este objeto de LiveData iniciará elActivityLauncher
que acabamos de crear y le mostrará al usuario la actividad de dispositivo de comisión de GPS.
- En
private fun setupObservers()
, reemplaza el comentario// CODELAB: commissionDeviceStatus
por el siguiente observador:// The current status of the share device action. viewModel.commissionDeviceStatus.observe(viewLifecycleOwner) { status -> Timber.d("commissionDeviceStatus.observe: status [${status}]") }
- Luego, reemplaza el comentario
// CODELAB: commissionDeviceIntentSender
por el siguiente observador:viewModel.commissionDeviceIntentSender.observe(viewLifecycleOwner) { sender -> Timber.d( "commissionDeviceIntentSender.observe is called with [${intentSenderToString(sender)}]") if (sender != null) { // Commission Device Step 4: Launch the activity described in the IntentSender that // was returned in Step 3 (where the viewModel calls the GPS API to commission // the device). Timber.d("CommissionDevice: Launch GPS activity to commission device") commissionDeviceLauncher.launch(IntentSenderRequest.Builder(sender).build()) viewModel.consumeCommissionDeviceIntentSender() } }
Paso 3: Llama a la API
Ahora que escribimos el código para controlar el flujo de la API, es momento de llamar a la API, pasar un servicio personalizado (que definiremos en el siguiente paso) y publicar en nuestros objetos LiveData.
- Abre
HomeViewModel.kt
en la carpetajava/screens/home/
. - Reemplaza el comentario
// CODELAB: commissionDevice
por el siguientecommissionDeviceRequest
.setCommissioningService
vinculaAppCommissioningService
a una instancia deCommissioningService
, que se muestra en una función de devolución de llamada. Cuando pases un servicio personalizado, el SDK para dispositivos móviles de la casa encargará primero los dispositivos a la estructura de Google y, luego, enviará la carga útil de integración aAppCommissioningService
.fun commissionDevice(context: Context) { _commissionDeviceStatus.postValue(TaskStatus.InProgress) val commissionDeviceRequest = CommissioningRequest.builder() .setCommissioningService(ComponentName(context, AppCommissioningService::class.java)) .build()
- Llama a
.getCommissioningClient()
y, luego, a.commissionDevice()
.Matter.getCommissioningClient(context) .commissionDevice(commissionDeviceRequest)
Para completar nuestra función commissionDevice
, agrega addOnSuccessListener
y addOnFailureListener
, y publica en los objetos LiveData:
.addOnSuccessListener { result -> // Communication with fragment is via livedata _commissionDeviceIntentSender.postValue(result) } .addOnFailureListener { error -> Timber.e(error) _commissionDeviceStatus.postValue( TaskStatus.Failed("Failed to to get the IntentSender.", error) } }
Después de usar el remitente, se debe llamar a consumeCommissionDeviceIntentSender()
para evitar recibirlo nuevamente después de un cambio de configuración.
/** * Consumes the value in [_commissionDeviceIntentSender] and sets it back to null. Needs to be * called to avoid re-processing the IntentSender after a configuration change (where the LiveData * is re-posted). */ fun consumeCommissionDeviceIntentSender() { _commissionDeviceIntentSender.postValue(null) }
5. Crea un servicio de Commissioning
En la función commissionDevice()
, solicitamos obtener un CommissioningService de la API de CommissioningClient. En este flujo, la API de CommissioningClient encarga los dispositivos a la estructura local de Android y, luego, muestra una devolución de llamada que incluye el objeto CommissioningRequestMetadata:
public interface CommissioningService { interface Callback { void onCommissioningRequested(CommissioningRequestMetadata metadata); } }
Ahora, debemos heredar CommissioningService.Callback y proporcionar la funcionalidad necesaria para asignar dispositivos a nuestra app de ejemplo. A continuación, se muestra un ejemplo de una implementación básica de CommissioningService:
class MatterCommissioningService : Service(), CommissioningService.Callback { private val commissioningServiceDelegate = CommissioningService.Builder(this) .setCallback(this) .build() override fun onBind(intent: Intent) = commissioningServiceDelegate.asBinder() override fun onCommissioningRequested(metadata: CommissioningRequestMetadata) { // perform commissioning commissioningServiceDelegate .sendCommissioningComplete(CommissioningCompleteMetadata.builder().build()) } }
Paso 1: Explora el AppCommissioningService personalizado
A fin de ayudarte a comenzar, ya definimos la estructura de clase básica para nuestro objeto CommissioningService personalizado. Esta es una descripción general rápida de la funcionalidad del servicio. Para seguir, abre AppCommissioningService
en java/commissioning
.
Agregamos las siguientes importaciones a las APIs del SDK de Home Mobile:
import com.google.android.gms.home.matter.commissioning.CommissioningCompleteMetadata import com.google.android.gms.home.matter.commissioning.CommissioningRequestMetadata import com.google.android.gms.home.matter.commissioning.CommissioningService
AppCommissioningService
también incluye bibliotecas del repositorio de Matter (connectedhomeip
):
import com.google.home_sample_app_for_matter.chip.ChipClient
Por último, el servicio incluye importaciones compatibles con corrutinas de Hilt y Kotlin.
A continuación, creamos el constructor y configuramos algunos aspectos, incluido el commissioningServiceDelegate
, que usaremos para informarle a los Servicios de Google Play cuando se complete la asignación.
private lateinit var commissioningServiceDelegate: CommissioningService ... commissioningServiceDelegate = CommissioningService.Builder(this).setCallback(this).build()
Ahora es el momento de agregar las funciones de asignación.
Paso 2: Anula onCommissioningRequested
Para asignar dispositivos a la estructura de desarrollo de la app, completa los siguientes pasos:
- Abre
AppCommissioningService
enjava/commissioning
. - Ubica la función
onCommissioningRequested()
. Proporcionamos un mensaje de registro que imprimeCommissioningRequestMetadata
. Reemplaza el comentario// CODELAB: onCommissioningRequested()
para iniciar la corrutinaserviceScope
y obtenerdeviceId
.// Perform commissioning on custom fabric for the sample app. serviceScope.launch { val deviceId = devicesRepository.incrementAndReturnLastDeviceId()
- Realice la puesta en marcha. En este paso, podemos pasar la información del dispositivo que se muestra en el objeto CommissioningRequestMetadata.
ChipClient
usa esta información de metadatos para crear un canal seguro entre la app de GHSA para Matter y tu dispositivo.Timber.d("Commissioning: App fabric -> ChipClient.establishPaseConnection(): deviceId [${deviceId}]") chipClient.awaitEstablishPaseConnection( deviceId, metadata.networkLocation.ipAddress.hostAddress!!, metadata.networkLocation.port, metadata.passcode) Timber.d("Commissioning: App fabric -> ChipClient.commissionDevice(): deviceId [${deviceId}]") chipClient.awaitCommissionDevice(deviceId, null)
- Usa
commissioningServiceDelegate
para informar a los Servicios de Google Play que se completó la asignación. En.sendCommissioningComplete()
, pasa CommissioningCompleteMetadata.Timber.d("Commissioning: Calling commissioningServiceDelegate.sendCommissioningComplete()") commissioningServiceDelegate .sendCommissioningComplete( CommissioningCompleteMetadata.builder().setToken(deviceId.toString()).build()) .addOnSuccessListener { Timber.d("Commissioning: OnSuccess for commissioningServiceDelegate.sendCommissioningComplete()") } .addOnFailureListener { ex -> Timber.e(ex, "Commissioning: Failed to send commissioning complete.", ex) } }
Ejecuta la app
Ahora que todo el código necesario está en uso para la asignación de nuestra tela local, es momento de probarlo. Elige tu dispositivo Android y ejecuta la app. En la pantalla principal, presiona Agregar dispositivo y completa los pasos que se solicitan para el dispositivo.
Cuando se complete la asignación, tu dispositivo participará en dos tejidos: el de Android local y el de desarrollo local. Cada tela tiene su propio conjunto de credenciales y un ID de tela único de 64 bits.
6. Controla dispositivos
Las comisiones a una estructura de desarrollo te permiten usar las bibliotecas del repositorio de Matter (connectedhomeip
) para controlar dispositivos desde la app de ejemplo.
Creamos algunas clases auxiliares para facilitar el acceso a los clústeres del dispositivo y el envío de comandos. Para obtener más información, abre ClustersHelper
en java/clusters
. Este asistente de singleton importa las siguientes bibliotecas para acceder a la información del dispositivo:
import chip.devicecontroller.ChipClusters import chip.devicecontroller.ChipStructs
Podemos usar esta clase para obtener el clúster de encendido y apagado de un dispositivo y, luego, llamar a .toggle
:
suspend fun toggleDeviceStateOnOffCluster(deviceId: Long, endpoint: Int) { Timber.d("toggleDeviceStateOnOffCluster())") val connectedDevicePtr = try { chipClient.getConnectedDevicePointer(deviceId) } catch (e: IllegalStateException) { Timber.e("Can't get connectedDevicePointer.") return } return suspendCoroutine { continuation -> getOnOffClusterForDevice(connectedDevicePtr, endpoint) .toggle( object : ChipClusters.DefaultClusterCallback { override fun onSuccess() { continuation.resume(Unit) } override fun onError(ex: Exception) { Timber.e("readOnOffAttribute command failure: $ex") continuation.resumeWithException(ex) } }) } }
Activar o desactivar un dispositivo
Después de encargar un dispositivo, la carga útil que se muestra en CommissioningResult se agrega a DataStore. Esto le da a nuestra app acceso a la información del dispositivo que podemos usar para enviar comandos.
Las apps de Matter son controladas por eventos. Cuando se inicializa la pila de Matter, los servicios del clúster detectan los mensajes entrantes. Una vez que se encarga un dispositivo, los clientes de Matter envían comandos a través del canal operativo seguro que se estableció durante la asignación del dispositivo.
En el dispositivo, los paquetes se validan, se desencriptan y, luego, se envían con una devolución de llamada. Las funciones de devolución de llamada incluyen EndpointId, ClusterId y AttributeId, a las que se puede acceder desde attributePath
. Por ejemplo, este código se puede implementar en un dispositivo Matter:
void MatterPostAttributeChangeCallback(const chip::app::ConcreteAttributePath & attributePath, uint8_t mask, uint8_t type, uint16_t size, uint8_t * value) { // handle callback ClusterId clusterId = attributePath.mClusterId; AttributeId attributeId = attributePath.mAttributeId; }
En los próximos pasos, usarás el SDK de Matter y ClustersHelper
para activar o desactivar un dispositivo.
- Ve a
DeviceViewModel
enjava/screens/device
. - Ubica la función
updateDeviceStateOn
. - Reemplaza el comentario
// CODELAB: toggle
por el código para llamar aclustersHelper
y, luego, actualiza el repositorio del dispositivo:Timber.d("Handling real device") try { clustersHelper.setOnOffDeviceStateOnOffCluster(deviceUiModel.device.deviceId, isOn, 1) devicesStateRepository.updateDeviceState(deviceUiModel.device.deviceId, true, isOn) } catch (e: Throwable) { Timber.e("Failed setting on/off state") }
Se llama a esta función desde DeviceFragment
:
// Change the on/off state of the device binding.onoffSwitch.setOnClickListener { val isOn = binding.onoffSwitch.isChecked viewModel.updateDeviceStateOn(selectedDeviceViewModel.selectedDeviceLiveData.value!!, isOn) }
Ejecuta la app
Ejecuta la app para volver a cargar las actualizaciones. En la pantalla principal, activa o desactiva el dispositivo.
7. Compartir dispositivos con otros ecosistemas
En la especificación de Matter, compartir un dispositivo se conoce como flujo de varios administradores.
En los pasos anteriores, aprendimos que el SDK para dispositivos móviles de la casa permite asignar dispositivos a la estructura local de Android y también a una estructura de desarrollo para la app de ejemplo. Este es un ejemplo de flujo multiadministrador, en el que los dispositivos se pueden asignar a más de una estructura.
Es posible que quieras compartir dispositivos con más telas, especialmente si se trata de un grupo familiar en el que las personas tienen sus propias preferencias con respecto a las aplicaciones y plataformas.
El SDK para dispositivos móviles de Home proporciona esta funcionalidad en la API de ShareDeviceRequest, lo que te permite hacer lo siguiente:
- Abre un período de comisión temporal para los dispositivos.
- Cambia el estado de los dispositivos para que se puedan asignar a otra estructura.
- Controla tus dispositivos desde otras apps y ecosistemas.
En los próximos pasos, usarás el SDK para dispositivos móviles de Home a fin de compartir dispositivos.
Paso 1: Crea un selector de actividades de GPS
Al igual que el Selector de actividades de comisión que creamos cuando nos encargamos de un tejido de desarrollo, creamos un selector de actividad de dispositivos compartidos para controlar IntentSender
desde la API de CommissioningClient.
- Abre
DeviceFragment
en la carpetajava/screens/device/
. - Reemplaza el comentario
// CODELAB: shareDeviceLauncher definition
por el siguiente código para registrar y controlar el resultado de la actividad.shareDevice()
:shareDeviceLauncher = registerForActivityResult(ActivityResultContracts.StartIntentSenderForResult()) { result -> // Share Device Step 5. // The Share Device activity in GPS (step 4) has completed. val resultCode = result.resultCode if (resultCode == RESULT_OK) { Timber.d("ShareDevice: Success") viewModel.shareDeviceSucceeded(selectedDeviceViewModel.selectedDeviceLiveData.value!!) } else { viewModel.shareDeviceFailed( selectedDeviceViewModel.selectedDeviceLiveData.value!!, resultCode) } }
Paso 2: Revisa los objetos LiveData
La devolución de llamada exitosa de la API de .shareDevice()
proporciona la IntentSender
que se usará para iniciar la actividad del dispositivo compartido en los Servicios de Google Play. En el DeviceViewModel
, creamos dos objetos LiveData para informar sobre el resultado de esta llamada a la API:
_shareDeviceStatus
para realizar un seguimiento deTaskStatus
// The current status of the share device action. viewModel.shareDeviceStatus.observe(viewLifecycleOwner) { status -> val isButtonEnabled = status !is InProgress updateShareDeviceButton(isButtonEnabled) if (status is TaskStatus.Failed) { showAlertDialog(errorAlertDialog, status.message, status.cause!!.toString()) } }
_shareDeviceIntentSender
para controlar el resultado de la llamada a.sharedevice()
.viewModel.shareDeviceIntentSender.observe(viewLifecycleOwner) { sender -> Timber.d("shareDeviceIntentSender.observe is called with [${intentSenderToString(sender)}]") if (sender != null) { // Share Device Step 4: Launch the activity described in the IntentSender that // was returned in Step 3 (where the viewModel calls the GPS API to commission // the device). Timber.d("ShareDevice: Launch GPS activity to share device") shareDeviceLauncher.launch(IntentSenderRequest.Builder(sender).build()) viewModel.consumeShareDeviceIntentSender() } }
En los próximos pasos, usaremos estos objetos de LiveData en nuestra llamada a la API .shareDevice()
.
Paso 3: Llama a la API
Ahora es el momento de iniciar una tarea para compartir un dispositivo.
- Abre
DeviceViewModel.kt
en la carpetajava/screens/device/
. - Ubica la función
shareDevice()
. Reemplaza el comentario// CODELAB: shareDevice
por ShareDeviceRequest. ElDeviceDescriptor
proporciona información específica sobre el dispositivo, como el ID de proveedor, el ID del producto y el tipo de dispositivo. En este ejemplo, codificamos los valores de forma fija.Timber.d("ShareDevice: Setting up the IntentSender") val shareDeviceRequest = ShareDeviceRequest.builder() .setDeviceDescriptor(DeviceDescriptor.builder().build()) .setDeviceName("temp device name")
- Establece el parámetro CommissioningWindow y los parámetros. En este punto, el período de comisión temporal está abierto en el dispositivo.
.setCommissioningWindow( CommissioningWindow.builder() .setDiscriminator(Discriminator.forLongValue(DISCRIMINATOR)) .setPasscode(SETUP_PIN_CODE) .setWindowOpenMillis(SystemClock.elapsedRealtime()) .setDurationSeconds(OPEN_COMMISSIONING_WINDOW_DURATION_SECONDS.toLong()) .build()) .build()
- Llama a
.getCommissioningClient()
, solo que esta vez, usa la API de.shareDevice()
. La devolución de llamada exitosa de la API decommissioningClient.shareDevice()
proporciona el IntentSender que se usará para iniciar la actividad del dispositivo de uso compartido en Servicios de Google Play.Matter.getCommissioningClient(activity) .shareDevice(shareDeviceRequest)
- Para completar nuestra función
shareDevice
, agregaaddOnSuccessListener
yaddOnFailureListener
, y publica en los objetos LiveData:.addOnSuccessListener { result -> Timber.d("ShareDevice: Success getting the IntentSender: result [${result}]") // Communication with fragment is via livedata _backgroundWorkAlertDialogAction.postValue(BackgroundWorkAlertDialogAction.Hide) _shareDeviceIntentSender.postValue(result) } .addOnFailureListener { error -> Timber.e(error) _backgroundWorkAlertDialogAction.postValue(BackgroundWorkAlertDialogAction.Hide) _shareDeviceStatus.postValue( TaskStatus.Failed("Setting up the IntentSender failed", error)) }
Después de usar el remitente, se debe llamar a consumeShareDeviceIntentSender
para evitar recibirlo nuevamente después de un cambio de configuración.
/** * Consumes the value in [_shareDeviceIntentSender] and sets it back to null. Needs to be called * to avoid re-processing an IntentSender after a configuration change where the LiveData is * re-posted. */ fun consumeShareDeviceIntentSender() { _shareDeviceIntentSender.postValue(null) }
Ejecuta la app
Para compartir tu dispositivo Matter con otros ecosistemas, deberás tener instalada otra plataforma en tu dispositivo Android. Creamos otra instancia de la app de ejemplo que puedes usar como comisionado de destino.
Una vez que hayas instalado el comisionador de destino en tu dispositivo Android, verifica que puedes compartir tu dispositivo Matter. La aplicación de comisiones objetivo está etiquetada como GHSAFM-TC.
Ahora tus dispositivos pueden participar en tres tejidos:
- Tela local de Android.
- Tu tejido de desarrollo (esta app).
- Esta tercera tela con la que acabas de compartir el dispositivo.
8. Próximos pasos
Felicitaciones
¡Felicitaciones! Completaste correctamente este codelab y aprendiste a encargar y compartir dispositivos con el SDK de Home Mobile.
Si tienes problemas con la app de ejemplo, intenta completar los pasos para verificar el entorno:
Si tienes preguntas sobre el uso de la app de ejemplo o descubres un error de código, puedes enviar problemas a la Herramienta de seguimiento de errores en el repositorio de GitHub:
Para obtener orientación oficial de Google sobre preguntas técnicas, usa el Foro para desarrolladores de casas inteligentes:
Para obtener asistencia técnica de la comunidad, usa la etiqueta google-smart-home
en Stack Overflow: