Android의 Permissions API

Android용 Home API를 사용하기 전에 앱에 API에서 구조 라고 하는 사용자 홈의 기기에 액세스할 수 있는 권한이 있어야 합니다. 사용자는 Permissions API를 사용하여 Google 계정으로 Home API 앱에 홈의 기기에 대한 액세스 권한을 부여할 수 있습니다.

권한 흐름을 사용하면 사용자가 Google Home app (GHA)을 사용하지 않고도 아직 설정되지 않은 경우 구조를 만들 수 있습니다.

Permissions API 통합

계속하기 전에 Android에서 홈 초기화를 따랐는지 확인하세요. 이 단계의 homeManager 인스턴스는 여기에 있는 모든 권한 예시에서 사용됩니다.

먼저 SDK에 ActivityResultCaller 를 등록합니다. 예를 들어 샘플 앱에서 이 작업을 처리하는 방법은 다음과 같습니다.

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

권한 확인

권한을 요청하기 전에 앱 사용자가 구조에 액세스하는 데 이미 동의했는지 확인하는 것이 좋습니다. 이렇게 하려면 Home 인스턴스의 hasPermissions() 메서드를 호출하여 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())
    }
}

확인에서 NOT_GRANTED 또는 PERMISSIONS_STATE_UNAVAILABLEPermissionsState가 반환되면 사용자 또는 애플리케이션에 구조에 대한 액세스 권한이 없는 것입니다. 확인에서 PermissionsStateGRANTED가 반환되었지만 후속 structures() 호출에서 구조가 반환되지 않으면 사용자가 GHA 설정 페이지를 통해 앱에 대한 액세스 권한을 취소했거나 사용자에게 필요한 액세스 권한이 없는 것입니다.

권한 요청

지정된 구조 내의 구조 및 기기에 액세스하려면 앱에 권한이 부여되어야 합니다.

사용자가 아직 권한을 부여하지 않은 경우 Home 인스턴스의 requestPermissions() 메서드를 사용하여 권한 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

권한 UI가 제대로 실행되려면 앱에 OAuth를 이미 설정해야 합니다.

권한 부여

이제 앱을 실행하고 사용자에게 권한을 부여할 수 있습니다. 권한을 부여할 수 있는 사용자 유형과 권한을 부여할 수 있는 기기 유형은 Google Home Developer Console에 앱을 등록했는지 여부에 따라 다릅니다.

Developer Console 등록이 필요합니다. Home API를 사용하여 앱을 게시하려면 Home API를 테스트하고 사용하는 데는 필요하지 않습니다.

앱이 Developer Console에 등록되지 않은 경우 인증되지 않은 상태가 됩니다. Home API의 테스트 사용에 권장되는 사항은 다음과 같습니다.

앱이 개발자 콘솔에 등록되어 있고Developer Console 하나 이상의 기기 유형에 대한 액세스 권한이 승인되었으며 OAuth의 브랜드 인증이 완료된 경우, 인증된 상태가 됩니다. 이 상태는 앱을 프로덕션에 출시하는 데 필요합니다.

  • 테스트 사용자 제한이 더 이상 적용되지 않습니다. 모든 사용자가 앱에 권한을 부여할 수 있습니다.
  • 사용자는 개발자 콘솔에서 승인된 기기 유형에만 권한을 부여할 수 있습니다.Developer Console

이제 OAuth가 설정되었으므로 앱의 requestPermissions() 호출이 다음 대화상자를 트리거합니다.

  1. 사용자에게 사용하려는 Google 계정을 선택하라는 메시지가 표시됩니다.
  2. 사용자에게 앱 액세스 권한을 부여하려는 구조를 선택하라는 메시지가 표시됩니다.
    1. 인증되지 않은 앱의 경우 Home API에서 지원하는 모든 기기 유형을 앱에서 사용할 수 있습니다.
    2. 인증된 앱의 경우 사용자는 개발자 콘솔에서 승인된 기기 유형에만 권한을 부여할 수 있습니다. Developer Console
    3. 앱에서 관리할 수 있는 민감한 기기 유형의 경우 사용자는 기기별로 액세스를 제한할 수 있습니다. 예를 들어 사용자에게 잠금장치가 3개 있는 경우 이러한 잠금장치 중 하나에만 액세스 권한을 부여할 수 있습니다.
  • OAuth 동의 - 계정 선택
  • OAuth 동의 - 기기 연결 01
  • OAuth 동의 - 기기 연결 02
그림 1: OAuth 동의 흐름 예시

권한이 부여되면 앱은 Home API를 사용하여 구조의 기기 상태를 읽고 제어할 수 있습니다. 사용자가 특정 기기 유형 또는 민감한 기기에 대한 권한을 앱에 부여하지 않으면 앱은 Home API를 사용하여 액세스, 제어 또는 자동화할 수 없습니다.

권한 변경

다른 구조의 기기에 액세스할 수 있는 권한을 부여하려면 계정 선택 도구를 실행하여 사용자가 전환할 Google 계정 및 구조를 선택할 수 있도록 합니다. 이 과정에서 사용자는 이전에 동의가 부여된 경우에도 동의 화면을 다시 보게 됩니다.

이는 forceLaunch 플래그를 true로 설정하여 requestPermissions()를 다시 호출하면 됩니다.

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
            }
        }
    }
}

OkGoogle 권한

okGoogle 명령어는 기기 수준 명령어이며 구조의 모든 기기를 자동화하는 데 사용할 수 있습니다. 하지만 Home API 앱은 모든 기기에 액세스하지 못할 수 있습니다. 다음 표에서는 이러한 경우 권한이 적용되는 방법을 설명합니다.

자동화 트레이트 권한 적용
오후 10시에 침실 스피커에서 '취침 시간'을 브로드캐스트합니다. AssistantBroadcastTrait 기기에서. 자동화 생성:
  • 브로드캐스트 기기는 어시스턴트 기기여야 합니다.
  • 앱과 사용자는 브로드캐스트가 발생하는 기기에 액세스할 수 있어야 합니다.
자동화 실행:
  • 앱과 사용자는 브로드캐스트가 발생하는 기기에 액세스할 수 있어야 합니다.
오후 10시에 모든 기기에서 '취침 시간'을 브로드캐스트합니다. AssistantBroadcastTrait 구조에. 자동화 생성:
  • 앱과 사용자가 액세스할 수 있는 구조에 어시스턴트 기기가 하나 이상 있어야 합니다.
  • 앱과 사용자는 구조에 액세스할 수 있어야 합니다.
자동화 실행:
  • 앱과 사용자는 구조에 액세스할 수 있어야 합니다.
오후 10시에 '음악 재생' AssistantFulfillmentTrait.OkGoogleCommand 자동화 생성:
  • 앱과 사용자는 자동화에서 명령어를 실행하는 기기에 액세스할 수 있어야 합니다.
자동화 실행:
  • 앱과 사용자는 자동화에서 명령어를 실행하는 기기에 액세스할 수 있어야 합니다.
누군가 '음악 재생'이라고 말할 때마다 VoiceStarterTrait.OkGoogleEvent 자동화 생성:
  • 앱과 사용자는 구조에 액세스할 수 있어야 합니다. 자동화는 유효성 검사를 통과하거나 실행하는 데 어시스턴트 기기가 필요하지 않습니다. 구조에 액세스할 수 있는 모든 사용자가 동일한 Google 계정을 사용하여 휴대전화를 사용하여 어시스턴트와 상호작용하고 VoiceStarter를 트리거할 수 있기 때문입니다.
자동화 실행:
  • 앱에는 자동화를 시작하는 기기에 액세스할 수 있는 권한이 필요하지 않습니다.
  • 앱과 사용자에게는 작업이 발생하는 기기에 액세스할 수 있는 권한이 있어야 합니다.

사용자가 모든 권한을 취소하는 경우 안내

사용자가 모든 권한을 취소하면 기존의 모든 자동화가 중지됩니다. 또한 사용자가 특정 기기에 대한 액세스 권한을 취소하면 이러한 기기와 연결된 시작 조건, 조건, 작업이 중지됩니다.

앱이 시작될 때마다 권한이 여전히 유효한지 확인하세요. 권한이 취소된 경우 애플리케이션에 캐시된 데이터를 포함하여 이전의 모든 데이터가 삭제되었는지 확인하세요.