واجهة Permissions API على Android

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

يسمح مسار الأذونات للمستخدِم بإنشاء بنية إذا لم يتم إعدادها من قبل ، بدون الحاجة إلى استخدام 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 لنشر تطبيق باستخدام واجهات برمجة التطبيقات لمنزل Google. ولكن لا يجب التسجيل لاختبار واجهات برمجة التطبيقات لمنزل Google واستخدامها.

إذا لم يكن التطبيق مسجّلاً في Developer Console، سيظهر في حالة غير مُثبَتة. ننصح بذلك لاختبار استخدام واجهات برمجة التطبيقات لمنزل Google:

  • لا يمكن منح الأذونات للتطبيق إلا للمستخدِمين المسجّلين كمستخدِمين اختباريين في وحدة تحكّم 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

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

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

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

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

homeManager.requestPermissions(forceLaunch=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
            }
        }
    }
}

أذونات "مساعد Google"

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

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

إرشادات في حال إبطال المستخدِم الأذونات الكاملة

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

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