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 で追加を求められます)。
Dispatchers.IOコルーチン コンテキストとレジストリ インスタンスを使用して、HomeConfigをインスタンス化します。val homeConfig = HomeConfig( coroutineContext = Dispatchers.IO, factoryRegistry = registry)最後に、コンテキストと
HomeConfigを使用して、API のエントリ ポイントであるHomeのシングルトン インスタンスを作成します。val homeManager: HomeClient = Home.getClient(context, homeConfig)
無効なセッションによるエラーを回避するには、Home のシングルトン インスタンスのみが作成されることが重要です。そのためには、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] を選択します。 - [アプリケーションの種類] で [ウェブ アプリケーション] を選択します。
- ウェブ クライアントの名前を入力します(例: 「My App Web Backend」)。
- [作成] をクリックします。
- [認証情報] ページで、
- クライアント 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 アカウントに明示的に関連付けられた HomeClientWithProvidedAccount(HomeClient のサブクラス)のインスタンスが返されます。
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 を作成し、forcePermissionFlow を ForcePermissionFlow.FORCE_LAUNCH に設定して requestPermissions() を呼び出すと、同意画面が再度表示され、ユーザーは権限の付与を更新できます。
val client =
Home.getClient(
context = context.applicationContext,
account =
lazy {
UserAccount.GoogleAccount(androidAccount)
},
homeConfig = HomeConfig()
)
client.registerActivityResultCallerForPermissions(this)
client.requestPermissions(forcePermissionFlow = ForcePermissionFlow.FORCE_LAUNCH)
Home APIs の権限の管理について詳しくは、Permissions API をご覧ください。
新しい HomeClient でアクティビティ全体を更新する
新しい HomeClient インスタンスを取得したら、アクティビティ全体を更新して再度定期購入し、このユーザー アカウントに関連付けられている完全なストラクチャ、デバイス、その他の関連データを取得する必要があります。
トレイトとデバイスタイプの登録
FactoryRegistry クラスを使用すると、アプリで使用される特性とデバイスタイプを明示的に指定できるため、アプリのバイナリサイズを最適化できます。
権限とファクトリ レジストリは分離されています。したがって、権限を使用してアプリで使用できるものの、ファクトリ レジストリに含まれていない未登録のトレイトとタイプには、Automation API を使用してアクセスできません。また、一括 traits() メソッド呼び出しまたは types() メソッド呼び出しでも返されません。