قبل استخدام أي من واجهات برمجة التطبيقات Home API لنظام التشغيل 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
لإعداد واجهات Home API، اتّبِع الخطوات التالية:
احصل على مرجع لسياق
Application. لا يعتمد هذا السياق على أي مراحل نشاط، وسيظل متاحًا طالما أنّ تطبيقك متاح. يمكنك الحصول عليه من خلال استدعاءgetApplicationContext()ضمنActivityأوService:val context = getApplicationContext()أنشئ مثيلاً من
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 إضافتها).
أنشئ مثيلاً من
HomeConfigباستخدام سياق دالة الكوروتينDispatchers.IOومثيل السجلّ.val homeConfig = HomeConfig( coroutineContext = Dispatchers.IO, factoryRegistry = registry)أخيرًا، أنشئ مثيل singleton لـ
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، مثل شاشة طلب الموافقة على الأذونات، بلغة معيّنة، يمكنك استدعاء setLocale() في مثيل HomeClient قبل طلب الأذونات. لمعرفة التفاصيل، يُرجى الاطّلاع على ضبط لغة التطبيق.
تسجيل الدخول باستخدام حساب Google من خلال التطبيق
قد تحتاج إلى إدارة عمليات مصادقة Google للمستخدمين داخل تطبيقك. يتيح لك ذلك استخدام حساب المستخدم نفسه في مختلف خدمات Google، مثل Google Home وDrive و"خرائط Google" وما إلى ذلك.
من خلال تسجيل الدخول إلى Google من التطبيق، يمكنك الحصول على مثيل HomeClient
مرتبط بشكل صريح بمستخدم معيّن، وبالتالي تجاوز أداة اختيار حساب Google
وشاشة طلب الموافقة عندما يكون الحساب مصرّحًا به.
بالإضافة إلى ذلك، يمنع هذا النهج المستخدمين من رؤية شاشتَين مختلفتَين لاختيار الحساب، إحداهما من صفحة تسجيل الدخول إلى التطبيق والأخرى من Google Home.
لإجراء ذلك، عليك الرجوع إلى مقالة مصادقة المستخدمين من خلال ميزة "تسجيل الدخول باستخدام حساب Google" وإكمال الخطوات التالية:
إنشاء معرِّف عميل لتطبيق ويب يستخدم بروتوكول OAuth
- افتح Google Cloud Console
- انتقِل إلى صفحة "بيانات الاعتماد" في Google Cloud Console.
- اختَر مشروعًا حاليًا أو أنشِئ مشروعًا جديدًا.
- ضبط شاشة طلب الموافقة المتعلّقة ببروتوكول OAuth (إذا لم يسبق لك ضبطها)
- قبل إنشاء بيانات الاعتماد، تأكَّد من ضبط شاشة طلب الموافقة عبر OAuth باستخدام تفاصيل تطبيقك، بما في ذلك عناوين URL لسياسة الخصوصية وبنود الخدمة.
- إنشاء معرّف عميل OAuth (نوع تطبيق الويب)
- في صفحة "بيانات الاعتماد"، انقر على
+ CREATE CREDENTIALSواختَر معرِّف عميل OAuth من القائمة المنسدلة. - في حقل نوع التطبيق، اختَر تطبيق الويب.
- أدخِل اسمًا لعميل الويب (مثلاً، "الواجهة الخلفية لتطبيق الويب").
- انقر على "إنشاء".
- في صفحة "بيانات الاعتماد"، انقر على
- استرداد معرِّف العميل
- بعد الإنشاء، ستعرض وحدة التحكّم معرّف العميل الجديد. هذه هي القيمة التي ستستخدمها في تطبيق 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:
registerActivityResultCallerForPermissions()مع إشارة إلى ActivityResultCaller الذي تريد استخدامه.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)
لعرض شاشة طلب الموافقة بلغة معيّنة، يمكنك استدعاء client.setLocale() قبل استدعاء requestPermissions(). يُرجى الاطّلاع على
ضبط لغة التطبيق لمعرفة التفاصيل، وعلى
واجهة برمجة التطبيقات Permissions API لمزيد من المعلومات حول إدارة أذونات
واجهات برمجة تطبيقات Home.
إعادة تحميل النشاط بالكامل باستخدام HomeClient الجديد
بعد الحصول على مثيل جديد من HomeClient، عليك إعادة تحميل النشاط بالكامل لإعادة الاشتراك واسترجاع البُنى والأجهزة الكاملة والبيانات الأخرى ذات الصلة المرتبطة بحساب المستخدم هذا.
تسجيل السمات وأنواع الأجهزة
تساعد فئة FactoryRegistry المطوّرين في تحسين حجم الملف الثنائي لتطبيقاتهم من خلال السماح لهم بالإشارة صراحةً إلى السمات وأنواع الأجهزة التي يستخدمها تطبيقهم.
يُرجى العِلم أنّ الأذونات وسجلّ المصنع منفصلان. لذلك، لا يمكن الوصول إلى السمات والأنواع غير المسجّلة والمتاحة لتطبيقك باستخدام الأذونات ولكنّها غير مضمّنة في سجلّ المصنع باستخدام واجهة برمجة التطبيقات Automation API، ولا يتم عرضها في طلبات إجراء traits() أو types() المجمّعة.
DeviceGroup، وهو يختلف عن HomeDevice. للاستعلام عن مجموعات الأجهزة والتفاعل معها، أدرِج DeviceGroup في قائمة entityTypes عند إعداد FactoryRegistry، بالإضافة إلى السمات Group وGroupManagement وGroupMembership.
لمزيد من المعلومات، يُرجى الاطّلاع على مجموعات الأجهزة.
ضبط لغة التطبيق
استخدِم setLocale() وgetLocale() في مثيل HomeClient لضبط اللغة المفضّلة لتطبيقك واستردادها. يجب أن تكون اللغة علامة لغة صالحة وفقًا لمعيار BCP-47، مثل "en-US" أو "en-GB" أو "ja".
عند ضبط لغة على "HomeClient"، تستخدم واجهات برمجة تطبيقات Home هذه اللغة لسير عمل واجهة المستخدم المُستضاف على Google، بما في ذلك واجهة مستخدم الأذونات وعمليات تشغيل Matter وإزالة الأجهزة. في حال عدم ضبط لغة، سيتم ضبط هذه المسارات تلقائيًا على لغة التطبيق أو الجهاز.
- يؤدي استدعاء
setLocale()قبل تسجيل المستخدم الدخول ومنح الأذونات إلى تخزين اللغة في الذاكرة وتطبيقها على مسار واجهة المستخدم الأولية للأذونات. بعد تسجيل المستخدم الدخول وتوفُّر بنية، تتم مزامنة اللغة مع السحابة الإلكترونية من خلال حزمة تطوير البرامج (SDK). إذا كان لدى المستخدم لغة محفوظة في السحابة الإلكترونية لتطبيقك، ستكون لإعدادات السحابة الإلكترونية الأولوية في المزامنة الأولية. - يؤدي استدعاء
setLocale()أثناء تسجيل الدخول إلى تحديث اللغة في الذاكرة وحفظها في السحابة الإلكترونية لهذا المستخدم والتطبيق.
// Set the locale using a BCP-47 language tag
coroutineScope.launch {
homeManager.setLocale("ja")
}
// Retrieve the configured locale, or null if not set
val currentLocale: String? = homeManager.getLocale()
المزامنة مع إعدادات اللغة المخصّصة حسب التطبيقات في Android
إذا كان تطبيقك يتيح استخدام إعدادات اللغة المخصصة حسب التطبيقات على Android باستخدام
LocaleManager،
يُرجى استدعاء homeManager.setLocale() قبل تعديل
LocaleManager.applicationLocales. يؤدي تعديل applicationLocales إلى إعادة إنشاء Activity النشط، ما قد يؤدي إلى إلغاء دالة coroutine قيد التنفيذ إذا تم استدعاء setLocale() بعد ذلك.
coroutineScope.launch {
val languageTag = "fr-CA"
// 1. Persist the locale to HomeClient first
homeManager.setLocale(languageTag)
// 2. Update Android's per-app locale (recreates the Activity)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
context.getSystemService(LocaleManager::class.java).applicationLocales =
LocaleList.forLanguageTags(languageTag)
}
}