Permissions API در Android

قبل‌از استفاده از هرکدام از Home APIs برای Android، برنامه باید اجازه دسترسی به دستگاه‌های موجود در خانه کاربر را داشته باشد که در میانای برنامه‌سازی کاربردی به آن ساختار گفته می‌شود. با Permissions API، کاربر می‌تواند بااستفاده از «حساب Google» خود، به برنامه‌های Home APIs اجازه دهد به دستگاه‌های موجود در خانه‌اش دسترسی داشته باشند.

جریان اجازه به کاربر امکان می‌دهد ساختاری ایجاد کند و نشانی خیابان آن را اختصاص دهد، اگر قبلاً تنظیم نشده باشد، بدون اینکه مجبور باشد از Google Home app (GHA) استفاده کند.

ادغام کردن Permissions API

قبل‌از ادامه دادن، مطمئن شوید که راه‌اندازی خانه در Android را دنبال کرده‌اید. در همه مثال‌های «اجازه‌ها» در اینجا، از نمونه homeManager آن مرحله استفاده می‌شود.

ابتدا، ActivityResultCaller را با کیت توسعه نرم‌افزار ثبت کنید. برای مثال، «برنامه نمونه» این کار را به این صورت انجام می‌دهد:

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 را برای برنامه‌تان راه‌اندازی کرده باشید.

رابط کاربری رضایت «اجازه‌ها» در منطقه زبانی پیکربندی‌شده با HomeClient.setLocale() ارائه می‌شود، یا اگر تنظیم نشده باشد، به‌طور پیش‌فرض به منطقه زبانی برنامه یا دستگاه برمی‌گردد. برای نمایش صفحه رضایت به زبانی خاص، setLocale() را در نمونه HomeClient خود قبل‌از فراخوانی requestPermissions() فراخوانی کنید. برای اطلاعات بیشتر، به پیکربندی منطقه زبانی برنامه مراجعه کنید.

اعطای اجازه‌ها

اکنون باید بتوانید برنامه‌تان را اجرا کنید و از کاربر بخواهید اجازه‌ها را اعطا کند. نوع کاربرانی که می‌توانند اجازه اعطا کنند و نوع دستگاه‌هایی که برای اعطای اجازه دردسترس هستند، بسته به اینکه برنامه‌تان را در Google Home Developer Console ثبت کرده باشید یا نه، متفاوت خواهد بود.

برای انتشار برنامه بااستفاده از ای‌پی‌آی‌های Home، ثبت‌نام Developer Console الزامی است. برای آزمایش و استفاده از Home APIs لازم نیست.

اگر برنامه‌ای در Developer Console ثبت نشده باشد، در وضعیت درستی‌سنجی‌نشده قرار می‌گیرد. این مورد برای آزمایش کردن استفاده از Home API توصیه می‌شود:

  • فقط کاربرانی که به‌عنوان کاربر آزمایشی در کنسول OAuth ثبت شده‌اند می‌توانند برای برنامه اجازه صادر کنند. برای برنامه تأییدنشده، محدودیت ۱۰۰ کاربر آزمایشی وجود دارد.

  • برنامه تأییدنشده به دستگاه‌هایی از هر نوع دستگاهی که OAuth برای Home API پشتیبانی می‌کند (فهرست انواع دستگاه در Developer Console) دسترسی خواهد داشت. همه دستگاه‌های موجود در ساختار اعطا خواهند شد.

اگر برنامه‌ای در Developer Console ثبت شده باشد و برای دسترسی به یک یا چند نوع دستگاه تأیید شده باشد، و درستی‌سنجی نمانام برای OAuth تکمیل شده باشد، در وضعیت درستی‌سنجی‌شده قرار خواهد گرفت. این وضعیت برای راه‌اندازی برنامه در تولید الزامی است:

  • محدودیت‌های کاربر آزمایشی دیگر اعمال نمی‌شود. هر کاربری می‌تواند به برنامه اجازه دسترسی بدهد.
  • کاربر فقط می‌تواند به انواع دستگاهی که در Developer Console تأیید شده‌اند اجازه دسترسی بدهد.

اکنون که OAuth راه‌اندازی شده است، تماس برنامه با requestPermissions() کادرهای گفتگوی زیر را راه‌اندازی می‌کند:

  1. از کاربر خواسته می‌شود «حساب Google» موردنظرش را برای استفاده انتخاب کند.
  2. از کاربر خواسته می‌شود ساختاری را که می‌خواهد به برنامه اجازه دسترسی به آن را بدهد انتخاب کند.
    1. برای برنامه تأییدنشده، همه انواع دستگاه‌های پشتیبانی‌شده توسط Home APIs برای برنامه دردسترس است.
    2. برای برنامه تأییدشده، کاربر می‌تواند فقط به انواع دستگاه‌هایی اجازه اعطا کند که در Developer Console تأیید شده‌اند.
    3. برای انواع دستگاه‌های حساس که برنامه به مدیریت آن‌ها دسترسی دارد، کاربر می‌تواند دسترسی را به‌صورت دستگاه‌به‌دستگاه محدود کند. برای مثال، اگر کاربری سه قفل داشته باشد، می‌تواند فقط به یکی از آن قفل‌ها دسترسی اعطا کند.
  • رضایت OAuth - انتخاب حساب
  • OAuth consent - link devices 01
  • OAuth consent - link device 02
شکل ۱: نمونه جریان کسب رضایت OAuth

پس‌از اعطای اجازه، برنامه می‌تواند از ای‌پی‌آی‌های Home برای خواندن وضعیت دستگاه‌های موجود در ساختار و کنترل آن‌ها استفاده کند. اگر کاربر برای نوع خاصی از دستگاه یا دستگاه حساس به برنامه اجازه ندهد، برنامه نمی‌تواند از Home API برای دسترسی، کنترل، یا خودکارسازی آن استفاده کند.

تغییر اجازه‌ها

برای اعطای اجازه دسترسی به دستگاه‌ها در ساختاری متفاوت، می‌توان انتخابگر حساب را راه‌اندازی کرد تا کاربر بتواند «حساب Google» و ساختار موردنظر را برای جابه‌جایی انتخاب کند. درطول این فرایند، صفحه رضایت دوباره به کاربر نشان داده می‌شود، حتی اگر قبلاً رضایت داده باشد.

این کار را می‌توان با فراخوانی مجدد requestPermissions() با تنظیم forcePermissionFlow روی ForcePermissionFlow.FORCE_LAUNCH انجام داد:

homeManager.requestPermissions(forcePermissionFlow = ForcePermissionFlow.FORCE_LAUNCH)

تغییر اجازه‌ها با خوانایاری ساختاری

خوانایاری ساختاری به برنامه اجازه می‌دهد هنگام درخواست تغییر افزایشی در اجازه‌های Home APIs کاربر، ساختار خاصی را ازپیش انتخاب کند یا فهرست ساختارهای دردسترس را محدود کند. با ارسال پارامترهای ساختار به درخواست مجوز، کادر گفتگوی اجازه‌ها به‌طور خودکار روی ساختار انتخاب‌شده تمرکز می‌کند، که این امر باعث کاهش اصطکاک کاربر و جلوگیری از خطاهای پیکربندی می‌شود.

خوانایاری ساختاری بااستفاده از کلاس داده ConsentScreenOptions مدیریت می‌شود. کلاس ConsentScreenOptions پارامترهای پیکربندی زیر را می‌پذیرد:

  • structureId — شناسه ساختار خاص برای پیش‌انتخاب در کادر گفتگوی اجازه. این را با بررسی ویژگی‌های ساختار برای ساختاری که به‌روز می‌شود دریافت کنید.
  • allowedStructureIds — فهرستی از شناسه‌های ساختمان. اگر ارائه شود، کادر گفتگوی اجازه، ساختارهای دردسترس را فیلتر می‌کند تا فقط موارد موجود در این فهرست را نشان دهد. در بیشتر موارد، این مورد می‌تواند نامشخص باقی بماند، مگراینکه بخواهید مطمئن شوید که کاربر در فهرست ساختارهای ازقبل اعطاشده باقی می‌ماند.
  • allowStructureChange — تعیین می‌کند که آیا کاربر مجاز است ساختار ازپیش انتخاب‌شده را تغییر دهد یا نه. اگر حداقل یکی از allowedStructureIds و structureId در اکثر موارد برای پشتیبانی از رفتار طبیعی برای کاربر مشخص شده است، این را روی true تنظیم کنید.

این شیء را به‌عنوان پارامتر اختیاری در تماس requestPermissions() ارسال کنید، درحالی‌که forcePermissionFlow روی ForcePermissionFlow.FORCE_LAUNCH تنظیم شده باشد:

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(forcePermissionFlow = ForcePermissionFlow.FORCE_LAUNCH, consentScreenOptions = consentOptions)

صفحه رضایت ازقبل فیلترشده برای ساختار ذکرشده در شیء ConsentScreenOptions به کاربر نشان داده خواهد شد.

اجازه دادن به کاربر برای عوض کردن ساختارها با خوانایاری ساختاری

اگر کاربری چند ساختار در برنامه‌ای دارد و می‌خواهید یکی را ازپیش انتخاب کنید و درعین‌حال به او اجازه دهید بین ساختارهای دردسترسش جابه‌جا شود، تغییرات ساختار را با پرچم allowStructureChange فعال کنید و فهرستی از ساختارها را در allowedStructureIds ارائه دهید:

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

لغو کردن اجازه‌ها

کاربران می‌توانند دسترسی قبلاً اعطاشده را لغو کنند:

  1. ازطریق تنظیمات «حساب Google» > داده‌ها و حریم خصوصی > برنامه‌ها و سرویس‌های طرف سوم. با این کار، نشان OAuth که هنگام اعطای موافقت اولیه صادر شده بود لغو می‌شود و دسترسی به هر نمونه‌ای از برنامه که کاربر در همه سطوح (تلفن‌ها) و ساختارها استفاده می‌کرد لغو می‌شود.

    کاربر ممکن است با پیوند عمیق به زیرصفحه برنامه‌ها و سرویس‌های شخص ثالث بااستفاده از طرح‌واره نشانی وب زیر هدایت شود:

    https://myaccount.google.com/connections/link?project_number=Cloud project_number
    
  2. ازطریق صفحه GHA > تنظیمات > برنامه‌های پیوندشده. با کلیک کردن روی در GHA به صفحه تنظیمات هدایت می‌شوید. از آنجا، روی کاشی برنامه‌های پیوندشده کلیک کنید که شما را به صفحه‌ای می‌برد که شبیه صفحه رضایت است. از این صفحه کاربر می‌تواند دسترسی به برنامه را بردارد. کاربر می‌تواند از همین صفحه برای تغییر انواع دستگاه یا دستگاه‌های حساس خاصی که برای برنامه قابل‌دسترسی هستند استفاده کند.

حذف و صادر کردن داده‌های کاربر

وقتی کاربر «حساب Google» خود را حذف می‌کند یا از ساختاری خارج می‌شود، پلتفرم به‌طور خودکار حذف داده‌های پس‌زمینه را مدیریت می‌کند:

  • اگر کاربر حذف‌شده تنها مالک ساختار باشد، پلاتفرم ساختار و دستگاه‌های مرتبط با آن را حذف می‌کند.
  • اگر مالکان دیگری در ساختار مشترک باقی بمانند، ساختار و دستگاه‌های مشترک آن برای اعضای باقی‌مانده حفظ می‌شود. پلاتفرم عضویت کاربر خارج‌شده را برمی‌دارد و پیوند همه دستگاه‌های شخص ثالث Cloud-to-cloud را که فقط ازطریق اطلاعات کاربری آن کاربر متصل شده‌اند لغو می‌کند.
  • حذف حساب فوراً و برای همیشه داده‌های ساختار کاربر و اجازه‌های برنامه را برمی‌دارد. حتی اگر کاربر بعداً «حساب Google» خود را بازیابی کند، ساختارها و اجازه‌های او بازیابی نمی‌شود.

Home APIs نقاط پایانی برای صادر کردن یا حذف کردن داده‌های «حساب Google» کاربر ارائه نمی‌دهد. کاربران دارای «حساب Google» را به بیرون‌بر Google هدایت کنید تا داده‌های Google Home خود را صادر کنند و به تنظیمات «حساب Google» خود بروند تا حذف حساب را مدیریت کنند.

در بوم‌سازگان 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

فرمان okGoogle فرمانی در سطح دستگاه است و می‌توان از آن برای خودکارسازی هر دستگاهی در ساختار استفاده کرد. بااین‌حال، ممکن است برنامه Home APIs به همه دستگاه‌ها دسترسی نداشته باشد. جدول زیر نحوه اعمال اجازه‌ها را در چنین مواردی شرح می‌دهد.

خودکارسازی ویژگی اجرای اجازه‌ها
ساعت ۱۰:۰۰ ب.ظ.، پیام «وقت خواب» را در بلندگوی اتاق خواب همه‌فرستی کن. ‫ AssistantBroadcastTrait در دستگاه. ایجاد خودکارسازی:
  • دستگاه همه‌فرستی باید دستگاه مجهز به «دستیار» باشد.
  • برنامه و کاربر باید به دستگاهی که همه‌فرستی در آن انجام می‌شود دسترسی داشته باشند.
اجرای خودکارسازی:
  • برنامه و کاربر باید به دستگاهی که همه‌فرستی در آن انجام می‌شود دسترسی داشته باشند.
ساعت ۱۰:۰۰ شب، پیام «وقت خواب» را در همه دستگاه‌ها همه‌فرستی کن AssistantBroadcastTrait روی ساختار. ایجاد خودکارسازی:
  • باید حداقل یک دستگاه مجهز به «دستیار» در ساختار وجود داشته باشد که برنامه و کاربر به آن دسترسی داشته باشند.
  • برنامه و کاربر باید به ساختار دسترسی داشته باشند.
اجرای خودکارسازی:
  • برنامه و کاربر باید به ساختار دسترسی داشته باشند.
ساعت ۱۰:۰۰ شب، «موسیقی پخش کن» AssistantFulfillmentTrait.OkGoogleCommand ایجاد خودکارسازی:
  • برنامه و کاربر باید به دستگاه‌هایی که خودکارسازی به آن‌ها فرمان می‌دهد دسترسی داشته باشند.
اجرای خودکارسازی:
  • برنامه و کاربر باید به دستگاه‌هایی که خودکارسازی به آن‌ها فرمان می‌دهد دسترسی داشته باشند.
هرگاه کسی بگوید «موسیقی پخش کن» VoiceStarterTrait.OkGoogleEvent ایجاد خودکارسازی:
  • برنامه و کاربر باید به ساختار دسترسی داشته باشند. «خودکارسازی» برای گذراندن اعتبارسنجی یا اجرا شدن به دستگاه مجهز به «دستیار» نیاز ندارد، زیرا هر کاربری که به ساختار دسترسی داشته باشد می‌تواند از تلفنش (بااستفاده از همان «حساب Google») برای تعامل با «دستیار» و فعال کردن VoiceStarter استفاده کند.
اجرای خودکارسازی:
  • برنامه برای دسترسی به دستگاهی که خودکارسازی را شروع می‌کند به اجازه نیاز ندارد.
  • برنامه و کاربر باید اجازه دسترسی به دستگاهی را که کنش در آن رخ می‌دهد داشته باشند.

راهنمایی برای زمانی که کاربر اجازه‌های کامل را لغو می‌کند

اگر کاربر اجازه‌های کامل را لغو کند، همه خودکارسازی‌های موجود متوقف خواهند شد. همچنین، اگر کاربر دسترسی به دستگاه‌های خاصی را لغو کند، آغازگرها، شرایط، و کنش‌های مرتبط با آن دستگاه‌ها دیگر کار نخواهند کرد.

هربار که برنامه شروع می‌شود، حتماً بررسی کنید که اجازه‌ها همچنان فعال باشند. اگر لغو شده‌اند، مطمئن شوید که همه داده‌های قبلی، ازجمله داده‌های ذخیره‌شده در حافظه نهان برنامه، برداشته شده باشند.

وقتی دسترسی به ساختمان لغو شود، StructureAccessRevokedEvent به پسای ابری شما ارسال می‌شود. برای گردش کار لغو برنامه تلفن همراه و فضای ابری شریک سرتاسر، به ساختار واگذاری‌ها مراجعه کنید.