إعداد المنزل على Android

قبل استخدام أيّ من واجهات برمجة التطبيقات لمنزل Google على Android، عليك تهيئة المنزل في تطبيقك. في هذه الخطوة، ستنشئ مثيلاً فريدًا من Home للسياق المحلي.

يجب أن يكون هناك مثيل واحد فقط من Home نشطًا في كل مرة.

هذه هي نقطة الدخول إلى واجهات برمجة التطبيقات لمنزل Google، وتتضمّن أيضًا تحديد السمات وأنواع الأجهزة التي تنوي استخدامها مع واجهات برمجة التطبيقات للأجهزة والبنية والتشغيل التلقائي. إذا كنت قد بدأت للتو في استخدام نظام Google Home، ولم تكن متأكدًا من السمات أو أنواع الأجهزة التي يجب تسجيلها، فقد اقترحنا بعضًا من أكثرها شيوعًا في هذا الدليل.

إنشاء مثيل من Home

للبدء، استورِد هذه الحِزم إلى تطبيقك:

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

لتهيئة واجهات برمجة التطبيقات لمنزل Google:

  1. احصل على مرجع لـ Application سياق. لا يعتمد هذا السياق على أي مراحل نشاط، وسيظل متاحًا طوال مدة تشغيل تطبيقك. يمكنك الحصول عليه من خلال استدعاء getApplicationContext() ضمن Activity أو Service:

    val context = getApplicationContext()
    
  2. أنشئ مثيلاً من FactoryRegistry يتضمّن جميع السمات وأنواع الأجهزة التي تنوي استخدامها في تطبيقك.

    في هذا الدليل، اقترحنا بعض السمات وأنواع الأجهزة الشائعة (أنواع أجهزة الإضاءة والمقبس والمستشعر والمفتاح والمنظّم الحراري، وسمات الحضور و"مساعد Google" للتشغيل التلقائي)، في حال لم تكن متأكدًا مما تحتاجه. لمزيد من المعلومات، يُرجى الاطّلاع على تسجيل السمات وأنواع الأجهزة.

    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 يجب أن يطلب منك إضافة هذه العبارات).

  3. أنشئ مثيلاً من HomeConfig باستخدام Dispatchers.IO سياق روتين ومثيل التسجيل.

    val homeConfig = HomeConfig(
            coroutineContext = Dispatchers.IO,
            factoryRegistry = registry)
    
  4. أخيرًا، أنشئ مثيل سينغلتون من Home، وهو نقطة الدخول إلى واجهات برمجة التطبيقات، باستخدام السياق و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 وDrive و"خرائط Google" وما إلى ذلك.

باستخدام ميزة "تسجيل الدخول بحساب Google" التي بدأها التطبيق، يمكنك الحصول على مثيل من HomeClient مرتبط بشكلٍ صريح بمستخدم معيّن، ما يؤدي إلى تجاوز أداة اختيار حساب Google وشاشة طلب الموافقة عندما يكون الحساب مأذونًا به.

بالإضافة إلى ذلك، يمنع هذا النهج المستخدمين من رؤية شاشتَين مختلفتَين لاختيار الحساب، إحداهما من تسجيل الدخول إلى التطبيق والأخرى من Google Home.

لإجراء ذلك، عليك الرجوع إلى مقالة مصادقة المستخدمين باستخدام ميزة "تسجيل الدخول باستخدام حساب Google" وإكمال الخطوات التالية:

إنشاء معرّف عميل لتطبيق ويب يستخدم البروتوكول OAuth

  1. افتح Google Cloud Console.
    • انتقِل إلى صفحة بيانات الاعتماد في Google Cloud Console.
    • اختَر مشروعًا حاليًا أو أنشئ مشروعًا جديدًا.
  2. اضبط شاشة طلب الموافقة المتعلّقة ببروتوكول OAuth (إذا لم تفعل ذلك)
    • قبل إنشاء بيانات الاعتماد، تأكَّد من ضبط شاشة طلب الموافقة المتعلّقة ببروتوكول OAuth باستخدام تفاصيل تطبيقك، بما في ذلك عناوين URL لسياسة الخصوصية وبنود الخدمة.
  3. أنشئ معرّف عميل OAuth (نوع تطبيق الويب)
    • في صفحة "بيانات الاعتماد"، انقر على + CREATE CREDENTIALS و اختر معرّف عميل OAuth من القائمة المنسدلة.
    • في حقل نوع التطبيق، اختَر تطبيق الويب.
    • أدخِل اسمًا لعميل الويب (مثل "الواجهة الخلفية لتطبيق الويب").
    • انقر على "إنشاء".
  4. استرداد معرّف العميل
    • بعد الإنشاء، ستعرض وحدة التحكّم معرّف العميل الجديد. هذه هي القيمة التي ستستخدمها في تطبيق 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 مثيل:

  1. registerActivityResultCallerForPermissions() مع مرجع إلى ActivityResultCaller الذي تريد استخدامه.
  2. 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)

راجِع واجهة برمجة التطبيقات للأذونات لمزيد من المعلومات حول إدارة أذونات واجهات برمجة التطبيقات لمنزل Google.

إعادة تحميل النشاط بالكامل باستخدام HomeClient الجديد

بعد الحصول على مثيل جديد من HomeClient، عليك إعادة تحميل النشاط بالكامل لإعادة الاشتراك واسترداد البِنى والأجهزة والبيانات الأخرى ذات الصلة المرتبطة بحساب المستخدم هذا.

تسجيل السمات وأنواع الأجهزة

تساعد فئة FactoryRegistry المطوّرين في تحسين حجم ملف التطبيق الثنائي من خلال السماح لهم بالإشارة بشكلٍ صريح إلى السمات وأنواع الأجهزة التي يستخدمها تطبيقهم.

يُرجى العِلم أنّ الأذونات وتسجيل المصنع منفصلان. لذلك، لا يمكن الوصول إلى السمات والأنواع غير المسجّلة التي تتوفّر لتطبيقك باستخدام الأذونات ولكنها غير مضمّنة في تسجيل المصنع، وذلك باستخدام واجهة برمجة التطبيقات للتشغيل التلقائي، ولا يتم عرضها في استدعاءات الطريقتَين المجمّعة traits() أو types().