1. Olá!
Criado para unificar os padrões de IoT, o Matter conecta dispositivos de casa inteligente em vários ecossistemas, como o Google Home, Zigbee, Bluetooth Mesh, Z-Wave e muito mais.
Os dispositivos móveis são um ponto central de interação com os dispositivos de casa inteligente. Se você quer criar seus próprios apps Android para oferecer suporte aos dispositivos Matter, podemos ajudar você a começar rapidamente.
O app de exemplo do Google Home para o Matter (GHSA for Matter) mostra as APIs do SDK do Google Mobile para dispositivos móveis, permitindo que os usuários comissionem e compartilhem dispositivos. Você também pode usar o app de exemplo como uma ferramenta de aprendizado para entender melhor os principais conceitos do Matter e depurar e resolver problemas com esses dispositivos.
Atividades deste laboratório
Neste codelab, você vai fazer o download do código-fonte do app de exemplo e aprender a usar o SDK do Home Mobile para comissionar e compartilhar dispositivos. Você também aprenderá a usar as bibliotecas de cluster e de comissionamento do repositório Matter (connectedhomeip
).
Depois de fazer o download do app de exemplo, analisaremos o código-fonte no Android Studio e implementaremos as seguintes APIs do SDK do Google Mobile:
Você também vai aprender mais sobre os conceitos de comissionamento, tecidos do Matter e como controlar dispositivos Matter.
O que é necessário
Antes de começar, siga estas etapas:
- Leia o Guia de exemplo de app Google Home para o caso.
- Faça o download do Android Studio.
- Ter um dispositivo Android O (8.1, API de nível 27) ou mais recente disponível para teste. Para garantir que o dispositivo tenha o suporte mais recente ao Matter, consulte o guia Módulos e serviços do Matter.
- Crie um dispositivo Matter com recursos de ativação/desativação. Este app de exemplo funciona com um dispositivo virtual e um ESP32.
- Crie um dispositivo virtual Matter com o app
rootnode_dimmablelight_bCwGYSDpoe
. Ao Criar uma integração do Matter no Console do desenvolvedor inicial, use0xFFF1
como seu ID de fornecedor e0x8000
como seu ID do produto. - Crie um dispositivo Espressif com o
all-clusters-app
. Ao criar uma integração do Matter no Console do desenvolvedor do Google Home, use0xFFF1
como seu ID de fornecedor e0x8001
como seu ID do produto.
- Crie um dispositivo virtual Matter com o app
- Veja como configurar o Google Play Services.
Você não precisa de um hub, como o Google Nest Hub (segunda geração), para comissionar e controlar dispositivos com o app de exemplo.
2. Preparativos
O repositório do app de exemplo do GitHub inclui bibliotecas de terceiros do repositório Matter (connectedhomeip
). Essas bibliotecas nativas têm mais de 50 MB e exigem o uso do Git File Storage Storage (LFS grande).
O app inicial do codelab está localizado na ramificação codelab
. Para começar a trabalhar com o código-fonte do codelab, faça o download do arquivo ZIP. Esse ZIP inclui as bibliotecas nativas do SDK do Matter sem a necessidade do Git LFS:
Você usará esse arquivo ZIP codelab
para criar uma amostra em funcionamento.
Versões do codelab
A ramificação codelab
é marcada com a versão 1.2.2 do app de exemplo. Para comparar suas atualizações em cada etapa, você pode fazer o download do código-fonte completo desta versão.
Se você quiser clonar o repositório do GitHub, siga as instruções no arquivo README do aplicativo de amostra.
Dependências
Orientaremos você no código-fonte necessário para compartilhar e encomendar dispositivos, mas talvez seja importante conhecer as seguintes dependências antes de começar:
- SDK de dispositivos móveis para casa.
implementation 'com.google.android.gms:play-services-home:16.0.0'
- Bibliotecas do SDK do Matter.
// Native libs implementation fileTree(dir: "third_party/connectedhomeip/libs", include: ["*.jar", "*.so"])
- Material Design. Para saber mais, consulte MDC-103 Android: temas do Material Design com cor, elevação e tipo (Kotlin) e Material Theme Builder (links em inglês).
implementation 'com.google.android.material:material:1.5.0'
- Proto DataStore, usado para manter os dados do app. Os repositórios e serializadores do Datastore são armazenados em
java/data
, incluindo esquemas para dispositivos e preferências do usuário. Para saber mais sobre o DataStore, consulte Como trabalhar com o 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 manter os dados e oferecer suporte à injeção de dependência.
kapt 'com.google.dagger:hilt-compiler:2.41' implementation 'com.google.dagger:hilt-android:2.41'
Código-fonte
A interface do usuário e a maioria das funcionalidades já foram criadas para você.
Neste codelab, vamos adicionar a funcionalidade Matter aos seguintes arquivos:
java/commissioning/AppCommissioningService
: permite encomendar dispositivos para a infraestrutura de desenvolvimentojava/screens/HomeFragment
ejava/screens/HomeViewModel.kt
: inclui a funcionalidade de comissionamento do Home Mobile SDKjava/screens/DeviceViewModel
: inclui as chamadas da API Share Device.
Cada arquivo é comentado com o bloco de código que você modificará, por exemplo:
// CODELAB: add commissioningFunction()
Isso permite que você localize rapidamente a seção correspondente no codelab.
3. Comissão para o Google
Antes que você possa controlar os dispositivos e permitir que eles se comuniquem entre si no mesmo tecido, eles precisam ser encomendados por um comissário, que neste caso é o aplicativo de exemplo do Google Home para a matéria.
É importante entender os seguintes conceitos sobre a comissão da Matter:
- Os tecidos permitem que os dispositivos se comuniquem entre si.
- Os tecidos mantêm um conjunto compartilhado de credenciais exclusivas.
- Os ecossistemas são responsáveis por emitir certificados raiz confiáveis, atribuir IDs de tecido e IDs de nó exclusivos. Um ecossistema é o serviço de back-end de um comissário, por exemplo, o Home Graph do ecossistema do Google Home.
- Os dispositivos podem ser encomendados a mais de uma malha (recurso multiadministrador).
Para comissionar um dispositivo, você precisa usar a API CommissioningClient. Uma chamada para .commissionDevice()
retorna um IntentSender, que inicia a atividade adequada no Google Play Services:
interface CommissioningClient { Task<IntentSender> commissionDevice(CommissioningRequest request); }
Nas próximas seções, abordaremos o código mínimo necessário para comissionar dispositivos no conjunto do Google.
Etapa 1: acesso rápido às atividades
Para processar o IntentSender
do CommissioningClient
, você pode usar um 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) } }
Etapa 2: função de comissionamento
Veja um exemplo básico que usa a API CommissioningClient para comissionar um dispositivo no tecido do Google.
- O processo de comissionamento começa com a função
commissionDevice()
. Primeiro, umCommissioningRequest
é definido. Com essa configuração padrão, os dispositivos são encomendados apenas para a infraestrutura local do Android. Matter
é o ponto de entrada do SDK do Home Mobile. Na próxima chamada,.getCommissioningClient
recebe um CommissioningClient dethis
(Activity)..commissionDevice()
aceitaCommissioningRequest
.- Por fim,
.addOnSuccessListener
é chamado para processar oCommissioningResult
e iniciar a atividade do dispositivo de comissão do Google Play Services (GPS).
private fun commissionDevice() { val request: CommissioningRequest = CommissioningRequest.builder().build() Matter.getCommissioningClient(this) .commissionDevice(request) .addOnSuccessListener { result -> commissioningLauncher.launch(IntentSenderRequest.Builder(result).build()) } }
O Android Fabric local pode ser aproveitado por meio de configurações do Android para simplificar o processo de comissionamento de seus dispositivos para outros tecidos.
Em seguida, você vai aprender a comissionar um dispositivo para uma malha de desenvolvimento.
Para uma visão geral da interface do usuário durante o processo de comissionamento, consulte o Guia de amostra do app Google Home para o caso.
4. Comissão para uma malha de desenvolvimento
Os dispositivos podem ser encomendados a mais de um tecido. Para gerenciar pares confiáveis, os dispositivos armazenam um FabricTable
que contém vários membros do FabricInfo
, por exemplo:
- Identificação do tecido
- ID do nó atribuído pelo Fabric ao dispositivo
- ID do fornecedor
- ID do Fabric
- Credenciais operacionais do dispositivo
O gerenciador de domínio administrativo (ADM) define as credenciais da malha. No cenário anterior, o Google Play Services é o ecossistema que atua como uma autoridade de certificação (CA, na sigla em inglês) raiz confiável. Quando você encomenda dispositivos para a malha local do Android, cada dispositivo inclui o mesmo conjunto de credenciais e o mesmo conjunto de CAs.
Serviços de comissão personalizados
Para comissionar no tecido do Android local, usamos os parâmetros padrão para criar o CommissioningRequest
na API CommissioningClient:
val request: CommissioningRequest = CommissioningRequest.builder().build()
Se quiser controlar e gerenciar novos dispositivos a partir do aplicativo, crie uma malha de desenvolvimento local e receba as credenciais operacionais para encomendar dispositivos. Nesse cenário, seu app se torna um ecossistema único e independente que atribui aos dispositivos as credenciais de nó adequadas.
Você pode informar ao SDK do Google Home Mobile que deseja comissionar dispositivos para seu tecido passando um serviço personalizado para o CommissioningRequest:
class CommissioningRequest { static CommissioningRequest.Builder builder(); class Builder { Builder setCommissioningService(@Nullable ComponentName commissioningService); CommissioningRequest build(); } }
Nas próximas etapas, modificaremos a função commissionDevice()
para usar um serviço personalizado. Também adicionaremos um inicializador de atividade ao fragmento inicial e usaremos os objetos LiveData para gerenciar o fluxo da API.
Etapa 1: criar um acesso rápido às atividades do GPS
Primeiro, vamos criar um acesso rápido de atividades para processar o IntentSender
da API CommissioningClient.
- Abra
HomeFragment
na pastajava/screens/home/
. - Substitua o comentário
// CODELAB: commissionDeviceLauncher declaration
pela seguinte declaração:// The ActivityResult launcher that launches the "commissionDevice" activity in Google Play // Services. private lateinit var commissionDeviceLauncher: ActivityResultLauncher<IntentSenderRequest>
- Substitua o comentário
// CODELAB: commissionDeviceLauncher definition
pelo seguinte código para registrar e gerenciar o resultado da atividade de ativação: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) } } ```
Etapa 2: criar objetos LiveData
O callback da API .commissionDevice()
fornece o IntentSender
a ser usado para iniciar a atividade do dispositivo da comissão no Google Play Services. No HomeViewModel
, criaremos dois objetos LiveData para gerar relatórios sobre o resultado dessa chamada de API:
commissionDeviceStatus
para rastrear oTaskStatus
.commissionDeviceIntentSender
para processar o resultado da chamada.commissionDevice()
. Esse objeto LiveData iniciará oActivityLauncher
que acabamos de criar e exibirá a atividade do dispositivo da comissão do GPS para o usuário.
- No
private fun setupObservers()
, substitua o comentário// CODELAB: commissionDeviceStatus
pelo seguinte observador:// The current status of the share device action. viewModel.commissionDeviceStatus.observe(viewLifecycleOwner) { status -> Timber.d("commissionDeviceStatus.observe: status [${status}]") }
- Em seguida, substitua o comentário
// CODELAB: commissionDeviceIntentSender
pelo seguinte 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() } }
Etapa 3: chamar a API
Agora que criamos o código para processar o fluxo da API, é hora de chamar a API, transmitir um serviço personalizado (que será definido na próxima etapa) e postar nos objetos LiveData.
- Abra
HomeViewModel.kt
na pastajava/screens/home/
. - Substitua o comentário
// CODELAB: commissionDevice
pelo seguintecommissionDeviceRequest
.setCommissioningService
vinculaAppCommissioningService
a uma instância deCommissioningService
, retornada em uma função de callback. Quando você passa um serviço personalizado, o SDK do Google Home para dispositivos móveis primeiro encomenda os dispositivos para a malha do Google e, em seguida, envia o payload de integração para oAppCommissioningService
.fun commissionDevice(context: Context) { _commissionDeviceStatus.postValue(TaskStatus.InProgress) val commissionDeviceRequest = CommissioningRequest.builder() .setCommissioningService(ComponentName(context, AppCommissioningService::class.java)) .build()
- Chame
.getCommissioningClient()
e, em seguida, chame.commissionDevice()
.Matter.getCommissioningClient(context) .commissionDevice(commissionDeviceRequest)
Para concluir nossa função commissionDevice
, adicione um addOnSuccessListener
e um addOnFailureListener
e publique nos 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) } }
Depois de usar o remetente, consumeCommissionDeviceIntentSender()
precisa ser chamado para evitar o recebimento do remetente novamente após uma mudança de configuração.
/** * 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. Criar um CommissioningService
Na função commissionDevice()
, solicitamos o recebimento de um CommissioningService da API CommissioningClient. Nesse fluxo, a API CommissioningClient encomenda dispositivos para a malha local do Android primeiro e depois retorna um callback que inclui o objeto CommissioningRequestMetadata:
public interface CommissioningService { interface Callback { void onCommissioningRequested(CommissioningRequestMetadata metadata); } }
Agora, precisamos herdar o CommissioningService.Callback e fornecer a funcionalidade necessária para ativar dispositivos no nosso app de exemplo. Veja um exemplo de implementação 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()) } }
Etapa 1: explorar o AppCommissioningService personalizado
Para ajudar você a começar, já definimos a estrutura de classes básica para nosso CommissioningService personalizado. Esta é uma visão geral rápida da funcionalidade do serviço. Para acompanhar, abra AppCommissioningService
em java/commissioning
.
Adicionamos as seguintes importações às APIs Mobile SDK:
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
também inclui bibliotecas do repositório Matter (connectedhomeip
):
import com.google.home_sample_app_for_matter.chip.ChipClient
Por fim, o serviço inclui importações compatíveis com Hilt e corrotinas de Kotlin.
Em seguida, criamos o construtor e definimos alguns itens, incluindo o commissioningServiceDelegate
, que usaremos para informar ao Google Play Services quando o comissionamento estiver concluído.
private lateinit var commissioningServiceDelegate: CommissioningService ... commissioningServiceDelegate = CommissioningService.Builder(this).setCallback(this).build()
Agora é hora de adicionar as funções de comissionamento.
Etapa 2: substituir onCommissioningRequested
Para encomendar dispositivos para a malha de desenvolvimento do app, siga estas etapas:
- Abrir
AppCommissioningService
emjava/commissioning
. - Localize a função
onCommissioningRequested()
. Fornecemos uma mensagem de registro que mostra oCommissioningRequestMetadata
. Substitua o comentário// CODELAB: onCommissioningRequested()
para iniciar a corrotinaserviceScope
e receber odeviceId
.// Perform commissioning on custom fabric for the sample app. serviceScope.launch { val deviceId = devicesRepository.incrementAndReturnLastDeviceId()
- Realize o comissionamento. Para esta etapa, podemos transmitir as informações do dispositivo retornadas no objeto CommissioningRequestMetadata. O
ChipClient
usa essas informações para criar um canal seguro entre o app GHSA for Matter e seu 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)
- Use o
commissioningServiceDelegate
para informar ao Google Play Services que o comissionamento foi concluído. Em.sendCommissioningComplete()
, transmita 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) } }
Executar o app
Agora que todo o código necessário está pronto para ser comissionado com nossa malha local, é hora de testá-lo. Escolha seu dispositivo Android e execute o app. Na tela inicial, toque em Adicionar dispositivo e siga as etapas para ativar o dispositivo.
Agora, quando o comissionamento for concluído, o dispositivo participará de dois tecidos: o tecido local do Android e o tecido de desenvolvimento local. Cada tecido tem o próprio conjunto de credenciais e um ID de tecido exclusivo de 64 bits.
6. Controlar dispositivos
A ativação de uma malha de desenvolvimento permite que você use as bibliotecas do repositório Matter (connectedhomeip
) para controlar dispositivos do app de amostra.
Criamos algumas classes auxiliares para facilitar o acesso aos clusters do dispositivo e o envio de comandos. Para saber mais, abra ClustersHelper
em java/clusters
. Esse auxiliar de Singleton importa as seguintes bibliotecas para acessar as informações do dispositivo:
import chip.devicecontroller.ChipClusters import chip.devicecontroller.ChipStructs
Podemos usar essa classe para receber o cluster de ativação/desativação de um dispositivo e chamar .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) } }) } }
Alternar um dispositivo
Depois de comissionar um dispositivo, o payload retornado em CommissioningResult é adicionado ao DataStore. Isso permite que nosso app acesse informações do dispositivo que podem ser usadas para enviar comandos.
Os apps Matter são orientados por eventos. Quando a pilha do Matter é inicializada, os serviços do cluster detectam mensagens recebidas. Quando um dispositivo é comissionado, os clientes do Matter enviam comandos pelo canal operacional seguro estabelecido durante a ativação do dispositivo.
No dispositivo, os pacotes são validados, descriptografados e enviados com um callback. As funções de callback incluem EndpointId, ClusterId e AttributeId, que podem ser acessadas no attributePath
. Por exemplo, este código pode ser implementado em um 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; }
Nas próximas etapas, você vai usar o SDK do Matter e o ClustersHelper
para alternar um dispositivo.
- Vá para
DeviceViewModel
emjava/screens/device
. - Localize a função
updateDeviceStateOn
. - Substitua o comentário
// CODELAB: toggle
pelo código para chamarclustersHelper
e atualize o repositório do 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 função é chamada a partir de DeviceFragment
:
// Change the on/off state of the device binding.onoffSwitch.setOnClickListener { val isOn = binding.onoffSwitch.isChecked viewModel.updateDeviceStateOn(selectedDeviceViewModel.selectedDeviceLiveData.value!!, isOn) }
Executar o app
Execute o app para recarregar as atualizações. Na tela inicial, ative e desative o dispositivo.
7. Compartilhar dispositivos com outros ecossistemas
O compartilhamento de um dispositivo é chamado de fluxo de vários administradores na especificação do Matter.
Nas etapas anteriores, aprendemos que o SDK do Google Mobile para dispositivos móveis permite encomendar dispositivos para a malha local do Android e também para uma malha de desenvolvimento do app de exemplo. Este é um exemplo de fluxo de vários administradores, em que os dispositivos podem ser encomendados a mais de uma malha.
Agora, você pode querer compartilhar dispositivos com ainda mais tecidos, especialmente se esta for uma família em que as pessoas têm suas próprias preferências em relação a aplicativos e plataformas.
O SDK do Mobile para dispositivos móveis oferece essa funcionalidade na API ShareDeviceRequest, que permite:
- Abra uma janela de comissionamento temporária para os dispositivos.
- Altere o estado dos dispositivos, permitindo que eles sejam encomendados a outro tecido.
- Controle seus dispositivos a partir de outros apps e ecossistemas.
Nas próximas etapas, você usará o SDK do Google Home para dispositivos móveis para compartilhar dispositivos.
Etapa 1: criar um acesso rápido às atividades do GPS
Assim como o inicializador de atividades de comissionamento, criado quando encomendamos um tecido de desenvolvimento, criamos um iniciador de atividade de compartilhamento de dispositivo para gerenciar o IntentSender
da API CommissioningClient.
- Abra
DeviceFragment
na pastajava/screens/device/
. - Substitua o comentário
// CODELAB: shareDeviceLauncher definition
pelo seguinte código para registrar e processar o resultado da atividade.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) } }
Etapa 2: revisar objetos LiveData
O callback da API .shareDevice()
fornece o IntentSender
a ser usado para iniciar a atividade Compartilhar dispositivo no Google Play Services. No DeviceViewModel
, criamos dois objetos LiveData para gerar relatórios sobre o resultado dessa chamada de API:
_shareDeviceStatus
para rastrear oTaskStatus
.// 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 processar o resultado da chamada.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() } }
Nas próximas etapas, vamos usar esses objetos LiveData na nossa chamada da API .shareDevice()
.
Etapa 3: chamar a API
Agora é hora de iniciar uma tarefa de compartilhamento de dispositivo.
- Abra
DeviceViewModel.kt
na pastajava/screens/device/
. - Localize a função
shareDevice()
. Substitua o comentário// CODELAB: shareDevice
pelo ShareDeviceRequest. ODeviceDescriptor
fornece informações específicas sobre o dispositivo, como o ID do fornecedor, o ID do produto e o deviceType. Neste exemplo, codificamos os valores.Timber.d("ShareDevice: Setting up the IntentSender") val shareDeviceRequest = ShareDeviceRequest.builder() .setDeviceDescriptor(DeviceDescriptor.builder().build()) .setDeviceName("temp device name")
- Defina CommissioningWindow e parâmetros. Neste ponto, a janela de comissionamento temporária está aberta no dispositivo.
.setCommissioningWindow( CommissioningWindow.builder() .setDiscriminator(Discriminator.forLongValue(DISCRIMINATOR)) .setPasscode(SETUP_PIN_CODE) .setWindowOpenMillis(SystemClock.elapsedRealtime()) .setDurationSeconds(OPEN_COMMISSIONING_WINDOW_DURATION_SECONDS.toLong()) .build()) .build()
- Chame
.getCommissioningClient()
, só que desta vez, use a API.shareDevice()
. O callback de sucesso da APIcommissioningClient.shareDevice()
fornece o IntentSender a ser usado para iniciar a atividade "Compartilhar dispositivo" no Google Play Services.Matter.getCommissioningClient(activity) .shareDevice(shareDeviceRequest)
- Para concluir a função
shareDevice
, adicione umaddOnSuccessListener
e umaddOnFailureListener
e publique nos 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)) }
Depois de usar o remetente, consumeShareDeviceIntentSender
precisa ser chamado para evitar o recebimento do remetente novamente após uma mudança de configuração.
/** * 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) }
Executar o app
Para compartilhar o dispositivo Matter com outros ecossistemas, é preciso ter outra plataforma instalada no dispositivo Android. Criamos outra instância do aplicativo de amostra que você pode usar como comissário de destino.
Depois de instalar o comissário de destino no dispositivo Android, verifique se é possível compartilhar o dispositivo Matter. O app de comissão do alvo é rotulado como GHSAFM-TC.
Seus dispositivos agora podem participar de três tecidos:
- O tecido local do Android.
- Seu tecido de desenvolvimento (este app).
- Este terceiro tecido com que você acabou de compartilhar o dispositivo.
8. Próximas etapas
Parabéns
Parabéns! Você concluiu este codelab e aprendeu a comissionar e compartilhar dispositivos usando o SDK do Google Home para dispositivos móveis.
Se você tiver problemas com o app de exemplo, siga as etapas abaixo para verificar o ambiente:
Se você tiver dúvidas sobre como usar o app de amostra ou descobrir um bug de código, envie os problemas para o Issue Tracker no repositório do GitHub:
- sample-apps-for-matter-android/issues (link em inglês)
Para receber orientações oficiais do Google sobre dúvidas técnicas, use o Fórum de desenvolvedores da casa inteligente:
- Fórum para desenvolvedores de casas inteligentes (em inglês)
Para receber suporte técnico da comunidade, use a tag google-smart-home
no Stack Overflow:
- Stack Overflow: google-smart-home (em inglês)