오디오 글래스 및 디스플레이 글래스의 하드웨어 권한 요청

적용 가능한 XR 기기
이 가이드에서는 이러한 유형의 XR 기기를 위한 환경을 빌드하는 방법을 설명합니다.
오디오 및
디스플레이 안경

휴대전화와 마찬가지로 오디오 글라스 및 디스플레이 글라스에서 카메라 및 마이크와 같은 민감한 하드웨어에 액세스하려면 명시적인 사용자 동의가 필요합니다. 이러한 권한은 안경 관련 권한으로 간주되며 앱에 휴대전화에 이미 상응하는 권한이 있더라도 런타임에 요청해야 합니다.

앱 매니페스트에서 권한 선언

권한을 요청하기 전에 앱의 매니페스트 파일에서 권한을 선언 해야 합니다. <uses-permission> 요소를 사용하세요. 이 선언은 권한이 휴대전화 또는 안경 관련 기능에 대한 것인지에 관계없이 동일하게 유지되지만 안경 관련 하드웨어 또는 기능에 대해 명시적으로 요청해야 합니다.

<manifest ...>
    <!-- Only declare permissions that your app actually needs. In this example,
    we declare permissions for the camera. -->
    <uses-permission android:name="android.permission.CAMERA"/>
    <application ...>
        ...
    </application>
</manifest>

안경 권한을 요청하기 전에

권한 원칙 및 워크플로를 검토하여 사용자에게 최상의 환경을 제공하는지 확인합니다. 예를 들어 앱에 필요한 런타임 권한을 사용자가 이미 부여했는지, 안경 관련 권한을 요청하기 전에 앱에서 사용자에게 근거를 표시해야 하는지 확인합니다.

권한 시나리오

오디오 및 디스플레이 글라스에서 위험한 런타임 권한을 요청할 때 발생할 수 있는 몇 가지 시나리오는 다음과 같습니다.

  • 예측된 활동에서 런타임 권한 요청
  • 휴대전화 활동에서 런타임 권한 요청

각 시나리오에 관한 자세한 내용은 이 가이드의 다음 섹션을 참고하세요.

예측된 활동에서 런타임 권한 요청 및 처리

오디오 글라스 및 디스플레이 글라스의 권한을 요청하려면 먼저 ActivityResultLauncherProjectedPermissionsResultContract 메서드와 함께 사용하여 권한 런처를 등록합니다. 사용자가 권한 요청에 따라 조치를 취하면 콜백은 권한 이름과 부여된 상태의 맵을 수신합니다.

// Register the permissions launcher using the ProjectedPermissionsResultContract.
private val requestPermissionLauncher: ActivityResultLauncher<List<ProjectedPermissionsRequestParams>> =
    registerForActivityResult(ProjectedPermissionsResultContract()) { results ->
        if (results[Manifest.permission.CAMERA] == true) {
            isPermissionDenied = false
            initializeGlassesFeatures()
        } else {
            // Handle permission denial.
            isPermissionDenied = true
        }
    }

코드에 관한 주요사항

권한 요청 흐름을 트리거하려면 등록된 권한 런처의 launch 메서드에 ProjectedPermissionsRequestParams 목록을 전달합니다. ProjectedPermissionsRequestParams 객체는 요청된 매니페스트 권한을 맞춤 rationale 문자열과 함께 번들로 묶습니다. rationale 문자열은 앱에서 안경의 하드웨어 기능 (예: 카메라 또는 마이크)에 액세스해야 하는 이유를 명확하고 간결하게 설명해야 합니다.

private fun requestHardwarePermissions() {
    val params = ProjectedPermissionsRequestParams(
        permissions = listOf(Manifest.permission.CAMERA),
        rationale = "Camera access is required to overlay digital content on your physical environment."
    )
    requestPermissionLauncher.launch(listOf(params))
}

코드에 관한 주요사항

권한 요청 사용자 흐름 이해

ProjectedPermissionsResultContract 메서드를 사용하여 권한 요청을 시작하면 시스템은 안경과 휴대전화 모두에서 조정된 사용자 흐름을 시작합니다.

권한 사용자 흐름 중에 앱과 사용자가 기대할 수 있는 사항은 다음과 같습니다.

  1. 안경: 예측된 기기 (안경)에 활동이 표시되어 사용자에게 휴대전화를 확인하여 계속 진행하도록 안내합니다.

  2. 휴대전화: 동시에 호스트 기기 (휴대전화)에서 활동이 시작됩니다. 이 화면에는 제공한 근거 문자열이 표시되고 사용자에게 계속 진행하거나 취소할 수 있는 옵션이 제공됩니다.

  3. 휴대전화: 사용자가 근거를 수락하면 수정된 Android 시스템 권한 대화상자가 휴대전화에 표시되어 사용자에게 휴대전화가 아닌 안경에 대한 권한을 부여하고 있음을 알리고 사용자는 권한을 공식적으로 부여하거나 거부할 수 있습니다.

  4. 결과 수신: 사용자가 최종 선택을 하면 휴대전화와 안경의 활동이 모두 종료됩니다. 그런 다음 요청된 각 권한의 부여된 상태가 포함된 맵으로 Your ActivityResultLauncher 콜백이 호출됩니다.

휴대전화 활동에서 런타임 권한 요청

앱이 휴대전화 활동에서 실행되지만 오디오 또는 디스플레이 글라스의 권한이 필요한 경우(예: 사용자가 1인칭 시점에서 동영상 스트림을 글라스의 카메라로 전환할 수 있도록 허용) 기기별 Activity#requestPermissions(permissions, requestCode, deviceId) 메서드를 사용하여 권한을 요청합니다.

오디오 및 디스플레이 글라스를 타겟팅하려면 예측된 기기 컨텍스트에서 getDeviceId를 호출하여 적절한 기기 ID를 가져옵니다. 다음 예와 같이 휴대전화 활동에서 권한을 요청할 때 이 ID를 전달합니다.

// Request the projected permission from phone activity
requestPermissions(
    arrayOf(Manifest.permission.CAMERA),
    // REQUEST_CODE_GLASSES_CAMERA is a developer-defined constant
    REQUEST_CODE_GLASSES_CAMERA,
    projectedDeviceId
)

권한 결과 처리

사용자가 휴대전화의 권한 대화상자에 응답하면 onRequestPermissionsResult 콜백을 호출하여 결정이 앱에 전달됩니다.

응답을 처리하려면 권0}onRequestPermissionsResult 내에서 권한 요청을 시작한 Activity 인스턴스를 재정의합니다.

다음 코드 스니펫은 콜백을 처리하고 사용자가 요청된 권한을 부여했는지 확인하는 방법을 보여줍니다.

private companion object {
    // REQUEST_CODE_GLASSES_CAMERA is a developer-defined constant.
    const val REQUEST_CODE_GLASSES_CAMERA = 1001
}

@RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
override fun onRequestPermissionsResult(
    requestCode: Int,
    permissions: Array<out String>,
    grantResults: IntArray,
    deviceId: Int
) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults, deviceId)

    // Handle the result of the permission request
    if (requestCode == REQUEST_CODE_GLASSES_CAMERA && deviceId == projectedDeviceId) {
        if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            // Proceed with glasses camera features
        } else {
            // Handle glasses permission denied
        }
    }
}

코드에 관한 주요사항
  • onRequestPermissionsResult 콜백과 함께 deviceId 오버로드를 사용하여 권한 상태가 호스트 휴대전화가 아닌 오디오 또는 디스플레이 글라스와 같은 특정 컨텍스트에 올바르게 매핑되도록 합니다.
  • 앱은 부여된 결과와 거부된 결과를 모두 정상적으로 처리해야 합니다.