Android पर होम को शुरू करना

Android के लिए Home API का इस्तेमाल करने से पहले, आपको अपने ऐप्लिकेशन में होम को शुरू करना होगा. इस चरण में, स्थानीय कॉन्टेक्स्ट के लिए सिंगलटन इंस्टेंस बनाया जाएगा.Home

एक समय पर, Home का सिर्फ़ एक इंस्टेंस चालू होना चाहिए.

यह Home API का एंट्री पॉइंट है. इसमें यह भी बताया जाता है कि Device &Structure और Automation API के साथ, किन ट्रेट और डिवाइस टाइप का इस्तेमाल किया जाना है. अगर आपने Google Home इकोसिस्टम का इस्तेमाल अभी शुरू किया है और आपको यह नहीं पता कि किन ट्रेट या डिवाइस टाइप को रजिस्टर करना है, तो हमने इस गाइड में कुछ सामान्य ट्रेट और डिवाइस टाइप के बारे में बताया है.

होम इंस्टेंस बनाना

शुरू करने के लिए, अपने ऐप्लिकेशन में ये पैकेज इंपोर्ट करें:

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

Home API को शुरू करने के लिए:

  1. Application कॉन्टेक्स्ट का रेफ़रंस पाएं. यह कॉन्टेक्स्ट, किसी भी गतिविधि के लाइफ़साइकल पर निर्भर नहीं करता. यह तब तक चालू रहेगा, जब तक आपका ऐप्लिकेशन चालू है. Activity या Service में getApplicationContext() को कॉल करके, इसे हासिल किया जा सकता है:

    val context = getApplicationContext()
    
  2. FactoryRegistry का एक इंस्टेंस बनाएं. इसमें वे सभी ट्रेट और डिवाइस टाइप शामिल करें जिनका इस्तेमाल आपको अपने ऐप्लिकेशन में करना है.

    इस गाइड में, हमने कुछ सामान्य ट्रेट और डिवाइस टाइप (लाइट, प्लग, सेंसर, स्विच, और थर्मोस्टैट डिवाइस टाइप, ऑटोमेशन के लिए मौजूदगी और Assistant ट्रेट) के बारे में बताया है. ऐसा तब किया गया है, जब आपको यह नहीं पता कि आपको किन ट्रेट और डिवाइस टाइप की ज़रूरत है. ज़्यादा जानने के लिए, ट्रेट और डिवाइस टाइप का रजिस्ट्रेशन देखें.

    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, Maps वगैरह) में एक ही उपयोगकर्ता खाते का इस्तेमाल किया जा सकता है.

ऐप्लिकेशन से शुरू होने वाले Google साइन-इन की मदद से, किसी खास उपयोगकर्ता से साफ़ तौर पर जुड़े HomeClient का इंस्टेंस हासिल किया जा सकता है. इससे, खाता पहले से ही ऑथराइज़ होने पर, Google खाता चुनने की स्क्रीन और ऐसी स्क्रीन जहां OAuth के लिए सहमति दी जाती है, को बायपास किया जा सकता है.

इसके अलावा, इस तरीके से उपयोगकर्ताओं को खाता चुनने की दो अलग-अलग स्क्रीन नहीं दिखतीं. इनमें से एक स्क्रीन, ऐप्लिकेशन के साइन-इन से जुड़ी होती है और दूसरी Google Home से.

इसके लिए, आपको 'Google से साइन इन करें' की मदद से उपयोगकर्ताओं की पुष्टि करना लेख देखना होगा. साथ ही, यह तरीका अपनाना होगा:

OAuth वेब ऐप्लिकेशन क्लाइंट आईडी बनाना

  1. Google Cloud Console खोलें
    • Google Cloud Console के क्रेडेंशियल पेज पर जाएं.
    • कोई मौजूदा प्रोजेक्ट चुनें या नया प्रोजेक्ट बनाएं.
  2. OAuth सहमति वाली स्क्रीन को कॉन्फ़िगर करें (अगर आपने ऐसा नहीं किया है)
    • क्रेडेंशियल बनाने से पहले, पक्का करें कि OAuth सहमति वाली स्क्रीन, आपके ऐप्लिकेशन की जानकारी के साथ कॉन्फ़िगर की गई हो. इसमें, निजता नीति और सेवा की शर्तों के यूआरएल शामिल होने चाहिए.
  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 का अनुरोध करें. उपयोगकर्ता के खाता चुनने के बाद, android.accounts.Account बनाने के लिए, Google आईडी टोकन से उसका ईमेल पता निकालें. इसके बाद, इस खाते का इस्तेमाल करके, 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 सहमति वाली स्क्रीन खुलती है. इस स्क्रीन पर, उपयोगकर्ता अपनी अनुमति दे सकता है.

आप UserAccount के साथ HomeClient बना सकते हैं और फिर forcePermissionFlow को ForcePermissionFlow.FORCE_LAUNCH पर सेट करके requestPermissions() को कॉल कर सकते हैं. इससे, ऐसी स्क्रीन जहां OAuth के लिए सहमति दी जाती है, वह फिर से लॉन्च हो जाती है. इससे उपयोगकर्ता, अनुमति देने से जुड़ी अपनी सेटिंग अपडेट कर सकता है:

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

client.registerActivityResultCallerForPermissions(this)
client.requestPermissions(forcePermissionFlow = ForcePermissionFlow.FORCE_LAUNCH)

Home API की अनुमतियों को मैनेज करने के बारे में ज़्यादा जानने के लिए, Permissions API देखें.

नए HomeClient की मदद से, पूरी गतिविधि को रीफ़्रेश करना

HomeClient का नया इंस्टेंस मिलने के बाद, आपको पूरी गतिविधि को रीफ़्रेश करना होगा. इससे, इस उपयोगकर्ता खाते से जुड़े सभी स्ट्रक्चर, डिवाइस, और अन्य ज़रूरी डेटा को फिर से फ़ेच किया जा सकेगा. साथ ही, सदस्यता भी फिर से ली जा सकेगी.

ट्रेट और डिवाइस टाइप का रजिस्ट्रेशन

FactoryRegistry क्लास, डेवलपर को अपने ऐप्लिकेशन के बाइनरी साइज़ को ऑप्टिमाइज़ करने में मदद करती है. इसके लिए, डेवलपर साफ़ तौर पर बता सकते हैं कि उनके ऐप्लिकेशन में किन ट्रेट और डिवाइस टाइप का इस्तेमाल किया जाता है.

ध्यान दें कि अनुमतियां और फ़ैक्ट्री रजिस्ट्री अलग-अलग होती हैं. इसलिए, रजिस्टर न किए गए ट्रेट और टाइप, आपके ऐप्लिकेशन के लिए अनुमतियों का इस्तेमाल करके उपलब्ध होते हैं. हालांकि, अगर इन्हें फ़ैक्ट्री रजिस्ट्री में शामिल नहीं किया जाता है, तो Automation API का इस्तेमाल करके इन्हें ऐक्सेस नहीं किया जा सकता. साथ ही, इन्हें बल्क traits() या types() तरीके से कॉल करने पर भी वापस नहीं किया जाता.