Android-এ হোম ইনিশিয়ালাইজ করা

Android-এর জন্য কোনও Home API ব্যবহার করার আগে, আপনাকে অবশ্যই নিজের অ্যাপে হোম ইনিশিয়ালাইজ করতে হবে। এই ধাপে, আপনি লোকাল কনটেক্সটের জন্য Home-এর একটি সিঙ্গেলটন ইনস্ট্যান্সতৈরি করবেন।

একবারে Home-এর একটি ইনস্ট্যান্সই অ্যাক্টিভ থাকতে পারবে।

এটি Home API-তে প্রবেশের পয়েন্ট এবং এর মধ্যে কোন কোন ট্রেইট ও ডিভাইসের ধরন আপনি ডিভাইস ও স্ট্রাকচার এবং অটোমেশন 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. সবশেষে, context ও HomeConfig ব্যবহার করে API-তে এন্ট্রি পয়েন্ট হিসেবে কাজ করে এমন Home-এর সিঙ্গেলটন ইনস্ট্যান্স তৈরি করুন।

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

ভুল সেশন সংক্রান্ত সমস্যা এড়াতে, সিঙ্গেলটন ইনস্ট্যান্সের Home অবজেক্ট ডিক্লারেশন-এর মধ্যে র‍্যাপ করে তৈরি করা গুরুত্বপূর্ণ।

যেমন, Sample App এটি এইভাবে করে:

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 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 অনুরোধ এক্সিকিউট করুন। ব্যবহারকারী অ্যাকাউন্ট বেছে নেওয়ার পরে, একটি android.accounts.Account তৈরি করতে, ফলাফল হিসেবে পাওয়া Google ID টোকেন থেকে তার ইমেল আইডি এক্সট্র্যাক্ট করুন। এই অ্যাকাউন্টটি তারপরে সাইন-ইন করা ব্যবহারকারীর সাথে বিশেষভাবে যুক্ত একটি 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. আপনি যে ActivityResultCaller ব্যবহার করতে চান সেটির রেফারেন্স সহ registerActivityResultCallerForPermissions()।
  2. 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 API-এর অনুমতি ম্যানেজ করা সম্পর্কে আরও জানতে অনুমতি API দেখুন।

নতুন HomeClient-এর মাধ্যমে সম্পূর্ণ অ্যাক্টিভিটি রিফ্রেশ করা

নতুন HomeClient ইনস্ট্যান্স পাওয়ার পরে, আপনাকে অবশ্যই আবার সাবস্ক্রাইব করতে এবং এই ব্যবহারকারীর অ্যাকাউন্টের সাথে যুক্ত সম্পূর্ণ স্ট্রাকচার, ডিভাইস এবং অন্যান্য প্রাসঙ্গিক ডেটা ফেচ করতে সম্পূর্ণ অ্যাক্টিভিটি রিফ্রেশ করতে হবে।

ট্রেইট ও ডিভাইসের ধরনের রেজিস্ট্রেশন

FactoryRegistry ক্লাস ডেভেলপারদের তাদের অ্যাপে ব্যবহৃত বৈশিষ্ট্য এবং ডিভাইসের ধরন স্পষ্টভাবে উল্লেখ করার অনুমতি দিয়ে তাদের অ্যাপ বাইনারি সাইজ অপ্টিমাইজ করতে সাহায্য করে।

মনে রাখবেন, অনুমতি ও ফ্যাক্টরি রেজিস্ট্রি আলাদা করা আছে। তাই, অনুমতি ব্যবহার করে আপনার অ্যাপের জন্য উপলভ্য কিন্তু ফ্যাক্টরি রেজিস্ট্রি অন্তর্ভুক্ত নয় এমন রেজিস্টার না করা ট্রেড ও ধরন অটোমেশন API ব্যবহার করে অ্যাক্সেস করা যায় না এবং বাল্ক traits() বা types() মেথড কলে সেগুলি রিটার্ন করা হয় না।