راه‌اندازی خانه در Android

قبل‌از استفاده از هریک از «میاناهای برنامه‌سازی کاربردی Home برای Android»، باید خانه را در برنامه‌تان مقداردهی اولیه کنید. در این مرحله، یک نمونه تک‌نمونه‌ای از Home برای بافت محلی ایجاد خواهید کرد.

فقط یک نمونه از Home باید در هر زمان فعال باشد.

این نقطه ورود به Home APIs است و همچنین شامل اعلام کردن ویژگی‌ها و انواع دستگاهی است که قصد دارید با Device & Structure و Automation APIs استفاده کنید. اگر تازه شروع به کار با بوم‌سازگان Google Home کرده‌اید و مطمئن نیستید که کدام ویژگی‌ها یا انواع دستگاه را ثبت کنید، برخی‌از رایج‌ترین آن‌ها را در اینجا در این راهنما پیشنهاد کرده‌ایم.

ایجاد نمونه «خانه»

برای شروع، این بسته‌ها را به برنامه‌تان وارد کنید:

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

برای مقداردهی اولیه کردن «میاناهای برنامه‌سازی کاربردی خانه»:

  1. مرجعی برای Application بافت دریافت کنید. این زمینه به هیچ چرخه حیات فعالیتی وابسته نیست و تا زمانی که برنامه‌تان فعال است، زنده می‌ماند. می‌توانید آن را با تماس با getApplicationContext() در Activity یا Service دریافت کنید:

    val context = getApplicationContext()
    
  2. یک نمونه 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 باید از شما بخواهد این موارد را اضافه کنید).

  3. بااستفاده از بافت روتین همکار Dispatchers.IO و نمونه ثبت شما، HomeConfig نمونه‌سازی کنید.

    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،‏ Maps، و غیره استفاده کنید.

با «ورود به سیستم با Google» آغازشده از برنامه، می‌توانید نمونه HomeClient را که به‌طور صریح به کاربر خاصی مرتبط است دریافت کنید، و ازاین‌طریق، وقتی حساب ازقبل مجاز شده است، از انتخابگر «حساب Google» و صفحه موافقت عبور کنید.

علاوه‌براین، این رویکرد مانع از این می‌شود که کاربران دو صفحه انتخاب حساب متفاوت ببینند - یکی از ورود به سیستم برنامه و دیگری از Google Home.

برای انجام این کار، باید به اصالت‌سنجی کاربران با «ورود به سیستم با Google» مراجعه کنید و مراحل زیر را تکمیل کنید:

ایجاد شناسه کارخواه برنامه وب OAuth

  1. «کنسول Google Cloud» را باز کنید
    • به صفحه «اطلاعات اعتباری کنسول Google Cloud» پیمایش کنید.
    • پروژه موجودی را انتخاب کنید یا پروژه جدیدی بسازید.
  2. «صفحه کسب رضایت OAuth» را پیکربندی کنید (اگر قبلاً این کار را نکرده‌اید)
    • پیش‌از ایجاد کردن اطلاعات اعتباری، مطمئن شوید صفحه موافقت OAuth با جزئیات برنامه‌تان، ازجمله نشانی‌های وب خط‌مشی رازداری و شرایط خدمات، پیکربندی شده باشد.
  3. شناسه کارخواه OAuth (نوع «برنامه وب») ایجاد کنید
    • در صفحه «اعتبارنامه‌ها»، روی + CREATE CREDENTIALS کلیک کنید و شناسه کارخواه OAuth را از منو کرکره‌ای انتخاب کنید.
    • برای نوع برنامه، برنامه وب را انتخاب کنید.
    • نامی برای کارخواه وب خود وارد کنید (برای نمونه، «My App Web Backend»).
    • روی «ایجاد کردن» کلیک کنید.
  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.getClient(context, homeConfig) در مرحله ۴، 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)

برای کسب اطلاعات بیشتر درباره مدیریت اجازه‌های میاناهای برنامه‌سازی کاربردی خانه، میاناهای برنامه‌سازی کاربردی اجازه‌ها را ببینید.

کل فعالیت را با HomeClient جدید بازآوری کنید

پس‌از اینکه نمونه جدید HomeClient را دریافت کردید، باید کل فعالیت را بازآوری کنید تا دوباره مشترک شوید و ساختارها، دستگاه‌ها، و دیگر داده‌های مربوط به این حساب کاربری را واکشی کنید.

ثبت ویژگی‌ها و انواع دستگاه

کلاس FactoryRegistry به توسعه‌دهندگان کمک می‌کند اندازه باینری برنامه خود را با اجازه دادن به آن‌ها برای نشان دادن صریح اینکه برنامه آن‌ها از کدام ویژگی‌ها و انواع دستگاه استفاده می‌کند بهینه‌سازی کنند.

توجه داشته باشید که اجازه‌ها و ثبت کارخانه از هم جدا هستند. بنابراین، ویژگی‌ها و انواع ثبت‌نشده‌ای که بااستفاده از اجازه‌ها دراختیار برنامه‌تان قرار می‌گیرند اما در ثبت کارخانه‌ای گنجانده نشده‌اند بااستفاده از میانای برنامه‌سازی کاربردی «خودکارسازی» قابل‌دسترسی نیستند و در فراخوانی‌های روش traits() یا types() دسته‌ای نیز برگردانده نمی‌شوند.