프로젝션된 컨텍스트를 사용하여 AI 안경 하드웨어에 액세스

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

필요한 권한을 요청하고 부여받은 후에는 앱에서 AI 안경 하드웨어에 액세스할 수 있습니다. 안경 하드웨어 (휴대전화 하드웨어 대신)에 액세스하는 방법은 프로젝션된 컨텍스트를 사용하는 것입니다.

코드가 실행되는 위치에 따라 프로젝션된 컨텍스트를 가져오는 방법에는 두 가지가 있습니다.

코드가 AI 안경 활동에서 실행되는 경우 프로젝션된 컨텍스트 가져오기

앱의 코드가 AI 안경 활동 내에서 실행되는 경우 자체 활동 컨텍스트가 이미 프로젝션된 컨텍스트입니다. 이 시나리오에서는 해당 활동 내에서 이루어진 호출이 이미 안경 하드웨어에 액세스할 수 있습니다.

휴대전화 앱 구성요소에서 실행되는 코드의 프로젝션된 컨텍스트 가져오기

AI 안경 활동 외부의 앱 부분 (예: 휴대전화 활동 또는 서비스)에서 안경 하드웨어에 액세스해야 하는 경우 프로젝션된 컨텍스트를 명시적으로 가져와야 합니다. 이렇게 하려면 createProjectedDeviceContext() 메서드를 사용하세요.

@OptIn(ExperimentalProjectedApi::class)
private fun getGlassesContext(context: Context): Context? {
    return try {
        // From a phone Activity or Service, get a context for the AI glasses.
        ProjectedContext.createProjectedDeviceContext(context)
    } catch (e: IllegalStateException) {
        Log.e(TAG, "Failed to create projected device context", e)
        null
    }
}

유효성 확인

프로젝션된 컨텍스트를 만든 후에는 모니터링합니다. ProjectedContext.isProjectedDeviceConnected 이 메서드가 true를 반환하는 동안 프로젝션된 컨텍스트는 연결된 기기에 유효한 상태로 유지되며 휴대전화 앱 활동 또는 서비스 (예: CameraManager)에서 AI 안경 하드웨어에 액세스할 수 있습니다.

연결 해제 시 정리

프로젝션된 컨텍스트는 연결된 기기의 수명 주기에 연결되어 있으므로 기기가 연결 해제되면 소멸됩니다. 기기가 연결 해제되면 ProjectedContext.isProjectedDeviceConnectedfalse를 반환합니다. 앱은 이 변경사항을 수신 대기하고 해당 프로젝션된 컨텍스트를 사용하여 앱에서 만든 시스템 서비스 (예: CameraManager) 또는 리소스를 정리해야 합니다.

재연결 시 다시 초기화

AI 안경 기기가 다시 연결되면 앱은 프로젝션된 컨텍스트 인스턴스를 `createProjectedDeviceContext()`를 사용하여 가져온 후 새 프로젝션된 컨텍스트를 사용하여 시스템 서비스 또는 리소스를 다시 초기화할 수 있습니다.createProjectedDeviceContext()

블루투스를 사용하여 오디오 액세스

현재 AI 안경은 표준 블루투스 오디오 기기로 휴대전화에 연결됩니다. 헤드셋과 A2DP (Advanced Audio Distribution Profile) 프로필이 모두 지원됩니다. 이 접근 방식을 사용하면 안경을 지원하도록 의도적으로 빌드되지 않은 경우에도 오디오 입력 또는 출력을 지원하는 모든 Android 앱이 안경에서 작동할 수 있습니다. 경우에 따라 블루투스를 사용하는 것이 프로젝션된 컨텍스트를 사용하여 안경 하드웨어에 액세스하는 것보다 앱의 사용 사례에 더 적합할 수 있습니다.

표준 블루투스 오디오 기기와 마찬가지로 RECORD_AUDIO 권한을 부여하는 권한은 안경이 아닌 휴대전화에서 제어합니다.

AI 안경 카메라로 이미지 캡처

AI 안경 카메라로 이미지를 캡처하려면 앱에 올바른 컨텍스트를 사용하여 CameraX의 ImageCapture 사용 사례를 안경 카메라에 설정하고 결합합니다.

private fun startCameraOnGlasses(activity: ComponentActivity) {
    // 1. Get the CameraProvider using the projected context.
    // When using the projected context, DEFAULT_BACK_CAMERA maps to the AI glasses' camera.
    val projectedContext = try {
        ProjectedContext.createProjectedDeviceContext(activity)
    } catch (e: IllegalStateException) {
        Log.e(TAG, "AI Glasses context could not be created", e)
        return
    }

    val cameraProviderFuture = ProcessCameraProvider.getInstance(projectedContext)

    cameraProviderFuture.addListener({
        val cameraProvider: ProcessCameraProvider = cameraProviderFuture.get()
        val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA

        // 2. Check for the presence of a camera.
        if (!cameraProvider.hasCamera(cameraSelector)) {
            Log.w(TAG, "The selected camera is not available.")
            return@addListener
        }

        // 3. Query supported streaming resolutions using Camera2 Interop.
        val cameraInfo = cameraProvider.getCameraInfo(cameraSelector)
        val camera2CameraInfo = Camera2CameraInfo.from(cameraInfo)
        val cameraCharacteristics = camera2CameraInfo.getCameraCharacteristic(
            CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP
        )

        // 4. Define the resolution strategy.
        val targetResolution = Size(1920, 1080)
        val resolutionStrategy = ResolutionStrategy(
            targetResolution,
            ResolutionStrategy.FALLBACK_RULE_CLOSEST_LOWER
        )
        val resolutionSelector = ResolutionSelector.Builder()
            .setResolutionStrategy(resolutionStrategy)
            .build()

        // 5. If you have other continuous use cases bound, such as Preview or ImageAnalysis,
        // you can use  Camera2 Interop's CaptureRequestOptions to set the FPS
        val fpsRange = Range(30, 60)
        val captureRequestOptions = CaptureRequestOptions.Builder()
            .setCaptureRequestOption(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE, fpsRange)
            .build()

        // 6. Initialize the ImageCapture use case with options.
        val imageCapture = ImageCapture.Builder()
            // Optional: Configure resolution, format, etc.
            .setResolutionSelector(resolutionSelector)
            .build()

        try {
            // Unbind use cases before rebinding.
            cameraProvider.unbindAll()

            // Bind use cases to camera using the Activity as the LifecycleOwner.
            cameraProvider.bindToLifecycle(
                activity,
                cameraSelector,
                imageCapture
            )
        } catch (exc: Exception) {
            Log.e(TAG, "Use case binding failed", exc)
        }
    }, ContextCompat.getMainExecutor(activity))
}

코드에 관한 주요 사항

  • ProcessCameraProvider를 사용하여 프로젝션된 기기 컨텍스트의 인스턴스를 가져옵니다.
  • 프로젝션된 컨텍스트의 범위 내에서 카메라를 선택할 때 AI 안경의 기본 외부 카메라가 DEFAULT_BACK_CAMERA에 매핑됩니다.
  • 사전 결합 검사에서는 cameraProvider.hasCamera(cameraSelector)를 사용하여 선택한 카메라가 기기에서 사용 가능한지 확인한 후 계속 진행합니다.
  • Camera2CameraInfo와 함께 Camera2 Interop 을 사용하여 지원되는 해상도에 대한 고급 검사에 유용할 수 있는 기본 CameraCharacteristics#SCALER_STREAM_CONFIGURATION_MAP을 읽습니다.
  • 커스텀 ResolutionSelectorImageCapture의 출력 이미지 해상도를 정확하게 제어하기 위해 빌드됩니다.
  • 커스텀 ResolutionSelector로 구성된 ImageCapture 사용 사례를 만듭니다.
  • ImageCapture 사용 사례를 활동의 수명 주기에 결합합니다. 이렇게 하면 활동의 상태에 따라 카메라 열기 및 닫기가 자동으로 관리됩니다 (예: 활동이 일시중지될 때 카메라 중지).

AI 안경 카메라가 설정되면 CameraX의 ImageCapture 클래스로 이미지를 캡처할 수 있습니다. 이미지를 캡처하는 방법을 알아보려면 CameraX의 문서를 참고하세요.takePicture()

AI 안경 카메라로 동영상 캡처

AI 안경 카메라로 이미지가 아닌 동영상을 캡처하려면 ImageCapture 구성요소를 상응하는 VideoCapture 구성요소 로 바꾸고 캡처 실행 로직을 수정합니다.

주요 변경사항에는 다른 사용 사례 사용, 다른 출력 파일 만들기, 적절한 동영상 녹화 메서드를 사용하여 캡처 시작이 포함됩니다. VideoCapture API 및 사용 방법에 관한 자세한 내용은 CameraX의 동영상 캡처 문서를 참고하세요.

다음 표는 앱의 사용 사례에 따라 권장되는 해상도와 프레임 속도를 보여줍니다.

사용 사례 해결 방법 프레임 속도
동영상 통신 1280 x 720 15 FPS
컴퓨터 비전 640 x 480 10 FPS
AI 동영상 스트리밍 640 x 480 1 FPS

AI 안경 활동에서 휴대전화 하드웨어에 액세스

AI 안경 활동은 `createHostDeviceContext(context)`를 사용하여 호스트 기기(휴대전화) 컨텍스트를 가져와 휴대전화 하드웨어(예: 카메라 또는 마이크)에 액세스할 수도 있습니다.createHostDeviceContext(context)

@OptIn(ExperimentalProjectedApi::class)
private fun getPhoneContext(activity: ComponentActivity): Context? {
    return try {
        // From an AI glasses Activity, get a context for the phone.
        ProjectedContext.createHostDeviceContext(activity)
    } catch (e: IllegalStateException) {
        Log.e(TAG, "Failed to create host device context", e)
        null
    }
}

하이브리드 앱(모바일 환경과 AI 안경 환경이 모두 포함된 앱)에서 호스트 기기 (휴대전화)에만 해당하는 하드웨어 또는 리소스에 액세스할 때는 앱이 올바른 하드웨어에 액세스할 수 있도록 올바른 컨텍스트를 명시적으로 선택해야 합니다.

  • 휴대전화 Activity 또는 ProjectedContext.createHostDeviceContext()Activity 컨텍스트를 사용하여 휴대전화의 컨텍스트를 가져옵니다.
  • 안경 활동이 가장 최근에 실행된 구성요소인 경우 애플리케이션 컨텍스트 가 AI 안경의 컨텍스트를 잘못 반환할 수 있으므로 getApplicationContext()를 사용하지 마세요.