Antes de usar qualquer uma das APIs Home para Android, é necessário inicializar a casa no
seu app. Nesta etapa, você vai criar uma instância singleton de
Home para o contexto local.
Apenas uma instância de Home deve estar ativa por vez.
Esse é o ponto de entrada para as APIs Home e também envolve declarar quais características e tipos de dispositivo você pretende usar com as APIs Device & Structure e Automation. Se você está começando a usar o ecossistema do Google Home e não sabe quais atributos ou tipos de dispositivo registrar, sugerimos alguns dos mais comuns neste guia.
Criar uma instância do Home
Para começar, importe estes pacotes para o app:
import android.content.Context
import com.google.home.FactoryRegistry
import com.google.home.HomeConfig
import com.google.home.Home
Para inicializar as APIs Home:
Acesse uma referência ao contexto
Application. Esse contexto não depende de nenhum ciclo de vida da atividade e vai durar enquanto o app estiver ativo. Para isso, chamegetApplicationContext()em umaActivityouService:val context = getApplicationContext()Crie uma instância
FactoryRegistrycom todos os atributos e tipos de dispositivo que você pretende usar no app.Para este guia, sugerimos alguns tipos comuns (tipos de dispositivo de luz, tomada, sensor, interruptor e termostato, traços de presença e do Assistente para automações), caso você não tenha certeza do que precisa. Para saber mais, consulte Registro de atributos e tipos de dispositivo.
val registry = FactoryRegistry( traits = listOf( AirQuality, AreaAttendanceState, AreaPresenceState, AssistantBroadcast, AssistantFulfillment, BooleanState, ColorControl, ExtendedColorControl, FlowMeasurement, IlluminanceMeasurement, LevelControl, Notification, OccupancySensing, OnOff, RelativeHumidityMeasurement, Switch, TemperatureMeasurement, Thermostat), types = listOf( AirQualitySensorDevice, ColorDimmerSwitchDevice, ColorTemperatureLightDevice, ContactSensorDevice, DimmableLightDevice, DimmablePlugInUnitDevice, DimmerSwitchDevice, ExtendedColorLightDevice, FlowSensorDevice, GenericSwitchDevice, HumiditySensorDevice, LightSensorDevice, OccupancySensorDevice, OnOffLightDevice, OnOffLightSwitchDevice, OnOffPluginUnitDevice, OnOffSensorDevice, SpeakerDevice, TemperatureSensorDevice, ThermostatDevice))As instruções de importação para cada trait e tipo de dispositivo registrado aqui são obrigatórias (o Android Studio vai solicitar que você as adicione).
Instancie um
HomeConfigusando o contexto de corrotinaDispatchers.IOe sua instância de registro.val homeConfig = HomeConfig( coroutineContext = Dispatchers.IO, factoryRegistry = registry)Por fim, crie a instância singleton de
Home, que é o ponto de entrada para as APIs, usando o contexto e oHomeConfig.val homeManager: HomeClient = Home.getClient(context, homeConfig)
Para evitar erros com sessões inválidas, é importante que apenas uma instância singleton
de Home seja criada, envolvendo-a em uma declaração
de objeto.
Por exemplo, o app de exemplo faz isso da seguinte maneira:
internal object HomeClientModule {
@Provides
@Singleton
fun provideHomeClient(@ApplicationContext context: Context): HomeClient {
return Home.getClient(
context,
HomeConfig(
coroutineContext = IODispatcherModule.provideIoDispatcher(),
factoryRegistry = registry,
),
)
}
}
Se você quiser que os fluxos de interface hospedados pelo Google, como a tela de permissão, sejam renderizados em um idioma específico, chame setLocale() na instância HomeClient antes de solicitar permissões. Para mais detalhes, consulte
Configurar a localidade do app.
Login do Google iniciado pelo app
Talvez você queira gerenciar as autenticações do Google do usuário no seu app. Isso permite usar a mesma conta de usuário em vários Serviços do Google, como Google Home, Drive, Maps etc.
Com o Login do Google iniciado pelo app, é possível receber uma instância HomeClient
explicitamente vinculada a um usuário específico, ignorando o seletor de Contas do Google
e a tela de permissão quando a conta já está autorizada.
Além disso, essa abordagem impede que os usuários vejam duas telas diferentes de seleção de conta: uma do login do app e outra do Google Home.
Para fazer isso, consulte Autenticar usuários com o recurso Fazer login com o Google e siga estas etapas:
Criar um ID do cliente de aplicativo da Web OAuth
- Abra o console do Google Cloud.
- Acesse a página "Credenciais" do console do Google Cloud.
- Selecione um projeto ou crie um novo.
- Configurar a tela de permissão OAuth (se ainda não tiver feito isso)
- Antes de criar credenciais, verifique se a tela de permissão OAuth está configurada com os detalhes do app, incluindo os URLs da Política de Privacidade e dos Termos de Serviço.
- Crie um ID do cliente OAuth (tipo de aplicativo da Web)
- Na página "Credenciais", clique em
+ CREATE CREDENTIALSe selecione ID do cliente OAuth no menu suspenso. - Em Tipo de aplicativo, selecione Aplicativo da Web.
- Insira um nome para o cliente da Web (por exemplo, "My App Web Backend").
- Clique em "Criar".
- Na página "Credenciais", clique em
- Recuperar o ID do cliente
- Após a criação, o console vai mostrar o novo ID do cliente. Esse é o valor que você vai usar no seu app Android (por exemplo, "{project number}-.....apps.googleusercontent.com").
- Recomendamos que você armazene o ID do cliente externamente
(por exemplo, em
build.gradle) em vez de codificá-lo diretamente.
Instanciar uma solicitação de Login do Google
Use o ID do app da Web para criar uma solicitação de Login do Google:
// Your Google Cloud console Web Client ID for Google Sign-In
val serverClientId = BuildConfig.DEFAULT_WEB_CLIENT_ID
// Build the request for Google ID token
val googleIdOption = GetGoogleIdOption.Builder()
.setFilterByAuthorizedAccounts(false) // Show all Google Accounts on the device
.setServerClientId(serverClientId) // embed WebClientID in token
.build()
// Build the GetCredentialRequest
val request = GetCredentialRequest.Builder().addCredentialOption(googleIdOption).build()
Criar o fluxo do recurso Fazer login com o Google
Para implementar o fluxo de login, use CredentialManager para executar uma
solicitação Sign in with Google. Depois que o usuário selecionar uma conta, extraia
o e-mail dele do token de ID do Google resultante para criar um
android.accounts.Account. Essa conta é usada para inicializar uma instância de HomeClient especificamente vinculada a esse usuário conectado.
try {
// CredentialManager is responsible for interacting with various credential providers on the device
val credentialManager = CredentialManager.create(context)
// Credential returns when user has selected an account and the getCredential call completes
val result = credentialManager.getCredential(context = context, request = request)
val credential = result.credential
if (
credential is CustomCredential &&
credential.type == GoogleIdTokenCredential.TYPE_GOOGLE_ID_TOKEN_CREDENTIAL
) {
try {
val googleCredential = GoogleIdTokenCredential.createFrom(credential.data)
googleCredential.id.let { userEmail ->
Log.i(TAG, "Email found in Google ID Token: $email")
/*
Why "com.google"?
The string "com.google" is a standard identifier used in Android's android.accounts.
Account system to represent accounts managed by Google. This is often used when
interacting with Android's Account Manager or when using Google-specific APIs. So,
even if the email ends in "@gmail.com", the underlying account type or provider is
still considered "com.google" within the Android system.
*/
val account = Account(userEmail, "com.google")
Log.d(TAG,"Switched account to : $userEmail")
// Get the new Home Client Instance with the userEmail
}
Log.i(TAG, "Account switch complete. Emitting navigation event.")
} catch (e: Exception) {
Log.e(TAG,"Could not convert CustomCredential to Google ID Token", e)
}
}
} catch (e: Exception) {
Log.e(TAG, "Google Sign-In failed with unexpected error", e)
}
Acessar uma nova instância do HomeClient
Siga as mesmas etapas descritas em
Criar uma instância de Home, mas, em vez de chamar
Home.getClient(context, homeConfig) na Etapa 4, chame
Home.getClient(context, userAccount,
homeConfig),
em que o segundo parâmetro é um Lazy<UserAccount>. Isso retorna uma instância de
HomeClientWithProvidedAccount,
uma subclasse de HomeClient, que está explicitamente vinculada à Conta do Google
especificada:
val client =
Home.getClient(
context = context.applicationContext,
account =
lazy {
// 1. Create the Account object.
val androidAccount = Account(userEmail,
GoogleAuthUtil.GOOGLE_ACCOUNT_TYPE)
// 2. Wrap it in UserAccount.GoogleAccount.
UserAccount.GoogleAccount(androidAccount)
},
homeConfig = HomeConfig()
)
Se o usuário especificado não estiver autorizado, solicite a permissão dele
chamando os seguintes métodos na instância
HomeClientWithProvidedAccount:
registerActivityResultCallerForPermissions()com uma referência ao ActivityResultCaller que você quer usar.requestPermissions(). Isso abre a tela de permissão da GHP, em que o usuário pode conceder permissão.
Você pode criar um HomeClient com um
UserAccount e chamar
requestPermissions() com forcePermissionFlow definido como
ForcePermissionFlow.FORCE_LAUNCH para iniciar a tela de permissão novamente e permitir
que o usuário atualize as permissões:
val client =
Home.getClient(
context = context.applicationContext,
account =
lazy {
UserAccount.GoogleAccount(androidAccount)
},
homeConfig = HomeConfig()
)
client.registerActivityResultCallerForPermissions(this)
client.requestPermissions(forcePermissionFlow = ForcePermissionFlow.FORCE_LAUNCH)
Para mostrar a tela de permissão em um idioma específico, chame client.setLocale()
antes de chamar requestPermissions(). Consulte
Configurar a localidade do app para mais detalhes e
API Permissions para mais informações sobre como gerenciar as permissões das
APIs do Google Home.
Atualize toda a atividade com o novo HomeClient
Depois de ter uma nova instância de HomeClient, atualize toda a atividade para renovar a assinatura e buscar as estruturas, os dispositivos e outros dados pertinentes
associados a essa conta de usuário.
Registro de atributos e tipos de dispositivo
A classe FactoryRegistry ajuda os desenvolvedores a otimizar o tamanho binário do app,
permitindo que eles indiquem explicitamente quais características e tipos de dispositivo são usados pelo
app.
As permissões e o registro de fábrica são dissociados. Portanto,
as características e os tipos não registrados que estão disponíveis para o app usando permissões,
mas não estão incluídos no registro de fábrica, não podem ser acessados usando a
API Automation nem são retornados nas chamadas de método em massa
traits() ou types().
DeviceGroup, que é diferente de HomeDevice. Para
consultar e interagir com grupos de dispositivos, inclua DeviceGroup na
lista entityTypes ao inicializar o
FactoryRegistry, junto
com as características
Group,
GroupManagement
e
GroupMembership.
Para mais informações, consulte Grupos de dispositivos.
Configurar a localidade do app
Use setLocale() e getLocale() na instância
HomeClient para
configurar e recuperar a preferência de idioma do app. A localidade precisa ser
uma tag de idioma BCP-47 válida, como "en-US", "en-GB" ou "ja".
Quando você define uma localidade em HomeClient, as APIs do Google Home usam esse idioma para fluxos de interface hospedados pelo Google, incluindo a interface de permissões, o comissionamento do Matter e os fluxos de remoção de dispositivos. Se você
não definir uma localidade, esses fluxos vão usar como padrão a localidade do app ou do dispositivo.
- Chamar
setLocale()antes que o usuário faça login e conceda permissões armazena a localidade na memória e a aplica ao fluxo inicial da interface de permissões. Depois que o usuário faz login e uma estrutura é disponibilizada, o SDK sincroniza a localidade com a nuvem. Se o usuário já tiver uma localidade salva na nuvem para seu app, a configuração da nuvem terá precedência na sincronização inicial. - Chamar
setLocale()enquanto o usuário está conectado atualiza a localidade na memória e a mantém na nuvem para esse usuário e app.
// Set the locale using a BCP-47 language tag
coroutineScope.launch {
homeManager.setLocale("ja")
}
// Retrieve the configured locale, or null if not set
val currentLocale: String? = homeManager.getLocale()
Sincronizar com a seleção de idioma por app do Android
Se o app for compatível com a seleção de idioma por app do Android usando
LocaleManager,
chame homeManager.setLocale() antes de atualizar
LocaleManager.applicationLocales. A atualização de applicationLocales recria o
Activity ativo, o que pode cancelar uma corrotina em andamento se você chamar
setLocale() depois.
coroutineScope.launch {
val languageTag = "fr-CA"
// 1. Persist the locale to HomeClient first
homeManager.setLocale(languageTag)
// 2. Update Android's per-app locale (recreates the Activity)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
context.getSystemService(LocaleManager::class.java).applicationLocales =
LocaleList.forLanguageTags(languageTag)
}
}