1. Antes de comenzar
Qué aprenderás
- Las experiencias del usuario únicas que hace posibles Android XR
- Cómo optimizar una app para auriculares de Android XR con la biblioteca de realidad extendida de Jetpack Compose
- Cómo usar elementos de la IU de la biblioteca de realidad extendida de Jetpack Compose
- Dónde obtener más información sobre la compilación de apps para Android XR
Qué no es este codelab
- Una guía para compilar apps para Android XR sin usar Compose. Consulta Cómo desarrollar una IU de apps para Android basadas en vistas.
- Una guía para compilar apps con Unity o con OpenXR para Android XR. Consulta Cómo desarrollar con Unity para Android XR y Cómo desarrollar con OpenXR.
Requisitos
- La versión preliminar de Android Studio más reciente
- Una computadora con capacidad para ejecutar el emulador de Android XR
- Experiencia con Kotlin y Jetpack Compose, por ejemplo, haber completado el curso Aspectos básicos de Android con Compose
- Experiencia en la creación de dispositivos virtuales de Android y ejecución de apps en ellos
- Experiencia con los modos y los paneles espaciales de Android XR, por ejemplo, haber completado el codelab Descubre los aspectos básicos de Android XR: Parte 1 - Modos y paneles espaciales
Qué compilarás
En este codelab, optimizarás aún más una app con algunas funciones de realidad extendida existentes. Para ello, agregarás elementos de la IU flotantes y personalizarás el entorno virtual que rodea al usuario mientras usa la app.
Punto de partida | Resultado final |
2. Prepárate
Obtén el código
- El código de este codelab se puede encontrar en el directorio
xr-fundamentals
dentro del repositorioxr-codelabs
de GitHub. Para clonar el repositorio, ejecuta el siguiente comando:
git clone https://github.com/android/xr-codelabs.git
- También tienes la opción de descargar el repositorio como archivo ZIP:
Abre el proyecto
- Después de iniciar Android Studio, importa el directorio
xr-fundamentals/part1
. El directorioxr-fundamentals/part2
contiene el código de la solución, que puedes consultar en cualquier momento si no logras avanzar o si deseas ver el proyecto completo.
Familiarízate con el código
- Después de abrir el proyecto en Android Studio, dedica un momento a analizar el código de partida.
- Si aún no realizaste el primer codelab ni usaste el emulador de Android XR, sigue los pasos que se indican en Ejecuta la app en el emulador de Android XR para ejecutarla.
3. Descubre los conceptos de la realidad extendida: orbitadores
Los orbitadores son elementos de la IU flotantes que están disponibles en el modo de espacio completo que suelen usarse para controlar el contenido dentro de los paneles espaciales o de otras entidades a las que está anclada su órbita. El uso de orbitadores para los controles de contenido le brinda más espacio al contenido, lo que significa que los usuarios pueden acceder rápidamente a las funciones contenidas en los orbitadores mientras el contenido principal permanece visible. Los orbitadores te brindan la versatilidad para integrar componentes de IU existentes (como barras de navegación) o crear otros nuevos.
Además, la API de Orbiter te permite renderizar el contenido de un orbitador donde lo haría normalmente cuando se ejecuta en el modo de espacio principal o en un dispositivo que no es de realidad extendida, y lo divide automáticamente en un orbitador cuando se ejecuta en el modo de espacio completo.
En el modo de espacio principal, este riel de navegación se renderiza dentro del panel principal de la app. | En el modo de espacio completo, el riel de navegación se divide en un orbitador conectado al panel principal. |
En este punto, la app contiene un botón en la barra superior para alternar entre el modo de espacio principal y el modo de espacio completo. Este botón es un ejemplo perfecto de un control que puede estar contenido en un orbitador cuando se ejecuta en el modo de espacio completo, ya que mover el control para que orbite el panel principal ayuda a que se destaque y, al mismo tiempo, indica visualmente que el control contraerá el contenido de la app en ese panel cuando se haga clic en él.
Estado actual | Qué implementarás |
Para obtener más información sobre las consideraciones de diseño de los orbitadores, consulta IU espacial.
4. Agrega un orbitador
Une el botón de activación del modo de espacio
Para convertir el botón de activación del modo de espacio en un orbitador, une el elemento componible ToggleSpaceModeButton
dentro de un elemento componible Orbiter
.
ui/component/XRFundamentalsTopAppBar .kt
import androidx.compose.foundation.shape.CornerSize
import androidx.compose.ui.Alignment
import androidx.compose.ui.unit.dp
import androidx.xr.compose.spatial.EdgeOffset
import androidx.xr.compose.spatial.Orbiter
import androidx.xr.compose.spatial.OrbiterEdge
import androidx.xr.compose.subspace.layout.SpatialRoundedCornerShape
...
Orbiter(
position = OrbiterEdge.Top,
alignment = Alignment.End,
offset = EdgeOffset.inner(16.dp),
shape = SpatialRoundedCornerShape(
CornerSize(percent = 100)
)
) {
ToggleSpaceModeButton()
}
Ahora, ejecuta la app. Cuando se ejecute en el modo de espacio principal, notarás que no cambió nada. Sin embargo, cuando hagas clic en el botón de activación y la app entre en el modo de espacio completo, notarás que el botón ya no se encuentra en la barra superior de la app, sino en el borde superior derecho del panel espacial principal.
El orbitador está anclado al panel espacial principal porque esa es la entidad espacial superior más cercana en el árbol de la IU. La posición exacta del orbitador en relación con el panel espacial principal se determina con los parámetros position
, alignment
y offset
. Intenta modificar estos parámetros para ver el rango de comportamientos que admiten.
Modo de espacio principal | Modo de espacio completo |
5. Descubre los conceptos de la realidad extendida: entornos espaciales
Usar un Orbiter
para personalizar la posición en el espacio 3D de los elementos de la IU es una excelente manera de mejorar la experiencia del usuario en dispositivos de realidad extendida. Puedes personalizar el entorno espacial en el que se encuentran los usuarios cuando usan tu app para mejorar aún más la experiencia.
Los entornos espaciales pueden incorporar recursos de profundidad, textura y geometría 3D para crear una experiencia visual envolvente y rica. Esto se logra usando una imagen de skybox esférica (en formato EXR) para proporcionar un fondo panorámico distante o un recurso de geometría (en formato glTF) para proporcionar elementos de primer plano y plano medio que se pueden combinar en un skybox. Por ejemplo, una app de transmisión de video por Internet podría usar un skybox nocturno con un glTF de un autocine con una pantalla de proyección y autos. Cuando crees recursos para configurar el entorno espacial de tus usuarios, asegúrate de que estos alcancen una resolución de alta calidad y, al mismo tiempo, mantengan un tamaño de archivo razonable. Consulta Optimiza los recursos del entorno para obtener más información.
Además, se puede controlar la opacidad del entorno espacial. Esto permite que una transmisión de video por Internet del mundo real pase y se combine con el entorno virtual, lo que puede ayudar a los usuarios a mantener el rumbo.
En el siguiente paso, agregarás un recurso de geometría a tu app y crearás un menú para permitir que el usuario elija su entorno.
Para obtener todos los detalles sobre el diseño y la implementación de entornos espaciales, consulta Entornos espaciales y Agrega entornos espaciales a tu app.
6. Permite que los usuarios cambien el entorno espacial
Cómo las apps controlan el entorno espacial
Antes de comenzar, es bueno comprender cómo las apps pueden controlar exactamente el entorno espacial.
A diferencia del contenido de los paneles, las apps no controlan directamente el entorno. En su lugar, pueden interactuar con la sesión de SceneCore para proporcionar una preferencia por el entorno que desean que use el sistema. Esta preferencia se representa con una SpatialEnvironmentPreference
, que consiste en una imagen EXR de skybox o un gLTF de geometría. Lo que sucede cuando tu app proporciona una preferencia depende de las capacidades de la app cuando establece la preferencia. Si tu app tiene la capacidad de cambiar el entorno, el sistema la usará de inmediato. De lo contrario, la preferencia se aplicará cuando tu app tenga esa capacidad.
Por ejemplo, las apps suelen no tener la capacidad de cambiar el entorno mientras se ejecutan en el modo de espacio principal, pero sí lo hacen cuando se ejecutan en el modo de espacio completo. Por lo tanto, si permites que un usuario establezca una preferencia de entorno mientras está en el modo de espacio principal, esa preferencia generalmente no tendrá efecto hasta que la app se ejecute en el modo de espacio completo.
Agrega una dependencia en la biblioteca de XR SceneCore
Para comenzar a modificar el entorno espacial, agrega una dependencia en la biblioteca XR SceneCore, que usarás para cargar los recursos del entorno y establecer las preferencias del entorno. También deberás agregar una dependencia en el artefacto kotlinx-coroutines-guava
, ya que algunas de las APIs para cargar recursos usan el tipo de datos ListenableFuture
.
libs.version.toml
[versions]
...
xrSceneCore = "1.0.0-alpha04"
kotlinxCoroutinesGuava = "1.10.2"
[libraries]
...
androidx-xr-scenecore = { group = "androidx.xr.scenecore", name = "scenecore", version.ref = "xrSceneCore"}
jetbrains-kotlinx-coroutines-guava = {group = "org.jetbrains.kotlinx", name="kotlinx-coroutines-guava", version.ref = "kotlinxCoroutinesGuava"}
app/build.gradle.kts
dependencies {
...
implementation(libs.androidx.xr.scenecore)
implementation(libs.jetbrains.kotlinx.coroutines.guava)
...
}
Agrega un recurso de entorno a tu proyecto
Para especificar una preferencia de entorno única, necesitarás un skybox o un recurso de geometría. En este codelab, solo usarás el recurso de geometría green_hills_ktx2_mipmap.glb
, que puedes encontrar en la carpeta part2
que contiene el código de la solución o en GitHub.
- Haz clic con el botón derecho en el módulo de la app en la ventana Project de Android Studio. Luego, selecciona New > Folder > Assets Folder y, luego, haz clic en Finish para crear la carpeta.
- Agrega el archivo GLB a la carpeta
app/src/main/assets
que acabas de crear.
Modela las opciones de entorno
Para simplificar la interacción entre el código de la IU y las APIs del sistema, puedes crear una clase de datos de Kotlin para modelar cada opción de entorno.
- Haz clic con el botón derecho en el paquete
com.example.android.xrfundamentals
de la ventana Project y selecciona New > Package. Ingresacom.example.android.xrfundamentals.environment
como el nombre del paquete. - Haz clic con el botón derecho en el paquete y selecciona New > Kotlin Class/File. Ingresa
EnvironmentOption
como nombre y haz clic en el tipo Data class. - Agrega el siguiente código en el archivo que acabas de crear:
EnvironmentOption.kt
data class EnvironmentOption(val name: String, val skyboxPath: String?, val geometryPath: String?)
val DEFAULT_ENVIRONMENT = EnvironmentOption("Default", null, null)
val ENVIRONMENT_OPTIONS = listOf(
DEFAULT_ENVIRONMENT,
EnvironmentOption("Green Hills", null, "green_hills_ktx2_mipmap.glb")
)
Agrega un ayudante para crear recursos de carga y mostrar SpatialEnvironmentPreference
A continuación, puedes agregar un método de ayuda a la clase de datos para facilitar la conversión de una EnvironmentOption
en la SpatialEnvrionmentPreference
correspondiente.
EnvironmentOption.kt
import androidx.xr.runtime.Session
import androidx.xr.scenecore.ExrImage
import androidx.xr.scenecore.GltfModel
import androidx.xr.scenecore.SpatialEnvironment
import kotlinx.coroutines.guava.await
...
data class EnvironmentOption(val name: String, val skyboxPath: String?, val geometryPath: String?) {
suspend fun toSpatialEnvironmentPreference(session: Session): SpatialEnvironmentPreference? {
if (skyboxPath == null && geometryPath == null) {
return null
} else {
val skybox = skyboxPath?.let {
ExrImage.create(session, it).await()
}
val geometry = geometryPath?.let {
GltfModel.create(session, it).await()
}
return SpatialEnvironmentPreference(skybox, geometry)
}
}
}
Ten en cuenta lo siguiente:
- Si el skybox y la geometría son nulos, se muestra un valor nulo para indicar que se debe usar la preferencia de entorno del sistema predeterminada. Consulta
setSpatialEnvironmentPreference
para obtener más información. - Los recursos
skybox
ygeometry
se crean de forma asíncrona porque estos recursos suelen ser bastante grandes y tardan en leerse en la memoria. En una app de producción, te recomendamos que almacenes en caché estos recursos en la memoria si cambias de entorno con frecuencia.
Implementa la IU de selección de entornos
Para implementar la IU, agregarás un segundo orbitador que rote entre las opciones de entorno cuando se haga clic en él.
Agrega el orbitador
- Haz clic con el botón derecho en el módulo
app
de la ventana Project y selecciona New > Vector Asset. Haz clic en el campo Clip art y busca y selecciona el recursolandscape
(de la familia de íconos Filled). Luego, haz clic en OK y, luego, en Next para crear el recurso. - Haz clic con el botón derecho en el paquete
com.example.android.xrfundamentals.ui.component
y selecciona New > Kotlin Class/File. IngresaEnvironmentSelectionOrbiter
como nombre y haz clic en el tipo File. - En el archivo que acabas de crear, agrega la siguiente implementación del elemento componible
EnvironmentSelectionOrbiter
.
EnvironmentSelectionOrbiter.kt
import androidx.compose.foundation.shape.CornerSize
import androidx.compose.material3.FilledTonalIconButton
import androidx.compose.material3.Icon
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.dp
import androidx.xr.compose.spatial.EdgeOffset
import androidx.xr.compose.spatial.Orbiter
import androidx.xr.compose.spatial.OrbiterEdge
import androidx.xr.compose.subspace.layout.SpatialRoundedCornerShape
import com.example.android.xrfundamentals.R
@Composable
fun EnvironmentSelectionOrbiter(
modifier: Modifier = Modifier,
onClick: () -> Unit = {},
) {
Orbiter(
position = OrbiterEdge.Top,
alignment = Alignment.Start,
offset = EdgeOffset.inner(16.dp),
shape = SpatialRoundedCornerShape(
CornerSize(100)
)
) {
FilledTonalIconButton(
modifier = modifier,
onClick = onClick,
) {
Icon(painterResource(R.drawable.baseline_landscape_24), "Show environment selection dialog")
}
}
}
- Por último, agrega el
EnvironmentSelectionOrbiter
dentro del panel espacial principal.
XRFundamentalsApp.kt
import androidx.xr.compose.platform.LocalSpatialCapabilities
import com.example.android.xrfundamentals.ui.component.EnvironmentSelectionOrbiter
...
SpatialPanel(...) {
// Only show the environment selection orbiter if the app is actually able to
// change the environment
if (LocalSpatialCapabilities.current.isAppEnvironmentEnabled) {
EnvironmentSelectionOrbiter(
onClick = { TODO() }
)
}
...
}
Cambia el entorno cuando se hace clic en el orbitador
Para que todo funcione, hay un último paso, que es llamar a setSpatialEnvironmentPreference
en el controlador de clics EnvironmentSelectionOrbiter
.
- Configura una variable para hacer un seguimiento de la opción de entorno actual (fuera del
Subspace
para que se mantenga el estado cuando se cambie entre el modo de espacio principal y el modo de espacio completo). Además, crea variables para la sesión de realidad extendida actual y un alcance de corrutina para llamar al ayudantetoSpatialEnvironmentPreference
.
XRFundamentalsApp.kt
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.rememberCoroutineScope
import androidx.xr.compose.platform.LocalSession
...
var currentEnvironmentOptionIndex by remember { mutableStateOf(0) }
Subspace {
val session = checkNotNull(LocalSession.current)
val scope = rememberCoroutineScope()
...
}
- Implementa la devolución de llamada
onClick
para rotar por las opciones de entorno.
XRFundamentalsApp.kt
EnvironmentSelectionOrbiter(
onClick = {
scope.launch {
currentEnvironmentOptionIndex =
(currentEnvironmentOptionIndex + 1) % ENVIRONMENT_OPTIONS.size
session.scene.spatialEnvironment.setSpatialEnvironmentPreference(
ENVIRONMENT_OPTIONS[currentEnvironmentOptionIndex].toSpatialEnvironmentPreference(
session
)
)
}
}
)
Ejecuta la app una vez más y comprueba que puedes cambiar entre los entornos Green Hills y predeterminado.
7. Felicitaciones
Para continuar aprendiendo a aprovechar al máximo la realidad extendida, consulta los siguientes recursos y ejercicios:
Lecturas adicionales
- Diseño para realidad extendida abarca los principios y las prácticas recomendadas de diseño para usar al compilar apps para Android XR.
- Cómo desarrollar con el SDK de realidad extendida de Jetpack incluye orientación técnica sobre las APIs y las herramientas que puedes usar al compilar tu experiencia de Android XR.
- La página de los lineamientos de calidad de las apps para Android XR describe los criterios de creación de una excelente experiencia del usuario.
- Explora la muestra de Hello Android XR.
Desafíos
- Busca o crea recursos de entorno adicionales y agrégalos como opciones.
- Modifica el controlador de entorno y la IU para permitir que el usuario establezca sus preferencias de transferencia con la API de
setPassthroughOpacityPreference
. Ten en cuenta que el control de transferencia está restringido por una capacidad diferente que la de cambiar los recursos del entorno.