Обработка физического ввода с аудио- и дисплейных очков.

Применимые устройства XR
Данное руководство поможет вам создавать приложения для устройств XR такого типа.
Аудио и
Очки для демонстрации

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

Управляйте движением камеры.

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

@OptIn(ExperimentalProjectedApi::class)
class CameraActionInputSnippetActivity : ComponentActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // Observe hardware camera action events when RESUMED
        lifecycleScope.launch {
            repeatOnLifecycle(Lifecycle.State.RESUMED) {
                withContext(Dispatchers.Default) {
                    try {
                        val projectedActivity = ProjectedActivityCompat.create(this@CameraActionInputSnippetActivity)
                        try {
                            projectedActivity.projectedInputEvents.collect { inputEvent ->
                                if (inputEvent.inputAction == TOGGLE_APP_CAMERA) {
                                    withContext(Dispatchers.Main) {
                                        onCameraActionTriggered()
                                    }
                                }
                            }
                        } finally {
                            projectedActivity.close()
                        }
                    } catch (e: CancellationException) {
                        throw e
                    } catch (e: Exception) {
                        Log.w("CameraActionSnippet", "ProjectedActivityCompat unavailable: ${e.message}")
                    }
                }
            }
        }

        setContent {
            GlimmerTheme {
                TouchpadInputSnippet(
                    onTap = { Log.i("CameraActionSnippet", "Touchpad tapped") }
                )
            }
        }
    }

    private fun onCameraActionTriggered() {
        Log.i("CameraActionSnippet", "Camera action button double-pressed!")
    }
}

Проверяйте общие события движения.

Используйте dispatchGenericMotionEvent для проверки универсальных событий движения, доставляемых в проецируемую активность вашего приложения. Универсальные события движения доставляются на границе активности и не требуют наличия сфокусированного компонента Jetpack Compose Glimmer.

В состав MotionEvent могут входить:

Не каждое значение имеет смысл для каждого действия. Прежде чем рассматривать исходное событие как завершенный жест, изучите само действие и его источник.

class MotionGestureInputSnippetActivity : ComponentActivity() {

    override fun dispatchGenericMotionEvent(ev: MotionEvent): Boolean {
        val actionName = when (ev.actionMasked) {
            MotionEvent.ACTION_DOWN -> "ACTION_DOWN" // First contact with the glasses touchpad
            MotionEvent.ACTION_MOVE -> "ACTION_MOVE" // Contact moving across the glasses touchpad
            MotionEvent.ACTION_UP -> "ACTION_UP"     // Contact lifted from the glasses touchpad
            else -> "ACTION_${ev.actionMasked}"
        }

        Log.d(
            "MotionGestureSnippet",
            "MotionEvent: action=$actionName x=${ev.x} y=${ev.y}"
        )

        // Delegate to super unless intentionally consuming the event
        return super.dispatchGenericMotionEvent(ev)
    }
}

Возвращайте true только в том случае, если активность намеренно обрабатывает событие. В противном случае верните super.dispatchGenericMotionEvent(ev) чтобы событие могло продолжить обработку в обычном режиме.

Управление системой Жест «Назад»

Если экрану требуется настроить поведение при нажатии кнопки "Назад", ваше приложение должно обрабатывать жест "Назад" с помощью тех же API Android, что и для других активностей, например, OnBackPressedDispatcher и OnBackPressedCallback .

Жест пользователя зависит от типа очков:

  • На дисплеях свайп вниз по сенсорной панели выполняет системный жест "Назад".
  • На аудиоочках движение пальцем назад по сенсорной панели выполняет системный жест "Назад".

Зарегистрируйте функцию обратного вызова, которая будет срабатывать, когда текущий экран должен перехватить нажатие кнопки «Назад», например, при закрытии всплывающего окна или отображении подтверждения выхода.

class BackGestureInputSnippetActivity : ComponentActivity() {

    private val backCallback = object : OnBackPressedCallback(true) {
        override fun handleOnBackPressed() {
            onBackGestureReceived()
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // Register back gesture callback with Activity's onBackPressedDispatcher
        onBackPressedDispatcher.addCallback(this, backCallback)
    }

    private fun onBackGestureReceived() {
        Log.i("BackGestureSnippet", "System back gesture intercepted")
    }
}

Функция обратного вызова должна быть включена только тогда, когда активный экран должен перехватывать событие «Назад». Отключите или удалите функцию обратного вызова, когда событие «Назад» должно обрабатываться системой по умолчанию или поведением навигации.

Следующие шаги

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