Используйте проецируемый контекст для доступа к оборудованию очков ИИ

Применимые устройства XR
Это руководство поможет вам создать опыт использования этих типов XR-устройств.
Очки ИИ

После того, как вы запросили и получили необходимые разрешения , ваше приложение сможет получить доступ к аппаратному обеспечению очков с искусственным интеллектом. Ключ к доступу к аппаратному обеспечению очков (а не телефона) — использование проецируемого контекста .

Существует два основных способа получить спроецированный контекст в зависимости от того, где выполняется ваш код:

Получите спроецированный контекст, если ваш код выполняется в активности очков ИИ.

Если код вашего приложения выполняется из активности очков ИИ, его собственный контекст активности уже является проецируемым контекстом. В этом случае вызовы, выполняемые внутри этой активности, уже могут обращаться к аппаратному обеспечению очков.

Получите спроецированный контекст, если ваш код выполняется в компоненте приложения для телефона.

Если часть вашего приложения, не связанная с активностью очков ИИ (например, активность телефона или служба), требует доступа к аппаратному обеспечению очков, она должна явно получить проецируемый контекст. Для этого используйте метод 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 ) могут получить доступ к аппаратному обеспечению очков с искусственным интеллектом.

Очистка при отключении

Проецируемый контекст привязан к жизненному циклу подключенного устройства, поэтому он уничтожается при его отключении. При отключении устройства ProjectedContext.isProjectedDeviceConnected возвращает false . Ваше приложение должно отслеживать это изменение и очищать все системные службы (например, CameraManager ) или ресурсы, созданные приложением с использованием этого проецируемого контекста.

Повторная инициализация при повторном подключении

При повторном подключении очков ИИ ваше приложение может получить другой экземпляр спроецированного контекста с помощью createProjectedDeviceContext() , а затем повторно инициализировать любые системные службы или ресурсы, используя новый спроецированный контекст.

Доступ к аудио через Bluetooth

В настоящее время очки с искусственным интеллектом подключаются к телефону как стандартное аудиоустройство Bluetooth. Поддерживаются профили гарнитуры и A2DP (Advanced Audio Distribution Profile). Благодаря этому любое приложение Android, поддерживающее аудиовход или аудиовыход, может работать на очках, даже если они не были специально разработаны для этой цели. В некоторых случаях использование Bluetooth может быть более эффективным для вашего приложения, чем доступ к аппаратному обеспечению очков через проецируемый контекст.

Как и в случае с любым стандартным аудиоустройством Bluetooth, разрешение на предоставление разрешения RECORD_AUDIO контролируется телефоном, а не очками.

Сделайте снимок с помощью камеры очков с искусственным интеллектом

Чтобы сделать снимок с помощью камеры очков ИИ, настройте и привяжите сценарий использования ImageCapture CameraX к камере очков, используя правильный контекст для вашего приложения:

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 , используя проецируемый контекст устройства .
  • В рамках проецируемого контекста основная направленная наружу камера очков ИИ сопоставляется с DEFAULT_BACK_CAMERA при выборе камеры.
  • Предварительная проверка привязки использует cameraProvider.hasCamera(cameraSelector) для проверки доступности выбранной камеры на устройстве перед продолжением работы.
  • Использует Camera2 Interop с Camera2CameraInfo для чтения базовых характеристик CameraCharacteristics#SCALER_STREAM_CONFIGURATION_MAP , что может быть полезно для расширенных проверок поддерживаемых разрешений.
  • Пользовательский ResolutionSelector создан для точного управления разрешением выходного изображения для ImageCapture .
  • Создает вариант использования ImageCapture , настроенный с помощью пользовательского ResolutionSelector .
  • Связывает вариант использования ImageCapture с жизненным циклом активности. Это автоматически управляет открытием и закрытием камеры в зависимости от состояния активности (например, останавливает камеру при приостановке активности).

После настройки камеры очков с искусственным интеллектом вы можете сделать снимок с помощью класса ImageCapture класса CameraX. Чтобы узнать об использовании takePicture() для захвата изображения , обратитесь к документации CameraX.

Снимите видео с помощью камеры очков ИИ

Чтобы захватить видео вместо изображения с помощью камеры очков ИИ, замените компоненты ImageCapture соответствующими компонентами VideoCapture и измените логику выполнения захвата.

Основные изменения включают использование другого варианта использования, создание другого выходного файла и запуск захвата с использованием соответствующего метода видеозаписи. Подробнее об API VideoCapture и его использовании см. в документации по видеозахвату CameraX .

В следующей таблице показаны рекомендуемые разрешение и частота кадров в зависимости от варианта использования вашего приложения:

Вариант использования Разрешение Частота кадров
Видеосвязь 1280 х 720 15 кадров в секунду
Компьютерное зрение 640 х 480 10 кадров в секунду
Потоковое видео с ИИ 640 х 480 1 кадр в секунду

Доступ к аппаратному обеспечению телефона с помощью очков ИИ

Активность очков ИИ также может получать доступ к оборудованию телефона (например, камере или микрофону), используя 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

При доступе к оборудованию или ресурсам, специфичным для хост-устройства (телефона) в гибридном приложении (приложении, содержащем как мобильные возможности, так и возможности очков ИИ), необходимо явно выбрать правильный контекст, чтобы ваше приложение могло получить доступ к правильному оборудованию:

  • Используйте контекст Activity из Activity телефона или ProjectedContext.createHostDeviceContext() чтобы получить контекст телефона.
  • Не используйте getApplicationContext() поскольку контекст приложения может неправильно вернуть контекст очков ИИ, если активность очков была последним запущенным компонентом.