Permissions API ใน Android

ก่อนที่จะใช้ Home API ใดก็ตามสำหรับ Android แอปต้องมีสิทธิ์เข้าถึงอุปกรณ์ในบ้านของผู้ใช้ ซึ่งใน API จะเรียกว่า โครงสร้าง โดยผู้ใช้สามารถใช้บัญชี Google ของตนเองเพื่อให้สิทธิ์เข้าถึงอุปกรณ์ในบ้านแก่แอปที่ใช้ Home API ได้ด้วย Permissions API

โฟลว์การให้สิทธิ์ช่วยให้ผู้ใช้สร้างโครงสร้างได้หากยังไม่ได้ตั้งค่าไว้ โดยไม่ต้องใช้Google Home app (GHA)

ผสานรวม Permissions API

โปรดตรวจสอบว่าคุณได้ทำตามขั้นตอน เริ่มต้นใช้งาน Home 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 เพื่อเปิด UI การให้สิทธิ์และประมวลผลผลลัพธ์

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}")
      }
    }
  }
}
PermissionsManager

คุณต้อง ตั้งค่า OAuth สำหรับแอปเรียบร้อยแล้วเพื่อให้ UI การให้สิทธิ์เปิดขึ้นอย่างถูกต้อง

ให้สิทธิ์

ตอนนี้คุณควรจะเรียกใช้แอปและให้ผู้ใช้ให้สิทธิ์ได้แล้ว ประเภทของผู้ใช้ที่ให้สิทธิ์ได้และประเภทอุปกรณ์ที่ให้สิทธิ์ได้จะแตกต่างกันไปตามว่าคุณได้ลงทะเบียนแอปใน Google Home Developer Console หรือไม่

Developer Console ต้องลงทะเบียนเพื่อเผยแพร่แอปโดยใช้ Home API แต่ไม่จำเป็นต้องลงทะเบียนเพื่อทดสอบและใช้ Home API

หากแอปไม่ได้ลงทะเบียนใน Developer Console แอปจะอยู่ใน สถานะ ไม่ได้รับการยืนยัน เราขอแนะนำให้ใช้สถานะนี้เพื่อทดสอบการใช้ Home API ดังนี้

  • เฉพาะผู้ใช้ที่ ลงทะเบียนเป็นผู้ใช้ทดสอบในคอนโซล OAuth เท่านั้นที่จะให้สิทธิ์ สำหรับแอปได้ แอปที่ไม่ได้รับการยืนยัน มีผู้ใช้ทดสอบได้สูงสุด 100 ราย

  • แอปที่ไม่ได้รับการยืนยันจะเข้าถึงอุปกรณ์ประเภทต่างๆ ที่ OAuth สำหรับ Home API รองรับ (รายการประเภทอุปกรณ์ใน Developer Console) ได้ ระบบจะให้สิทธิ์อุปกรณ์ทั้งหมดในโครงสร้าง

หาก แอปได้ลงทะเบียนใน Developer Console และ ได้รับการอนุมัติให้เข้าถึงอุปกรณ์ประเภทอย่างน้อย 1 ประเภท รวมถึงการยืนยัน แบรนด์สำหรับ OAuthเสร็จสมบูรณ์แล้ว แอปจะอยู่ในสถานะ ได้รับการยืนยัน คุณต้องมีสถานะนี้เพื่อเปิดตัวแอปในเวอร์ชันที่ใช้งานจริง

  • ไม่มีการจำกัดผู้ใช้ทดสอบอีกต่อไป ผู้ใช้ทุกคนให้สิทธิ์เข้าถึงแอปได้
  • ผู้ใช้จะให้สิทธิ์เข้าถึงได้เฉพาะอุปกรณ์ประเภทที่ได้รับการอนุมัติใน Developer Consoleเท่านั้น

เมื่อตั้งค่า OAuth แล้ว การเรียกใช้ requestPermissions() ของแอปจะทริกเกอร์กล่องโต้ตอบต่อไปนี้

  1. ระบบจะแจ้งให้ผู้ใช้เลือกบัญชี Google ที่ต้องการใช้
  2. ระบบจะแจ้งให้ผู้ใช้เลือกโครงสร้างที่ต้องการให้สิทธิ์เข้าถึงแก่แอป
    1. สำหรับแอปที่ไม่ได้รับการยืนยัน แอปจะเข้าถึงอุปกรณ์ประเภทต่างๆ ที่ Home API รองรับได้ทั้งหมด
    2. สำหรับแอปที่ได้รับการยืนยัน ผู้ใช้จะให้สิทธิ์เข้าถึงได้เฉพาะอุปกรณ์ประเภทที่ได้รับการอนุมัติใน Developer Console เท่านั้น
    3. สำหรับอุปกรณ์ประเภทที่มีความละเอียดอ่อนซึ่งแอปมีสิทธิ์เข้าถึงเพื่อจัดการ ผู้ใช้สามารถจำกัดสิทธิ์เข้าถึงอุปกรณ์แต่ละเครื่องได้ เช่น หากผู้ใช้มีล็อก 3 รายการ ผู้ใช้จะให้สิทธิ์เข้าถึงล็อกได้เพียง 1 รายการเท่านั้น
  • ความยินยอม OAuth - เลือกบัญชี
  • คำยินยอม OAuth - ลิงก์อุปกรณ์ 01
  • คำยินยอม OAuth - ลิงก์อุปกรณ์ 02
รูปที่ 1: ตัวอย่างโฟลว์คำยินยอม OAuth

เมื่อได้รับสิทธิ์แล้ว แอปจะใช้ Home API เพื่ออ่านสถานะและควบคุมอุปกรณ์ในโครงสร้างได้ หากผู้ใช้ไม่ให้สิทธิ์เข้าถึงอุปกรณ์ประเภทใดประเภทหนึ่งหรืออุปกรณ์ที่มีความละเอียดอ่อน แอปจะไม่สามารถใช้ Home API เพื่อเข้าถึง ควบคุม หรือตั้งค่าให้ทำงานอัตโนมัติได้

เปลี่ยนแปลงสิทธิ์

หากต้องการให้สิทธิ์เข้าถึงอุปกรณ์ในโครงสร้างอื่น คุณสามารถเปิดตัวเลือกบัญชีเพื่อให้ผู้ใช้เลือกบัญชี Google และโครงสร้างที่จะเปลี่ยนไปใช้ได้ ในระหว่างกระบวนการนี้ ผู้ใช้จะเห็นหน้าจอขอความยินยอมอีกครั้ง แม้ว่าจะให้ความยินยอมไปแล้วก่อนหน้านี้ก็ตาม

คุณสามารถทำได้โดยเรียกใช้ requestPermissions() อีกครั้งโดยตั้งค่าแฟล็ก forceLaunch เป็น true ดังนี้

homeManager.requestPermissions(forceLaunch=true)

เปลี่ยนแปลงสิทธิ์โดยใช้คำแนะนำโครงสร้าง

คำแนะนำโครงสร้างช่วยให้แอปเลือกโครงสร้างที่เฉพาะเจาะจงไว้ล่วงหน้า หรือจำกัดรายการโครงสร้างที่พร้อมใช้งาน เมื่อขอเปลี่ยนแปลงสิทธิ์เข้าถึง Home API ของผู้ใช้ การส่งพารามิเตอร์โครงสร้างไปยังคำขอการให้สิทธิ์จะทำให้กล่องโต้ตอบการให้สิทธิ์มุ่งเน้นไปที่โครงสร้างที่เลือกโดยอัตโนมัติ ซึ่งจะช่วยลดความยุ่งยากของผู้ใช้และป้องกันข้อผิดพลาดในการกำหนดค่า

คุณจัดการคำแนะนำโครงสร้างได้โดยใช้ ConsentScreenOptions คลาสข้อมูล คลาส ConsentScreenOptions ยอมรับพารามิเตอร์การกำหนดค่าต่อไปนี้

  • structureId — รหัสโครงสร้างที่เฉพาะเจาะจงเพื่อเลือกไว้ล่วงหน้าในกล่องโต้ตอบการให้สิทธิ์ คุณจะได้รับรหัสนี้โดยการตรวจสอบพร็อพเพอร์ตี้ โครงสร้างของโครงสร้างที่กำลัง อัปเดต
  • allowedStructureIds — รายการรหัสโครงสร้าง หากระบุไว้ กล่องโต้ตอบการให้สิทธิ์จะกรองโครงสร้างที่พร้อมใช้งานเพื่อแสดงเฉพาะโครงสร้างในรายการนี้ คุณสามารถปล่อยให้พารามิเตอร์นี้ไม่ได้ระบุไว้ในกรณีส่วนใหญ่ เว้นแต่ว่าคุณต้องการให้ผู้ใช้อยู่ในรายการโครงสร้างที่ได้รับสิทธิ์แล้ว
  • allowStructureChange — กำหนดว่าผู้ใช้ได้รับอนุญาตให้เปลี่ยนโครงสร้างที่เลือกไว้ล่วงหน้าหรือไม่ ตั้งค่าพารามิเตอร์นี้เป็น true ในกรณีส่วนใหญ่หากมีการระบุ allowedStructureIds และ structureId อย่างน้อย 1 รายการ เพื่อรองรับลักษณะการทำงานตามธรรมชาติของผู้ใช้

ส่งออบเจ็กต์นี้เป็นพารามิเตอร์ที่ไม่บังคับในการเรียกใช้ 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 ที่ออกให้เมื่อมีการให้ความยินยอมครั้งแรก และจะเพิกถอนสิทธิ์เข้าถึงอินสแตนซ์ของแอปที่ผู้ใช้ใช้งานในทุกแพลตฟอร์ม (โทรศัพท์) และโครงสร้าง

    ระบบอาจเปลี่ยนเส้นทางผู้ใช้ด้วย Deep Link ไปยังหน้าย่อยแอปและบริการของบุคคลที่สาม โดยใช้ URL Scheme ต่อไปนี้

    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

คำสั่ง okGoogle เป็นคำสั่งระดับอุปกรณ์และใช้เพื่อตั้งค่าให้ทำงานอัตโนมัติในอุปกรณ์ใดก็ได้ใน โครงสร้าง อย่างไรก็ตาม แอปที่ใช้ Home API อาจไม่มีสิทธิ์เข้าถึงอุปกรณ์ทุกเครื่อง ตารางต่อไปนี้อธิบายวิธีบังคับใช้สิทธิ์ในกรณีดังกล่าว

การทำงานอัตโนมัติ ลักษณะภาษา การบังคับใช้สิทธิ์
เมื่อถึงเวลา 22:00 น. ให้ประกาศว่า "ได้เวลานอนแล้ว" ผ่านลำโพงห้องนอน AssistantBroadcastTrait ในอุปกรณ์ การสร้างการทำงานอัตโนมัติ:
  • อุปกรณ์ที่ใช้ประกาศต้องเป็นอุปกรณ์ Assistant
  • แอปและผู้ใช้ต้องมีสิทธิ์เข้าถึงอุปกรณ์ที่ใช้ประกาศ
การดำเนินการการทำงานอัตโนมัติ:
  • แอปและผู้ใช้ต้องมีสิทธิ์เข้าถึงอุปกรณ์ที่ใช้ประกาศ
เมื่อถึงเวลา 22:00 น. ให้ประกาศว่า "ได้เวลานอนแล้ว" ผ่านอุปกรณ์ทุกเครื่อง AssistantBroadcastTrait ในโครงสร้าง การสร้างการทำงานอัตโนมัติ:
  • ต้องมีอุปกรณ์ Assistant อย่างน้อย 1 เครื่องในโครงสร้าง ที่แอปและผู้ใช้มีสิทธิ์เข้าถึง
  • แอปและผู้ใช้ต้องมีสิทธิ์เข้าถึงโครงสร้าง
การดำเนินการการทำงานอัตโนมัติ:
  • แอปและผู้ใช้ต้องมีสิทธิ์เข้าถึงโครงสร้าง
เมื่อถึงเวลา 22:00 น. ให้ "เปิดเพลงหน่อย" AssistantFulfillmentTrait.OkGoogleCommand การสร้างการทำงานอัตโนมัติ:
  • แอปและผู้ใช้ต้องมีสิทธิ์เข้าถึงอุปกรณ์ที่ การทำงานอัตโนมัติส่งคำสั่ง
การดำเนินการการทำงานอัตโนมัติ:
  • แอปและผู้ใช้ต้องมีสิทธิ์เข้าถึงอุปกรณ์ที่ การทำงานอัตโนมัติส่งคำสั่ง
เมื่อมีคนพูดว่า "เปิดเพลงหน่อย" VoiceStarterTrait.OkGoogleEvent การสร้างการทำงานอัตโนมัติ:
  • แอปและผู้ใช้ต้องมีสิทธิ์เข้าถึงโครงสร้าง การทำงานอัตโนมัติไม่จำเป็นต้องมีอุปกรณ์ Assistant เพื่อผ่านการตรวจสอบหรือทำงาน เนื่องจากผู้ใช้ที่มีสิทธิ์เข้าถึงโครงสร้างจะใช้โทรศัพท์ (โดยใช้บัญชี Google เดียวกัน) เพื่อโต้ตอบกับ Assistant และทริกเกอร์ VoiceStarter ได้
การดำเนินการการทำงานอัตโนมัติ:
  • แอปไม่จำเป็นต้องมีสิทธิ์เข้าถึงอุปกรณ์ที่ เริ่มการทำงานอัตโนมัติ
  • แอปและผู้ใช้ต้องมีสิทธิ์เข้าถึงอุปกรณ์ที่ การดำเนินการเกิดขึ้น

คำแนะนำในกรณีที่ผู้ใช้เพิกถอนสิทธิ์ทั้งหมด

หากผู้ใช้เพิกถอนสิทธิ์ทั้งหมด การทำงานอัตโนมัติที่มีอยู่ทั้งหมดจะหยุดทำงาน นอกจากนี้ หากผู้ใช้เพิกถอนสิทธิ์เข้าถึงอุปกรณ์ที่เฉพาะเจาะจง ตัวเริ่มต้น เงื่อนไข และการดำเนินการที่เชื่อมโยงกับอุปกรณ์เหล่านั้นจะหยุดทำงาน

โปรดตรวจสอบว่าสิทธิ์ยังคงมีผลอยู่ทุกครั้งที่แอปเริ่มต้น หากสิทธิ์ถูกเพิกถอนแล้ว โปรดตรวจสอบว่าได้นำข้อมูลก่อนหน้านี้ทั้งหมดออกแล้ว ซึ่งรวมถึงข้อมูลที่แคชไว้ในแอปพลิเคชัน