Zuhause auf Android-Geräten initialisieren

Bevor Sie eine der Home APIs für Android verwenden, müssen Sie das Zuhause in Ihrer App initialisieren. In diesem Schritt erstellen Sie eine Singleton Instanz von Home für den lokalen Kontext.

Es sollte immer nur eine Instanz von Home aktiv sein.

Dies ist der Einstiegspunkt für die Home APIs. Außerdem müssen Sie angeben, welche Traits und Gerätetypen Sie mit den Device &Structure und Automation APIs verwenden möchten. Wenn Sie gerade erst mit dem Google Home-Ökosystem beginnen und nicht wissen, welche Traits oder Gerätetypen Sie registrieren sollen, haben wir in diesem Leitfaden einige der häufigsten Vorschläge gemacht.

Home-Instanz erstellen

Importieren Sie zuerst diese Pakete in Ihre App:

import android.content.Context
import com.google.home.FactoryRegistry
import com.google.home.HomeConfig
import com.google.home.Home

So initialisieren Sie die Home APIs:

  1. Rufen Sie eine Referenz auf den Application Kontext ab. Dieser Kontext ist nicht vom Aktivitätslebenszyklus abhängig und ist so lange aktiv, wie Ihre App aktiv ist. Sie können ihn abrufen, indem Sie getApplicationContext() in einer Activity oder einem Service aufrufen:

    val context = getApplicationContext()
    
  2. Erstellen Sie eine FactoryRegistry Instanz mit allen Traits und Gerätetypen, die Sie in Ihrer App verwenden möchten.

    In diesem Leitfaden haben wir einige häufig verwendete Vorschläge gemacht (Gerätetypen „Light“, „Plug“, „Sensor“, „Switch“ und „Thermostat“, Traits „presence“ und „Assistant“ für Automatisierungen), falls Sie sich nicht sicher sind, was Sie benötigen. Weitere Informationen finden Sie unter Registrierung von Traits und Gerätetypen.

    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))
    

    Für jedes hier registrierte Trait und jeden Gerätetyp sind Importanweisungen erforderlich (Android Studio sollte Sie auffordern, diese hinzuzufügen).

  3. Instanziieren Sie eine HomeConfig mit dem Dispatchers.IO Coroutinenkontext und Ihrer Registrierungsinstanz.

    val homeConfig = HomeConfig(
            coroutineContext = Dispatchers.IO,
            factoryRegistry = registry)
    
  4. Erstellen Sie schließlich die Singleton -Instanz von Home, die den Einstiegspunkt für die APIs darstellt, indem Sie den Kontext und die HomeConfig verwenden.

    val homeManager: HomeClient = Home.getClient(context, homeConfig)
    

Um Fehler mit ungültigen Sitzungen zu vermeiden, darf nur eine Singleton Instanz von Home erstellt werden. Dazu muss sie in eine Objekterklärung eingeschlossen werden.

In der Beispiel-App wird dies so gemacht:

internal object HomeClientModule {
  @Provides
  @Singleton
  fun provideHomeClient(@ApplicationContext context: Context): HomeClient {
    return Home.getClient(
      context,
      HomeConfig(
        coroutineContext = IODispatcherModule.provideIoDispatcher(),
        factoryRegistry = registry,
      ),
    )
  }
}

Von der App initiierte Google-Anmeldung

Möglicherweise möchten Sie die Google-Authentifizierungen Ihrer Nutzer in Ihrer App verwalten. So können Sie dasselbe Nutzerkonto für verschiedene Google-Dienste wie Google Home, Drive, Maps usw. verwenden.

Mit der von der App initiierten Google-Anmeldung können Sie eine HomeClient-Instanz abrufen, die explizit mit einem bestimmten Nutzer verknüpft ist. So werden die Google-Kontenauswahl und der Zustimmungsbildschirm umgangen, wenn das Google-Konto bereits autorisiert ist.

Außerdem wird so verhindert, dass Nutzer zwei verschiedene Bildschirme zur Kontoauswahl sehen: einen für die Anmeldung in der App und einen für Google Home.

Dazu müssen Sie sich auf Nutzer mit „Über Google anmelden“ authentifizieren beziehen und die folgenden Schritte ausführen:

OAuth-Webanwendungs-Client-ID erstellen

  1. Öffnen Sie die Google Cloud Console.
    • Rufen Sie in der Google Cloud Console die Seite Anmeldedaten auf.
    • Wählen Sie ein vorhandenes Projekt aus oder erstellen Sie ein neues.
  2. OAuth-Zustimmungsbildschirm konfigurieren (falls noch nicht geschehen)
    • Bevor Sie Anmeldedaten erstellen, muss der OAuth-Zustimmungsbildschirm mit den Details Ihrer App konfiguriert sein, einschließlich der URLs der Datenschutzerklärung und der Nutzungsbedingungen.
  3. OAuth-Client-ID erstellen (Typ „Webanwendung“)
    • Klicken Sie auf der Seite „Anmeldedaten“ auf + CREATE CREDENTIALS und wählen Sie OAuth-Client-ID im Drop-down-Menü aus.
    • Wählen Sie als Anwendungstyp die Option Webanwendung aus.
    • Geben Sie einen Namen für Ihren Webclient ein (z.B. „Web-Back-End meiner App“).
    • Klicken Sie auf „Erstellen“.
  4. Client-ID abrufen
    • Nach der Erstellung wird in der Console die neue Client-ID angezeigt. Dies ist der Wert, den Sie in Ihrer Android-App verwenden (z.B. „{project number}-.....apps.googleusercontent.com“)
    • Es wird empfohlen, die Client-ID extern zu speichern (z. B. in build.gradle) und nicht direkt fest zu codieren.

Google Log-in-Anfrage instanziieren

Verwenden Sie die Web-App-ID, um eine Google-Anfrage für die Anmeldung zu erstellen:

// 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()

Ablauf für „Über Google anmelden“ erstellen

Verwenden Sie CredentialManager, um eine Sign in with Google Anfrage auszuführen. Sobald der Nutzer ein Konto ausgewählt hat, extrahieren Sie seine E‑Mail-Adresse aus dem resultierenden Google-ID-Token, um ein android.accounts.Account zu erstellen. Dieses Konto wird dann verwendet, um eine HomeClient-Instanz zu initialisieren, die speziell mit diesem angemeldeten Nutzer verknüpft ist.

  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)
  }

Neue HomeClient-Instanz abrufen

Führen Sie dieselben Schritte aus, die unter Home-Instanz erstellen beschrieben sind. Rufen Sie in Schritt 4 jedoch nicht Home.getClient(context, homeConfig) auf, sondern Home.getClient(context, userAccount, homeConfig) auf. Der zweite Parameter ist ein Lazy<UserAccount>. Dadurch wird eine Instanz von HomeClientWithProvidedAccount, einer Unterklasse von HomeClient, die explizit mit dem angegebenen Google Konto verknüpft ist:

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()
     )

Wenn der angegebene Nutzer nicht autorisiert ist, fordern Sie ihn auf, die Berechtigung zu erteilen, indem Sie die folgenden Methoden für die HomeClientWithProvidedAccount Instanz aufrufen:

  1. registerActivityResultCallerForPermissions() mit einer Referenz auf den zu verwendenden ActivityResultCaller.
  2. requestPermissions(). Dadurch wird der GHP-Zustimmungsbildschirm aufgerufen, auf dem der Nutzer seine Berechtigung erteilen kann.

Sie können einen HomeClient mit einem UserAccount erstellen und dann requestPermissions() mit forceLaunch==true aufrufen, um den Zustimmungsbildschirm noch einmal zu starten und dem Nutzer die Möglichkeit zu geben, seine Berechtigungen zu aktualisieren:

val client =
     Home.getClient(
       context = context.applicationContext,
       account =
         lazy {
              UserAccount.GoogleAccount(androidAccount)
         },
       homeConfig = HomeConfig()
     )

client.registerActivityResultCallerForPermissions(this)
client.requestPermissions(forceLaunch= true)

Weitere Informationen zum Verwalten von Berechtigungen für Home APIs finden Sie unter Permissions API.

Gesamte Aktivität mit dem neuen HomeClient aktualisieren

Sobald Sie eine neue HomeClient-Instanz haben, müssen Sie die gesamte Activity aktualisieren, um sich erneut zu abonnieren und alle Strukturen, Geräte und andere relevante Daten abzurufen, die mit diesem Nutzerkonto verknüpft sind.

Registrierung von Traits und Gerätetypen

Mit der Klasse FactoryRegistry können Entwickler die Größe ihrer App-Binärdatei optimieren, indem sie explizit angeben, welche Traits und Gerätetypen von ihrer App verwendet werden.

Berechtigungen und die Factory Registry sind entkoppelt. Daher sind nicht registrierte Traits und Typen, die für Ihre App über Berechtigungen verfügbar sind, aber nicht in der Factory Registry enthalten sind, über die Automation API nicht zugänglich. Sie werden auch nicht in den Bulk-Methodenaufrufen traits() oder types() zurückgegeben.