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

해당 XR 기기
이 안내는 이러한 유형의 XR 기기용 환경을 구축하는 데 도움이 됩니다.
AI 글래스

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

코드가 실행되는 위치에 따라 예상 컨텍스트를 가져오는 두 가지 기본 방법이 있습니다.

코드가 AI 안경 활동에서 실행되는 경우 예상 컨텍스트 가져오기

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

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

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

// From a phone Activity, get a context for the AI glasses
try {
    val glassesContext = ProjectedContext.createProjectedDeviceContext(this)
    // Now use glassesContext to access glasses' system services
} catch (e: IllegalStateException) {
    // Projected device was not found
}

유효성 확인

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

연결 해제 시 정리

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

다시 연결 시 다시 초기화

AI 안경 기기가 다시 연결되면 앱은 createProjectedDeviceContext()를 사용하여 다른 투영된 컨텍스트 인스턴스를 가져온 다음 새 투영된 컨텍스트를 사용하여 시스템 서비스나 리소스를 다시 초기화할 수 있습니다.

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

현재 AI 안경은 표준 블루투스 오디오 기기로 휴대전화에 연결됩니다. 헤드셋과 A2DP (고급 오디오 전송 프로필) 프로필이 모두 지원됩니다. 이 방법을 사용하면 오디오 입력 또는 출력을 지원하는 모든 Android 앱이 안경에서 작동할 수 있습니다. 안경을 지원하도록 의도적으로 빌드되지 않은 앱도 마찬가지입니다. 경우에 따라 블루투스를 사용하면 투영된 컨텍스트를 사용하여 글래스 하드웨어에 액세스하는 대신 앱의 사용 사례에 더 적합할 수 있습니다.

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

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

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

private fun startCamera() {
    // Get the CameraProvider using the projected context.

    val cameraProviderFuture = ProcessCameraProvider.getInstance(
        ProjectedContext.createProjectedDeviceContext(this)
    )

    cameraProviderFuture.addListener({
        // Used to bind the lifecycle of cameras to the lifecycle owner
        val cameraProvider: ProcessCameraProvider = cameraProviderFuture.get()

        // Select the camera. When using the projected context, DEFAULT_BACK_CAMERA maps to the AI glasses' camera.
        val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
    
        // Check for the presence of a camera before initializing the ImageCapture use case.
       if (!cameraProvider.hasCamera(cameraSelector)) {
            Log.w(TAG, "The selected camera is not available.")
            return@addListener
        }

        // Get supported streaming resolutions.
        val cameraInfo = cameraProvider.getCameraInfo(cameraSelector)
        val camera2CameraInfo = Camera2CameraInfo.from(cameraInfo)
        val cameraCharacteristics = camera2CameraInfo.getCameraCharacteristic(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP)

        // 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()

        // 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, 30)
        val captureRequestOptions = CaptureRequestOptions.Builder()
                .setCaptureRequestOption(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE,fpsRange)
                .build()

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

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

            // 4. Bind use cases to camera
            cameraProvider.bindToLifecycle(this as LifecycleOwner, cameraSelector, imageCapture)

        } catch(exc: Exception) {
            // This catches exceptions like IllegalStateException if use case binding fails
            Log.e(TAG, "Use case binding failed", exc)
        }

    }, ContextCompat.getMainExecutor(this))
}

코드에 관한 핵심 사항

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

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

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)를 사용하여 호스트 기기(휴대전화)의 컨텍스트를 가져와 카메라나 마이크와 같은 휴대전화의 하드웨어에 액세스할 수도 있습니다.

// From an AI glasses Activity, get a context for the phone
val phoneContext = ProjectedContext.createHostDeviceContext(this)
// Now use phoneContext to access the phone's hardware

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

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