Android 用の Home API を使用する前に、アプリでホームを初期化する必要があります。この手順では、ローカル コンテキスト用の シングルトン インスタンスを作成します。Home
アクティブな Home インスタンスは一度に 1 つだけにする必要があります。
これは Home API のエントリ ポイントであり、Device &Structure 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またはService内でgetApplicationContext()を呼び出すことで取得できます。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 で追加するよう求められます)。
HomeConfigDispatchers.IOコルーチン コンテキストとレジストリ インスタンスを使用してインスタンス化します。val homeConfig = HomeConfig( coroutineContext = Dispatchers.IO, factoryRegistry = registry)最後に、コンテキストと
HomeConfigを使用して、API のエントリ ポイントであるHomeの シングルトン インスタンスを作成します。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 Home、ドライブ、マップなど、さまざまな Google サービスで同じユーザー アカウントを使用できます。
アプリから開始される Google ログインを使用すると、特定のユーザーに明示的に関連付けられた HomeClient インスタンスを取得できます。これにより、アカウントがすでに承認されている場合は、Google アカウントの選択ツールと同意画面をスキップできます。
また、この方法では、アプリのログインと Google Home の 2 つの異なるアカウント選択画面が表示されるのを防ぐことができます。
これを行うには、「Google でログイン」を使用してユーザーを認証するを参照し、次の手順を完了する必要があります。
OAuth ウェブ アプリケーション クライアント ID を作成する
- Google Cloud コンソールを開きます。
- Google Cloud コンソール の [認証情報] ページに移動します。
- 既存のプロジェクトを選択するか、プロジェクトを新規作成します。
- OAuth 同意画面を構成する(まだ構成していない場合)
- 認証情報を作成する前に、OAuth 同意画面がアプリの詳細(プライバシー ポリシーと利用規約の URL など)で構成されていることを確認してください。
- OAuth クライアント ID(ウェブ アプリケーション タイプ)を作成する
- [認証情報] ページで、[
+ CREATE CREDENTIALS] をクリックし、プルダウン メニューから [OAuth クライアント ID] を選択します。 - [**アプリケーションの種類**] で [**ウェブ アプリケーション**] を選択します。
- ウェブ クライアントの名前(「マイアプリのウェブ バックエンド」など)を入力します。
- [作成] をクリックします。
- [認証情報] ページで、[
- クライアント ID を取得する
- 作成後、コンソールに新しいクライアント ID が表示されます。これは、Android アプリケーションで使用する値です(例: "{project number}-.....apps.googleusercontent.com")。
- クライアント ID は直接ハードコードするのではなく、外部に保存することをおすすめします(
build.gradleなど)。
Google ログイン リクエストをインスタンス化する
ウェブアプリ 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)を呼び出します。
2 番目のパラメータは Lazy<UserAccount> です。これにより、指定した Google
アカウントに明示的に関連付けられた HomeClient のサブクラスである
HomeClientWithProvidedAccountのインスタンスが返されます。
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 同意画面が表示され、ユーザーが権限を付与できます。
UserAccount を使用して HomeClient を作成し、forceLaunch==true を指定して
requestPermissions() を呼び出すと、同意画面が
再度表示され、ユーザーが権限の付与を更新できます。
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 でアクティビティ全体を更新する
新しい HomeClient インスタンスを取得したら、アクティビティ全体を更新して、このユーザー アカウントに関連付けられているすべての構造、デバイス、その他の関連データを再登録して取得する必要があります。
トレイトとデバイスタイプの登録
FactoryRegistry クラスを使用すると、アプリで使用するトレイトとデバイスタイプを明示的に指定できるため、アプリのバイナリサイズを最適化できます。
権限とファクトリ レジストリは分離されています。したがって、権限を使用してアプリで利用できるが、ファクトリ レジストリに含まれていない未登録のトレイトとタイプは、Automation API を使用してアクセスすることも、一括 traits() または types() メソッド呼び出しで返されることもありません。