Gérer les entrées physiques des lunettes audio et avec affichage

Appareils XR concernés
Ces conseils vous aident à créer des expériences pour ces types d'appareils XR.
Lunettes audio et
d'affichage

Pour capturer et traiter les entrées utilisateur qui sont transmises à l'activité projetée de votre application, ou pour implémenter des comportements personnalisés du pavé tactile, utilisez des entrées de pointeur indirectes. Pour gérer d'autres types d'événements (tels que l'action de la caméra), consultez les sections suivantes de ce guide.

Gérer l'action de la caméra

Chaque fois qu'un utilisateur appuie sur le bouton de la caméra d'un appareil, le système transmet un événement d'entrée à l'activité projetée de votre application en tant qu' ProjectedInputEvent.ProjectedInputAction.TOGGLE_APP_CAMERA action. Votre application peut observer cette action à l'aide d'un répartiteur dédié :

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

Inspecter les événements de mouvement génériques

Utilisez dispatchGenericMotionEvent pour inspecter les événements de mouvement génériques transmis à l'activité projetée de votre application. Les événements de mouvement génériques sont transmis à la limite de l'activité et ne nécessitent pas de composant Jetpack Compose Glimmer ciblé.

Un MotionEvent peut inclure les éléments suivants :

Toutes les valeurs ne sont pas significatives pour chaque action. Inspectez l'action et la source avant de traiter un événement brut comme un geste terminé.

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

Ne renvoyez true que lorsque l'activité consomme intentionnellement l'événement. Sinon, renvoyez super.dispatchGenericMotionEvent(ev) pour que l'événement puisse continuer à être distribué normalement.

Gérer le geste "Retour" du système

Lorsqu'un écran nécessite un comportement de retour personnalisé, votre application doit gérer le geste "Retour" des lunettes à l'aide des mêmes API Android que celles que vous utilisez pour d'autres activités, telles que OnBackPressedDispatcher et OnBackPressedCallback.

Le geste de l'utilisateur dépend du type de lunettes :

  • Sur les lunettes d'affichage, balayer vers le bas sur le pavé tactile effectue le geste "Retour" du système.
  • Sur les lunettes audio, balayer vers l'arrière sur le pavé tactile effectue le geste "Retour" du système.

Enregistrez un rappel de retour lorsque l'écran actuel doit intercepter le retour, par exemple pour fermer une superposition ou afficher une confirmation de sortie.

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

Le rappel ne doit être activé que lorsque l'écran actif doit intercepter le retour. Désactivez ou supprimez le rappel lorsque le comportement par défaut du système ou de la navigation doit gérer le retour.

Étapes suivantes

Après avoir implémenté la gestion des entrées pour ces événements, vous pouvez en savoir plus sur la gestion d'autres types d'événements d'entrée dans les rubriques suivantes :