Прежде чем использовать любой из API Home для Android, необходимо инициализировать дом в приложении. На этом шаге вы создадите одиночный экземпляр Home для локального контекста.
Одновременно может быть активен только один экземпляр параметра Home.
Это точка входа в Home API. Здесь также нужно указать, какие черты и типы устройств вы планируете использовать с Device & Structure API и Automation API. Если вы только начинаете работать с экосистемой Google Home и не знаете, какие типы устройств и функции регистрировать, мы рекомендуем вам ознакомиться с этим руководством.
Как создать экземпляр дома
Для начала импортируйте в приложение следующие пакеты:
import android.content.Context
import com.google.home.FactoryRegistry
import com.google.home.HomeConfig
import com.google.home.Home
Чтобы инициализировать Home API:
Получите ссылку на контекст
Application. Этот контекст не зависит от жизненного цикла объекта activity и будет существовать, пока работает приложение. Его можно получить, вызвав методgetApplicationContext()в объектеActivityилиService: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
- Откройте консоль Google Cloud.
- Перейдите на страницу учетных данных консоли Google Cloud.
- Выберите существующий проект или создайте новый.
- Настройте окно запроса доступа OAuth, если вы ещё этого не сделали.
- Прежде чем создавать учетные данные, убедитесь, что окно запроса доступа OAuth настроено с учетом сведений о вашем приложении, в том числе URL политики конфиденциальности и условий использования.
- Создайте идентификатор клиента OAuth (тип "Веб-приложение")
- На странице Credentials (Учетные данные) нажмите
+ CREATE CREDENTIALSи выберите OAuth client ID (Идентификатор клиента OAuth) в раскрывающемся меню. - Для параметра Application type (Тип приложения) выберите Web application (Веб-приложение).
- Введите название веб-клиента, например "Бэкэнд моего веб-приложения".
- Нажмите Create (Создать).
- На странице Credentials (Учетные данные) нажмите
- Как получить идентификатор клиента
- После создания идентификатор клиента будет показан в консоли. Это значение вы будете использовать в приложении для Android (например, {project number}-.....apps.googleusercontent.com).
- Рекомендуем хранить идентификатор клиента во внешнем источнике (например, в
build.gradle), а не жестко кодировать его.
Создайте запрос на вход с аккаунтом Google
Используйте идентификатор веб-приложения, чтобы создать запрос на вход в аккаунт 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, чтобы создать 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, но вместо Home.getClient(context, homeConfig) на шаге 4 вызовите 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() с параметром forcePermissionFlow, установленным на ForcePermissionFlow.FORCE_LAUNCH, чтобы снова запустить окно запроса доступа и позволить пользователю изменить предоставленные разрешения:
val client =
Home.getClient(
context = context.applicationContext,
account =
lazy {
UserAccount.GoogleAccount(androidAccount)
},
homeConfig = HomeConfig()
)
client.registerActivityResultCallerForPermissions(this)
client.requestPermissions(forcePermissionFlow = ForcePermissionFlow.FORCE_LAUNCH)
Подробнее о том, как управлять разрешениями Home API, рассказывается в статье Permissions API.
Обновление всего списка действий с помощью нового HomeClient
После того как вы создадите новый экземпляр HomeClient, вам нужно будет обновить все данные, чтобы повторно подписаться и получить полные сведения о структурах, устройствах и другие важные данные, связанные с аккаунтом пользователя.
Регистрация типов устройств и характеристик
Класс FactoryRegistry помогает разработчикам оптимизировать размер двоичного файла приложения, позволяя им явно указывать, какие функции и типы устройств используются в приложении.
Обратите внимание, что разрешения и заводской реестр не связаны друг с другом. Поэтому незарегистрированные трейты и типы, доступные приложению с помощью разрешений, но не включенные в фабричный реестр, недоступны через Automation API и не возвращаются при вызове методов traits() или types().