Прежде чем использовать какие-либо API Home для Android, необходимо инициализировать Home в вашем приложении. На этом шаге вы создадите единственный экземпляр Home для локального контекста.
В любой момент времени должен быть активен только один экземпляр Home .
Это точка входа в API Home, а также указание характеристик и типов устройств, которые вы планируете использовать с API Device & Structure и Automation. Если вы только начинаете работать с экосистемой Google Home и не уверены, какие характеристики или типы устройств нужно зарегистрировать, в этом руководстве мы предложили несколько наиболее распространенных вариантов.
Создайте экземпляр Home.
Для начала импортируйте следующие пакеты в ваше приложение:
import android.content.Context
import com.google.home.FactoryRegistry
import com.google.home.HomeConfig
import com.google.home.Home
Для инициализации API Home:
Получите ссылку на контекст
Application. Этот контекст не зависит от жизненного цикла какой-либо активности и будет существовать до тех пор, пока ваше приложение работает. Вы можете получить его, вызвавgetApplicationContext()внутриActivityилиService:val context = getApplicationContext()Создайте экземпляр
FactoryRegistryсо всеми характеристиками и типами устройств, которые вы планируете использовать в своем приложении.В этом руководстве мы предложили несколько распространенных типов устройств (светильник, розетка, датчик, выключатель и термостат, а также характеристики присутствия и данные голосового помощника для автоматизации), на случай, если вы не уверены, что именно вам нужно. Для получения дополнительной информации см. раздел «Регистрация характеристик и типов устройств» .
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 Drive, Google Maps и так далее.
При использовании входа в систему Google, инициируемого приложением, вы можете получить экземпляр HomeClient явно привязанный к конкретному пользователю, тем самым минуя выбор учетной записи Google и экран подтверждения согласия, когда учетная запись уже авторизована.
Кроме того, такой подход предотвращает отображение пользователями двух разных экранов выбора учетной записи — одного при входе в приложение и другого на Google Home.
Для этого необходимо перейти к разделу «Аутентификация пользователей с помощью входа через Google» и выполнить следующие шаги:
Создайте идентификатор клиента веб-приложения OAuth.
- Откройте консоль Google Cloud.
- Перейдите на страницу «Учетные данные консоли Google Cloud».
- Выберите существующий проект или создайте новый.
- Настройте экран согласия OAuth (если вы этого еще не сделали).
- Перед созданием учетных данных убедитесь, что экран согласия OAuth настроен с указанием данных вашего приложения, включая URL-адреса политики конфиденциальности и условий использования.
- Создайте идентификатор клиента OAuth (тип веб-приложения).
- На странице «Учетные данные» нажмите кнопку
+ CREATE CREDENTIALSи выберите «Идентификатор клиента OAuth» из выпадающего меню. - В поле «Тип приложения» выберите «Веб-приложение» .
- Введите имя для вашего веб-клиента (например, "My App Web Backend").
- Нажмите «Создать».
- На странице «Учетные данные» нажмите кнопку
- Получите идентификатор клиента.
- После создания в консоли отобразится ваш новый идентификатор клиента (Client ID). Это значение вы будете использовать в своем Android-приложении (например, " {номер проекта}-.....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 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» , но вместо вызова 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() с forceLaunch==true чтобы снова запустить экран согласия и позволить пользователю обновить предоставленные ему разрешения:
val client =
Home.getClient(
context = context.applicationContext,
account =
lazy {
UserAccount.GoogleAccount(androidAccount)
},
homeConfig = HomeConfig()
)
client.registerActivityResultCallerForPermissions(this)
client.requestPermissions(forceLaunch= true)
Дополнительную информацию об управлении разрешениями API Home см. в разделе «API разрешений» .
Обновите всю активность с помощью нового HomeClient.
После создания нового экземпляра HomeClient необходимо обновить всю активность, чтобы повторно подписаться и получить все структуры, устройства и другие соответствующие данные, связанные с этой учетной записью пользователя.
Регистрация характеристик и типов устройств
Класс FactoryRegistry помогает разработчикам оптимизировать размер исполняемого файла приложения, позволяя им явно указывать, какие характеристики и типы устройств используются их приложением.
Обратите внимание, что разрешения и реестр фабрик не связаны между собой. Поэтому незарегистрированные трейты и типы, доступные вашему приложению с помощью разрешений, но не включенные в реестр фабрик, недоступны с помощью API автоматизации и не возвращаются в вызовах методов bulk traits() или types() .