¡Atención! Pronto se lanzarán nuevos programas de vista previa para desarrolladores. Postúlate aquí y sé una de las primeras personas en probar herramientas nuevas y enviar comentarios.

Compilar una app de Android para Matter

1. Te damos la bienvenida

Matter, creado con el objetivo de unificar los estándares de IoT, conecta dispositivos de casa inteligente en varios ecosistemas, como Google Home, Zigbee, la malla Bluetooth, Z‐Wave y muchos más.

Los dispositivos móviles son un punto de interacción central con los dispositivos de casa inteligente. Si desea compilar sus propias aplicaciones para Android compatibles con dispositivos Matter, podemos ayudarlo a comenzar rápidamente.

La app de ejemplo de Google Home para Matter (GHSA for Matter) muestra las API del SDK de Home para dispositivos móviles, lo que permite a los usuarios encargar y compartir dispositivos. También puedes usar la app de ejemplo como herramienta de aprendizaje para comprender mejor los conceptos clave de Matter, así como una herramienta 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 de Home para dispositivos móviles a fin de encargar y compartir dispositivos. También aprenderás a usar las bibliotecas de asignación y agrupamiento en clústeres 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 API del SDK de Home para dispositivos móviles:

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:

No necesitas un concentrador, por ejemplo, un Google Nest Hub (2a generación), para encargar y controlar dispositivos con la app de ejemplo.

2. Prepárate

El repositorio de GitHub de la app de muestra incluye bibliotecas de terceros del repositorio de Matter (connectedhomeip). Estas bibliotecas nativas superan los 50 MB y requieren el uso de Git 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 ZIP incluye las bibliotecas nativas del SDK de Matter sin la necesidad de Git LFS:

Usarás este archivo ZIP codelab para compilar una muestra que funcione.

Versiones de Codelab

La rama codelab está etiquetada con la versión 1.2.2 de la app de muestra. Para comparar las actualizaciones mientras trabajas en cada paso, descarga 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 muestra.

Dependencias

Te guiaremos a través del código fuente que se requiere para compartir y poner en marcha los dispositivos, pero es posible que tengas en cuenta las siguientes dependencias antes de comenzar:

  • SDK de Home Mobile.
    implementation 'com.google.android.gms:play-services-home:16.0.0'
    
  • Bibliotecas del 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 para 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, usado para conservar los datos de las apps Los repositorios y los serializadores de Datastore se almacenan en java/data, incluidos los esquemas para los dispositivos y las preferencias del 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 los 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

Ya se creó la interfaz de usuario y la mayor parte de la funcionalidad para usted.

En este codelab, agregaremos la funcionalidad de Matter para los siguientes archivos:

  • java/commissioning/AppCommissioningService: Te permite asignar dispositivos a la estructura de desarrollo.
  • java/screens/HomeFragment y java/screens/HomeViewModel.kt: Incluyen la funcionalidad de puesta en marcha del SDK de Home para dispositivos móviles.
  • java/screens/DeviceViewModel: Incluye las llamadas a la API de Compartir dispositivo

Cada archivo se comenta con el bloque de código que modificarás, por ejemplo:

// CODELAB: add commissioningFunction()

De esta manera, podrás encontrar rápidamente la sección correspondiente del codelab.

3. Comisión ante Google

Para poder controlar los dispositivos y permitirles comunicarse entre sí dentro de la misma estructura, es necesario que los comisione un encargado, que en este caso es esta aplicación de muestra, la app de ejemplo de Google Home para Matter.

Es importante comprender los siguientes conceptos sobre la asignación de asuntos:

  • Las telas permiten que los dispositivos se comuniquen entre sí.
  • Las fábricas mantienen un conjunto compartido de credenciales únicas.
  • Los ecosistemas son responsables de emitir certificados raíz de confianza, asignar ID de tejido y asignar 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 una estructura (función de administrador múltiple).

Para poner en marcha 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, veremos el mínimo código necesario para encargar los 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

Aquí tienes un ejemplo básico que usa la API de CommissioningClient para encargar un dispositivo a la estructura de Google.

  1. El proceso de puesta en marcha comienza con la función commissionDevice(). Primero, se define un CommissioningRequest. Con esta configuración predeterminada, los dispositivos se encargan solo a la estructura local de Android.
  2. Matter es el punto de entrada del SDK de Home Mobile. En la próxima llamada, .getCommissioningClient obtiene un objeto CommissioningClient de this (actividad).
  3. .commissionDevice() acepta CommissioningRequest.
  4. Por último, se llama a .addOnSuccessListener para procesar CommissioningResult e iniciar la actividad del dispositivo de comisión de 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())
        }
}

Aprovecha Android Fabric local a través de la configuración de Android para simplificar el proceso de puesta en marcha sus dispositivos con otras telas.

A continuación, aprenderás cómo encargar un dispositivo a una estructura de desarrollo.

Para obtener una descripción general de la interfaz de usuario durante el proceso de asignación, consulte la Guía de ejemplo de la aplicación de Google Home para Matter.

4. Comisión a una estructura de desarrollo

Los dispositivos se pueden asignar a más de una tela. 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 del 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 autoridad certificada (CA) raíz de confianza. Cuando encargas los dispositivos a la estructura de Android local, cada dispositivo incluye el mismo conjunto de credenciales de fábrica y el mismo conjunto de CA.

Servicios de comisionados personalizados

A fin de encargar la estructura de Android local, 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 los 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 al SDK de Home Mobile que quieres encargar dispositivos a tu propia red. Para ello, pasa un servicio personalizado a CommissioningRequest:

class CommissioningRequest {
  static CommissioningRequest.Builder builder();

  class Builder {
    Builder setCommissioningService(@Nullable ComponentName commissioningService);

    CommissioningRequest build();
  }
}

En los siguientes pasos, modificaremos la función commissionDevice() para usar un servicio personalizado. También agregaremos un Launcher de actividad al fragmento de la página principal y usaremos objetos LiveData para administrar el flujo de API.

Paso 1: Crea un selector de actividad GPS

Primero, creemos un Launcher de actividad para controlar el IntentSender desde la API de CommissioningClient.

  1. Abre HomeFragment en la carpeta java/screens/home/.
  2. 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>
    
  3. 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 el 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 de TaskStatus.
  • commissionDeviceIntentSender para controlar el resultado de la llamada a .commissionDevice(). Este objeto LiveData iniciará el ActivityLauncher que acabamos de crear y mostrará la actividad del dispositivo de la comisión de GPS al usuario.
  1. 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}]")
    }
    
  2. A continuación, 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 manejar el flujo de API, es momento de llamar a la API, pasar un servicio personalizado (que definiremos en el siguiente paso) y publicar en nuestros objetos LiveData.

  1. Abre HomeViewModel.kt en la carpeta java/screens/home/.
  2. Reemplaza el comentario // CODELAB: commissionDevice por la siguiente commissionDeviceRequest. setCommissioningService vincula AppCommissioningService a una instancia CommissioningService, que se muestra en una función de devolución de llamada. Cuando pases un servicio personalizado, el SDK de Home para dispositivos móviles primero encargará los dispositivos a la estructura de Google y, luego, enviará la carga útil de integración a AppCommissioningService.
    fun commissionDevice(context: Context) {
      _commissionDeviceStatus.postValue(TaskStatus.InProgress)
    
      val commissionDeviceRequest =
          CommissioningRequest.builder()
              .setCommissioningService(ComponentName(context, AppCommissioningService::class.java))
              .build()
    
  3. Llama a .getCommissioningClient() y, luego, llama 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 de nuevo 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. Crear un objeto Service de comisión

En la función commissionDevice(), solicitamos obtener un CommissioningService de la API de CommissioningClient. En este flujo, la API de CommissioningClient encarga primero 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, heredaremos CommissioningService.Callback y proporcione la funcionalidad necesaria para encargar los dispositivos a nuestra app de muestra. 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 Service de comisión personalizado. A continuación, se incluye una breve descripción general de la funcionalidad del servicio. Para continuar, abre AppCommissioningService en java/commissioning.

Agregamos las siguientes importaciones para las API del SDK de Home para dispositivos móviles:

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 para admitir corrutinas de Hilt y Kotlin.

A continuación, creamos el constructor y configuramos algunos elementos, incluido el commissioningServiceDelegate, que usaremos para informarle a los Servicios de Google Play cuando se complete la puesta en marcha.

private lateinit var commissioningServiceDelegate: CommissioningService
...
commissioningServiceDelegate = CommissioningService.Builder(this).setCallback(this).build()

Ahora es momento de agregar las funciones de puesta en marcha.

Paso 2: Anula onCommissioningRequest

Para asignar dispositivos a la estructura de desarrollo de la app, completa los siguientes pasos:

  1. Abre AppCommissioningService en java/commissioning.
  2. Ubica la función onCommissioningRequested(). Proporcionamos un mensaje de registro que imprime el CommissioningRequestMetadata. Reemplaza el comentario // CODELAB: onCommissioningRequested() para iniciar la corrutina serviceScope y obtener la deviceId.
    // Perform commissioning on custom fabric for the sample app.
    serviceScope.launch {
      val deviceId = devicesRepository.incrementAndReturnLastDeviceId()
    
  3. Realizar la asignación Para este paso, podemos pasar la información del dispositivo que se muestra en el objeto CommissioningRequestMetadata. La 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)
    
  4. 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 requerido está en manos de nuestra estructura local, es momento de probarlo. Elige tu dispositivo Android y ejecuta la app. En la pantalla principal, presiona Agregar dispositivo y completa los pasos para enviárselo a tu dispositivo.

Cuando se completa la puesta en marcha, el dispositivo ahora participa en dos tejidos: el tejido local de Android y el tejido de desarrollo local. Cada tejido tiene su propio conjunto de credenciales y un ID de tejido único de 64 bits.

6. Controla dispositivos

La asignación a una estructura de desarrollo te permite usar las bibliotecas del repositorio de Matter (connectedhomeip) para controlar dispositivos desde la app de muestra.

Creamos algunas clases de ayuda para facilitar el acceso a clústeres de dispositivos 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 activación/desactivación 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 aplicación 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 Matter, los servicios de clúster detectan mensajes entrantes. Una vez que se realiza la asignación de un dispositivo, los clientes de Matter envían comandos a través del canal operativo seguro que se estableció durante la puesta en marcha del dispositivo.

En el dispositivo, los paquetes se validan, se desencriptan y, luego, se despachan con una devolución de llamada. Las funciones de devolución de llamada incluyen EndpointId, ClusterId y AttributeId, al 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.

  1. Ve a DeviceViewModel en java/screens/device.
  2. Ubica la función updateDeviceStateOn.
  3. Reemplaza el comentario // CODELAB: toggle por el código para llamar a clustersHelper 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")
        }
    

Esta función se llama 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 tus actualizaciones. En la pantalla principal, activa y desactiva el dispositivo.

7. Comparte dispositivos con otros ecosistemas

En la especificación de Matter, compartir un dispositivo se conoce como flujo de administrador múltiple.

En los pasos anteriores, aprendimos que el SDK de Home para dispositivos móviles permite asignar dispositivos a la estructura de Android local y también a una estructura de desarrollo para la aplicación de muestra. Este es un ejemplo de flujo de varios administradores, en el que los dispositivos se pueden asignar a más de una estructura.

Ahora, tal vez quiera compartir dispositivos con aún más tejidos, especialmente si se trata de una familia en la que las personas tienen sus propias preferencias en cuanto a aplicaciones y plataformas.

El SDK de Home para dispositivos móviles proporciona esta funcionalidad en la API de ShareDeviceRequest, lo que te permite hacer lo siguiente:

  1. Abre un período de asignación temporal para los dispositivos.
  2. Cambia el estado de tus dispositivos para que se puedan asignar a otra estructura.
  3. Controla tus dispositivos desde otras apps y ecosistemas.

En los próximos pasos, usarás el SDK de Home para dispositivos móviles a fin de compartir dispositivos.

Paso 1: Crea un selector de actividad GPS

De manera similar al iniciador de actividades de comisión que creamos cuando se encargó la construcción de una estructura de desarrollo, creamos un Launcher de actividad del dispositivo compartido para manejar el IntentSender desde la API de CommissioningClient.

  1. Abre DeviceFragment en la carpeta java/screens/device/.
  2. Reemplaza el comentario // CODELAB: shareDeviceLauncher definition por el siguiente código para registrar y controlar el resultado de la actividad de .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 el 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 de TaskStatus.
    // 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) { remitente -> Timber.d("shareDeviceIntentSender.observe se llama con [${intentSenderToString(sender)}]") if (sender != null) { // Compartir dispositivo Paso 4: Iniciar la actividad descrita en el IntentSender que // se mostró // en el Paso 3 (donde la vista de llamada llama a la API al dispositivo GPS) Timber.d("ShareDevice: Inicia la actividad de GPS para compartir el dispositivo") shareDeviceLauncher.launch(IntentSenderRequest.Builder(sender).build()) viewModel.consumeShareDeviceIntentSender() } } ```

En los próximos pasos, usaremos estos objetos de LiveData en nuestra llamada a la API de .shareDevice().

Paso 3: Llama a la API

Ahora tienes que iniciar una tarea para compartir el dispositivo.

  1. Abre DeviceViewModel.kt en la carpeta java/screens/device/.
  2. Ubica la función shareDevice(). Reemplaza el comentario // CODELAB: shareDevice por ShareDeviceRequest. El DeviceDescriptor proporciona información específica sobre el dispositivo, como el ID de proveedor, el ID de producto y el deviceType. En este ejemplo, codificamos los valores.
      Timber.d("ShareDevice: Setting up the IntentSender")
      val shareDeviceRequest =
          ShareDeviceRequest.builder()
              .setDeviceDescriptor(DeviceDescriptor.builder().build())
              .setDeviceName("temp device name")
    
  3. Configura CommissioningWindow y parameters. En este momento, 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()
    
  4. Llama a .getCommissioningClient(), solo esta vez, usa la API de .shareDevice(). La devolución de llamada exitosa de la API de commissioningClient.shareDevice() proporciona el IntentSender que se usará para iniciar la actividad del dispositivo compartido en los Servicios de Google Play.
    Matter.getCommissioningClient(activity)
        .shareDevice(shareDeviceRequest)
    
  5. Para completar nuestra función shareDevice, agrega addOnSuccessListener y addOnFailureListener, 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 de nuevo 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 muestra que puedes usar como responsable de destino.

Una vez que hayas instalado el encargado objetivo en tu dispositivo Android, verifica que puedes compartir tu dispositivo Matter. La aplicación de comisión encargada de destino tiene la etiqueta GHSAFM-TC.

Los dispositivos ahora pueden participar de tres formas:

  1. La tela de Android local.
  2. Tu tejido de desarrollo (esta aplicación).
  3. La 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 para dispositivos móviles.

Si tienes problemas con la app de ejemplo, intenta completar los pasos para verificar tu entorno:

Si tienes preguntas sobre el uso de la app de muestra 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: