在使用任何 Android 版 Home API 之前,您必须在应用中初始化 Home。在此步骤中,您将为本地上下文创建 单例 实例。Home
一次只能有一个 Home 实例处于活动状态。
这是 Home API 的入口点,还涉及声明您打算与设备和结构 API 以及 Automation API 搭配使用的特征和设备类型。如果您刚开始使用 Google Home 生态系统,并且不确定要注册哪些特征或设备类型,我们已在本指南中建议了一些最常见的特征或设备类型。
创建 Home 实例
首先,将以下软件包导入到您的应用中:
import android.content.Context
import com.google.home.FactoryRegistry
import com.google.home.HomeConfig
import com.google.home.Home
如需初始化 Home API,请执行以下操作:
获取对
Application上下文的引用。此上下文不依赖于任何 activity 生命周期,并且只要您的应用处于活动状态,它就会一直存在。您可以通过在Activity或Service中调用getApplicationContext()来获取它:val context = getApplicationContext()使用您打算在应用中使用的所有特征和设备类型创建
FactoryRegistry实例。在本指南中,我们建议了一些常见的特征或设备类型(Light、Plug、Sensor、Switch 和 Thermostat 设备类型,以及用于自动化操作的 presence 和 Assistant 特征),以防您不确定需要哪些特征或设备类型。如需了解详情,请参阅 注册特征和设备类型。
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))您必须在此处注册的每个特征和设备类型导入语句 是必需的(Android Studio应该会提示您添加这些语句)。
实例化
HomeConfig使用Dispatchers.IO协程上下文和注册表实例。val homeConfig = HomeConfig( coroutineContext = Dispatchers.IO, factoryRegistry = registry)最后,创建 单例 实例
Home,这是 API 的入口点,使用上下文和HomeConfig。val homeManager: HomeClient = Home.getClient(context, homeConfig)
为避免因会话无效而导致错误,请务必仅创建一个 单例
实例,方法是将其封装在对象
声明中。Home
例如,示例应用会以这种方式执行此操作:
internal object HomeClientModule {
@Provides
@Singleton
fun provideHomeClient(@ApplicationContext context: Context): HomeClient {
return Home.getClient(
context,
HomeConfig(
coroutineContext = IODispatcherModule.provideIoDispatcher(),
factoryRegistry = registry,
),
)
}
}
应用发起的 Google 登录
您可能需要在应用中管理用户的 Google 身份验证。这样,您就可以在各种 Google 服务(例如 Google Home、云端硬盘、地图等)中使用同一用户账号。
借助应用发起的 Google 登录,您可以获取与特定用户明确关联的 HomeClient 实例,从而在账号已获得授权时绕过 Google 账号选择器和权限请求页面。
此外,这种方法还可以防止用户看到两个不同的账号选择屏幕:一个来自应用的登录,另一个来自 Google Home。
为此,您必须参阅使用 Google 账号登录对用户进行身份验证,并完成以下步骤:
创建 OAuth Web 应用客户端 ID
- 打开 Google Cloud 控制台
- 前往 Google Cloud 控制台的“凭据”页面。
- 选择现有项目或创建新项目。
- 配置 OAuth 权限请求页面(如果您尚未配置)
- 在创建凭据之前,请确保 OAuth 权限请求页面已配置应用的详细信息,包括隐私权政策和服务条款网址。
- 创建 OAuth 客户端 ID(Web 应用类型)
- 在“凭据”页面上,点击
+ CREATE CREDENTIALS,然后从下拉菜单中选择 OAuth 客户端 ID 。 - 对于应用类型,选择Web 应用。
- 输入 Web 客户端的名称(例如“我的应用 Web 后端”)。
- 点击“创建”。
- 在“凭据”页面上,点击
- 检索客户端 ID
- 创建后,控制台会显示新的客户端 ID。这是您将在 Android 应用中使用的值(例如“{project number}-.....apps.googleusercontent.com”)。
- 建议您将客户端 ID 存储在外部(例如,在
build.gradle中),而不是直接对其进行硬编码
实例化 Google 登录请求
使用 Web 应用 ID 创建 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()
创建“使用 Google 账号登录”流程
如需实现登录流程,请使用 CredentialManager 执行 Sign in with Google 请求。用户选择账号后,从生成的 Google ID 令牌中提取其电子邮件地址,以创建 android.accounts.Account。然后,此账号用于初始化专门与该登录用户关联的 HomeClient 实例。
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)
}
获取新的 HomeClient 实例
按照
创建 Home 实例中所述的相同步骤操作,但不要在第 4 步中调用
Home.getClient(context, homeConfig),而是调用
Home.getClient(context, userAccount,
homeConfig),
其中第二个参数是 Lazy<UserAccount>。 这会返回
HomeClientWithProvidedAccount(
HomeClient 的子类)的实例,该实例与指定的 Google
账号明确关联:
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()
)
如果指定的用户未获得授权,请通过
对
HomeClientWithProvidedAccount
实例调用以下方法来提示用户授予权限:
registerActivityResultCallerForPermissions(),并引用您要使用的 ActivityResultCaller。requestPermissions()。这会显示 GHP 权限请求页面,用户可以在其中授予权限。
您可以使用 HomeClient 创建
UserAccount,然后使用
requestPermissions() 调用 forceLaunch==true 以再次启动权限请求页面,从而允许用户更新其权限授予:
val client =
Home.getClient(
context = context.applicationContext,
account =
lazy {
UserAccount.GoogleAccount(androidAccount)
},
homeConfig = HomeConfig()
)
client.registerActivityResultCallerForPermissions(this)
client.requestPermissions(forceLaunch= true)
如需详细了解如何管理 Home API 权限,请参阅Permissions API。
使用新的 HomeClient 刷新整个 activity
获得新的 HomeClient 实例后,您必须刷新整个 activity,以重新订阅并提取与此用户账号关联的完整结构、设备和其他相关数据。
注册特征和设备类型
FactoryRegistry 类可让开发者明确指明其应用使用的特征和设备类型,从而帮助他们优化应用二进制文件大小。
请注意,权限和工厂注册表是分离的。因此,
使用权限但未包含在工厂注册表中的未注册 trait 和类型无法使用
Automation API 访问,也不会在批量
traits() 或 types() 方法调用中返回。