Cómo controlar la entrada física de los lentes con audio y los lentes con pantalla

Dispositivos de realidad extendida correspondientes
Esta guía te ayuda a crear experiencias para estos tipos de dispositivos de realidad extendida.
Lentes de audio y
visualización

Para capturar y procesar la entrada del usuario que se entrega a la actividad proyectada de tu app o para implementar comportamientos personalizados del panel táctil, usa entradas de puntero indirectas. Para controlar otros tipos de eventos (como la acción de la cámara), consulta las siguientes secciones de esta guía.

Cómo controlar la acción de la cámara

Cada vez que un usuario presiona el botón de la cámara de un dispositivo, el sistema entrega un evento de entrada a la actividad proyectada de tu app como una acción ProjectedInputEvent.ProjectedInputAction.TOGGLE_APP_CAMERA. Tu app puede observar esta acción con un dispatcher dedicado:

@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!")
    }
}

Cómo inspeccionar eventos de movimiento genéricos

Usa dispatchGenericMotionEvent para inspeccionar eventos de movimiento genéricos que se entregan a la actividad proyectada de tu app. Los eventos de movimiento genéricos se entregan en el límite de la actividad y no requieren un componente Glimmer de Jetpack Compose enfocado.

Un MotionEvent puede incluir lo siguiente:

No todos los valores son significativos para cada acción. Inspecciona la acción y la fuente antes de tratar un evento sin procesar como un gesto completado.

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)
    }
}

Muestra true solo cuando la actividad consume el evento de forma intencional. De lo contrario, muestra super.dispatchGenericMotionEvent(ev) para que el evento pueda continuar a través del envío normal.

Cómo controlar el gesto Atrás del sistema

Cuando una pantalla necesita un comportamiento personalizado hacia atrás, tu app debe controlar el gesto Atrás de los lentes con las mismas APIs de Android que usas para otras actividades, como OnBackPressedDispatcher y OnBackPressedCallback.

El gesto del usuario depende del tipo de lentes:

  • En los lentes de visualización, deslizar el dedo hacia abajo en el panel táctil realiza el gesto Atrás del sistema.
  • En los lentes con audio, deslizar el dedo hacia atrás en el panel táctil realiza el gesto Atrás del sistema.

Registra una devolución de llamada hacia atrás cuando la pantalla actual necesite interceptar Atrás, como cerrar una superposición o mostrar una confirmación de salida.

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")
    }
}

La devolución de llamada solo debe habilitarse cuando la pantalla activa deba interceptar Atrás. Inhabilita o quita la devolución de llamada cuando el comportamiento predeterminado del sistema o de navegación deba controlar Atrás.

Próximos pasos

Después de implementar el control de entrada para estos eventos, puedes obtener más información para controlar otros tipos de eventos de entrada en los siguientes temas: