واجهة Permissions API على Android

قبل استخدام أي من واجهات برمجة التطبيقات Home APIs لنظام التشغيل Android، يجب أن يحصل التطبيق على إذن بالوصول إلى الأجهزة في منزل المستخدم، ويُشار إليها في واجهة برمجة التطبيقات باسم البنية. باستخدام Permissions API، يمكن للمستخدم منح تطبيقات Home APIs إذن الوصول إلى الأجهزة في منزله باستخدام حسابه على Google.

يتيح مسار الأذونات للمستخدم إنشاء بنية إذا لم يتم إعدادها من قبل، بدون الحاجة إلى استخدام Google Home app (GHA).

دمج واجهة Permissions API

قبل المتابعة، تأكَّد من اتّباع الخطوات الواردة في مقالة إعداد المنزل على Android. يتم استخدام مثيل homeManager من تلك الخطوة في جميع أمثلة الأذونات الواردة هنا.

عليك أولاً تسجيل ActivityResultCaller باستخدام حزمة تطوير البرامج (SDK). إليك مثلاً طريقة تعامل التطبيق النموذجي مع ذلك:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    homeManager.registerActivityResultCallerForPermissions(this)
  }

التحقّق من الأذونات

قبل طلب الأذونات، ننصحك بالتحقّق مما إذا كان مستخدم التطبيق قد منح موافقته على الوصول إلى البنية. لإجراء ذلك، استدعِ طريقة hasPermissions() الخاصة بمثيل Home للحصول على Flow من قيم PermissionsState:

val permissionsReadyState =
homeManager.hasPermissions().collect { state ->
    when (state) {
      PermissionsState.GRANTED -> println("Permissions granted, no need to request permissions")
      PermissionsState.PERMISSIONS_STATE_UNAVAILABLE ->
          println("Permissions state unavailable, request permissions")

      PermissionsState.NOT_GRANTED ->
          println("OAuth permission is enabled but not granted yet, request permissions")

      PermissionsState.PERMISSIONS_STATE_UNINITIALIZED -> println(
          "Permissions state is not initialized yet. Clients should wait for another status update"
      )
      else ->
          throw IllegalStateException("""
            HomeClient.hasPermissions state should be PermissionsState.GRANTED,
            PermissionState.PERMISSIONS_STATE_UNINITIALIZED, or
            PermissionsState.PERMISSIONS_STATE_UNAVAILABLE. Actual state: $state
          """.trimIndent())
    }
}

إذا عرضت عملية التحقّق القيمة PermissionsState NOT_GRANTED أو PERMISSIONS_STATE_UNAVAILABLE، يعني ذلك أنّ المستخدم أو التطبيق لا يمكنه الوصول إلى البنية. إذا عرضت عملية التحقّق PermissionsState من GRANTED ولكن لم تعرض مكالمة لاحقة إلى structures() أي بنى، يعني ذلك أنّ المستخدم إما ألغى إذن الوصول إلى التطبيق من خلال صفحة إعدادات GHA، أو أنّ المستخدم لا يملك إذن الوصول المطلوب.

طلب الحصول على الأذونات

يجب منح تطبيقك الإذن بالوصول إلى البُنى والأجهزة داخل بنية معيّنة.

إذا لم يمنح المستخدم الأذونات من قبل، استخدِم طريقة requestPermissions() في مثيل Home لتشغيل واجهة مستخدم الأذونات ومعالجة النتيجة:

fun requestPermissions(scope: CoroutineScope, onShowSnackbar: (String) -> Unit) {
  scope.launch {
    val result =
      try {
        homeManager.requestPermissions()
      } catch (e: HomeException) {
        PermissionsResult(
          PermissionsResultStatus.ERROR,
          "Got HomeException with error: ${e.message}",
        )
      }
    when (result.status) {
      PermissionsResultStatus.SUCCESS -> {
        Log.i(TAG, "Permissions successfully granted.")
      }
      PermissionsResultStatus.CANCELLED -> {
        Log.i(TAG, "User cancelled Permissions flow.")
        onShowSnackbar("User cancelled Permissions flow")
      }
      else -> {
        Log.e(
          TAG,
          "Failed to grant permissions with error: ${result.status}, ${result.errorMessage}",
        )
        onShowSnackbar("Failed to grant permissions with error: ${result.errorMessage}")
      }
    }
  }
}

لكي يتم تشغيل واجهة مستخدم الأذونات بشكلٍ صحيح، يجب أن تكون قد أعددت بروتوكول OAuth لتطبيقك.

منح الأذونات

من المفترض أن تتمكّن الآن من تشغيل تطبيقك ومنح المستخدم أذونات. يختلف نوع المستخدمين الذين يمكنهم منح الإذن وأنواع الأجهزة التي يمكن منح الأذونات لها حسب ما إذا كنت قد سجّلت تطبيقك في Google Home Developer Console.

يجب التسجيل في Developer Console لنشر تطبيق باستخدام واجهات برمجة التطبيقات الخاصة بمنصة Home. ليس من الضروري اختبار واجهات برمجة التطبيقات الخاصة بالشاشة الرئيسية واستخدامها.

إذا لم يتم تسجيل تطبيق في Developer Console، ستكون حالته لم يتم التحقّق منه. ننصحك بما يلي لاختبار استخدام واجهات برمجة التطبيقات الخاصة بمنصة Home:

  • يمكن فقط للمستخدمين المسجَّلين كمستخدمين اختباريين في وحدة تحكّم OAuth منح أذونات للتطبيق، علمًا بأنّ عدد المستخدمين الاختباريين المسموح به هو 100 مستخدم للتطبيق الذي لم يتم التحقّق منه.

  • سيتمكّن التطبيق الذي لم يتم إثبات ملكيته من الوصول إلى أجهزة من أي أنواع أجهزة متوافقة مع OAuth لواجهات برمجة التطبيقات لمنزل Google (قائمة أنواع الأجهزة في Developer Console). وسيتم منح الإذن لجميع الأجهزة في البنية.

إذا تم تسجيل تطبيق في Developer Console وتمت الموافقة على منحه إذن الوصول إلى نوع جهاز واحد أو أكثر، وتم إكمال عملية إثبات ملكية العلامة التجارية في OAuth، ستكون حالة التطبيق معتمَدة. هذه الحالة مطلوبة لإطلاق تطبيق في مرحلة الإنتاج:

  • لم يعُد يتم تطبيق حدود على المستخدمين التجريبيين. يمكن لأي مستخدم منح الإذن للتطبيق.
  • يمكن للمستخدم منح الإذن لأنواع الأجهزة التي تمت الموافقة عليها في Developer Console فقط.

بعد إعداد OAuth، يؤدي طلب التطبيق إلى requestPermissions() إلى ظهور مربّعات الحوار التالية:

  1. يُطلب من المستخدم اختيار حساب Google الذي يريد استخدامه.
  2. سيُطلب من المستخدم اختيار البنية التي يريد منح التطبيق إذن الوصول إليها.
    1. بالنسبة إلى التطبيق الذي لم يتم التحقّق منه، تتوفّر للتطبيق جميع أنواع الأجهزة المتوافقة مع واجهات برمجة التطبيقات لمنزل Google.
    2. بالنسبة إلى التطبيق الذي تم التحقّق منه، يمكن للمستخدم منح الإذن فقط لأنواع الأجهزة التي تمت الموافقة عليها في Developer Console.
    3. بالنسبة إلى أنواع الأجهزة الحسّاسة التي يمكن للتطبيق الوصول إليها لإدارتها، يمكن للمستخدم حظر الوصول إليها على أساس كل جهاز على حدة. على سبيل المثال، إذا كان لدى المستخدم ثلاثة أقفال، يمكنه منح إذن الوصول إلى قفل واحد فقط من هذه الأقفال.
  • موافقة OAuth - اختيار حساب
  • OAuth consent - link devices 01
  • موافقة OAuth - ربط الجهاز 02
الشكل 1: مثال على مسار طلب الموافقة المتعلّق ببروتوكول OAuth

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

تغيير الأذونات

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

يمكن إجراء ذلك من خلال طلب requestPermissions() مرة أخرى مع ضبط العلامة forceLaunch على true:

homeManager.requestPermissions(forceLaunch=true)

تغيير الأذونات باستخدام تلميحات البنية

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

تتم إدارة تلميحات البنية باستخدام فئة البيانات ConsentScreenOptions. يقبل الصف ConsentScreenOptions معلَمات الإعداد التالية:

  • structureId: رقم تعريف البنية المحدّد الذي سيتم اختياره مسبقًا في مربّع حوار الأذونات. يمكنك الحصول على ذلك من خلال التحقّق من خصائص البنية للبنية التي يتم تعديلها.
  • allowedStructureIds: قائمة بمعرّفات البنية. في حال توفيرها، سيقوم مربّع حوار الأذونات بفلترة البُنى المتاحة لعرض تلك الواردة في هذه القائمة فقط. يمكن ترك هذا الحقل بدون تحديد في معظم الحالات، إلا إذا كنت تريد التأكّد من أنّ المستخدم يبقى ضمن قائمة الهياكل التي تم منحها سابقًا.
  • allowStructureChange: تحدّد ما إذا كان يُسمح للمستخدم بتغيير البنية المحدّدة مسبقًا. اضبط هذا الخيار على true إذا تم تحديد allowedStructureIds و/أو structureId في معظم الحالات لدعم السلوك الطبيعي للمستخدم.

مرِّر هذا العنصر كمَعلمة اختيارية في طلب requestPermissions()، مع ضبط العلامة forceLaunch على true:

import com.google.home.ConsentScreenOptions

// Create the ConsentScreenOptions class, allowing structure changes while
// ensuring the permissions dialog pre-selects the target structure on launch
val consentOptions = ConsentScreenOptions(
    structureId = target-structure-id,
    allowStructureChange = true
)

homeManager.requestPermissions(forceLaunch=true, consentOptions)

سيتم عرض شاشة طلب الموافقة على المستخدم بعد فلترتها لتتضمّن البنية المحدّدة في عنصر ConsentScreenOptions.

السماح للمستخدم بتبديل البُنى باستخدام تلميحات البُنى

إذا كان لدى المستخدم عدة بنى في أحد التطبيقات وأردت تحديد بنية مسبقًا مع السماح له بالتبديل بين البنى المتاحة، فعِّل تغييرات البنية باستخدام العلامة allowStructureChange وقدِّم قائمة بالبنى في allowedStructureIds:

val consentOptions = ConsentScreenOptions(
    structureId = target-structure-id,
    allowedStructureIds = listOf(target-structure-id, another-structure-id),
    allowStructureChange = true
)

إبطال الأذونات

يمكن للمستخدمين إبطال إذن الوصول الذي تم منحه سابقًا باتّباع الخطوات التالية:

  1. من خلال صفحة"حسابي " على Google > البيانات والخصوصية > التطبيقات والخدمات الخارجية سيؤدي ذلك إلى إبطال الرمز المميّز لبروتوكول OAuth الذي تم إصداره عند منح الموافقة الأولية، وإلغاء إذن الوصول إلى أي مثيل من التطبيق كان يستخدمه المستخدم على جميع الأجهزة (الهواتف) والمساحات.

    يمكن توجيه المستخدم باستخدام رابط عميق إلى الصفحة الفرعية التطبيقات والخدمات التابعة لجهات خارجية باستخدام مخطّط URL التالي:

    https://myaccount.google.com/connections/link?project_number=Cloud project_number
    
  2. من خلال صفحة GHA > الإعدادات > التطبيقات المرتبطة سيؤدي النقر على في GHA إلى نقلك إلى صفحة الإعدادات. بعد ذلك، انقر على مربّع التطبيقات المرتبطة الذي ينقلك إلى صفحة تشبه شاشة طلب الموافقة. يمكن للمستخدم من هذه الصفحة إزالة إذن الوصول إلى التطبيق، كما يمكنه استخدام الصفحة نفسها لتغيير أنواع الأجهزة أو الأجهزة الحساسة المحددة التي يمكن للتطبيق الوصول إليها.

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

لتحديد ما إذا كان المستخدم قد منح الإذن بالوصول إلى نوع جهاز حسّاس أو مقيّد، استخدِم الدالة consentedDeviceTypes() على مستوى البنية:

import com.google.home.Structure
import com.google.home.DeviceType
import com.google.home.DeviceTypeFactory
import com.google.home.consentedDeviceTypes // Extension function from the SDK
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch

/**
 * Example of how an app may monitor which device types have been granted access by a user.
 */
fun monitorDeviceConsent(structure: Structure, myScope: CoroutineScope) {
    // Obtain the flow of consented device type factories
    val consentedTypesFlow: Flow<Set<DeviceTypeFactory<out DeviceType>>> =
        structure.consentedDeviceTypes()

    myScope.launch {
        consentedTypesFlow.collect { consentedSet ->
            // Check if the user has consented to share a specific restricted
            // type, such as a Doorbell or Camera.
            val hasCameraAccess = consentedSet.any {
                it.toString() == "matter.google.type.GoogleDoorbellDevice"
            }

            if (hasCameraAccess) {
                // Enable features that require camera access
            } else {
                // Inform the user or disable camera-specific features
            }
        }
    }
}

OkGoogle permissions

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

التشغيل الآلي السمة فرض الأذونات
في الساعة 10:00 مساءً، أريد أن يتم بث رسالة مضمونها "حان وقت النوم" على مكبّر صوت غرفة النوم. AssistantBroadcastTrait على الجهاز إنشاء عملية مبرمَجة:
  • يجب أن يكون الجهاز الذي يتم البث منه مزوّدًا بخدمة "مساعد Google".
  • يجب أن يكون لدى التطبيق والمستخدم إذن بالوصول إلى الجهاز الذي يتم البث عليه.
تنفيذ عملية التشغيل الآلي:
  • يجب أن يكون لدى التطبيق والمستخدم إذن بالوصول إلى الجهاز الذي يتم البث عليه.
في الساعة 10:00 مساءً، أريد أن يتم بث رسالة مضمونها "حان وقت النوم" على جميع الأجهزة AssistantBroadcastTrait على البنية. إنشاء عملية مبرمَجة:
  • يجب أن يكون هناك جهاز واحد على الأقل مزوّد بخدمة &quot;مساعد Google&quot; في البنية يمكن للتطبيق والمستخدم الوصول إليه.
  • يجب أن يكون لدى التطبيق والمستخدم إذن الوصول إلى البنية.
تنفيذ عملية التشغيل الآلي:
  • يجب أن يكون لدى التطبيق والمستخدم إذن الوصول إلى البنية.
في الساعة 10:00 مساءً، "تشغيل بعض الموسيقى" AssistantFulfillmentTrait.OkGoogleCommand إنشاء عملية مبرمَجة:
  • يجب أن يكون لدى التطبيق والمستخدم إذن بالوصول إلى الأجهزة التي تصدر إليها الأوامر الآلية.
تنفيذ عملية التشغيل الآلي:
  • يجب أن يكون لدى التطبيق والمستخدم إذن بالوصول إلى الأجهزة التي تصدر إليها عملية التشغيل الآلي الأوامر.
عندما يقول أحد الأشخاص "تشغيل بعض الموسيقى" VoiceStarterTrait.OkGoogleEvent إنشاء عملية مبرمَجة:
  • يجب أن يكون لدى التطبيق والمستخدم إذن الوصول إلى البنية. لا تتطلّب عملية التشغيل الآلي جهازًا مزوّدًا بخدمة "مساعد Google" لإجراء عملية التحقّق أو التشغيل، لأنّه يمكن لأي مستخدم لديه إذن الوصول إلى المساحة استخدام هاتفه (باستخدام حساب Google نفسه) للتفاعل مع "مساعد Google" وتشغيل VoiceStarter.
تنفيذ عملية التشغيل الآلي:
  • لا يتطلّب التطبيق إذنًا للوصول إلى الجهاز الذي يبدأ التشغيل الآلي.
  • يجب أن يكون لدى التطبيق والمستخدم إذن بالوصول إلى الجهاز الذي يتم تنفيذ الإجراء عليه.

إرشادات في حال ألغى المستخدم الأذونات الكاملة

إذا ألغى المستخدم الأذونات الكاملة، ستتوقف جميع عمليات التشغيل الآلي الحالية عن العمل. في حال إلغاء المستخدم إذن الوصول إلى أجهزة معيّنة، سيتوقف عمل إجراءات التفعيل والشروط والإجراءات المرتبطة بهذه الأجهزة.

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