A Spatial SDK app’s immersive activity is an AppSystemActivity, which extends VrActivity. This inheritance hierarchy provides a lifecycle that builds upon the traditional Android activity lifecycle while adding spatial and VR-specific callbacks.
The lifecycle of a spatial activity extends the traditional Android activity lifecycle. Spatial SDK provides additional lifecycle callbacks such as onSceneReady, onVRReady, and onSpatialShutdown that help you manage the state of your XR app throughout its lifecycle.
In your immersive app, you should extend AppSystemActivity for the immersive activity. However, for your panel activities (either hybrid activities or the activity-based panels), you can simply extend Android’s Activity class.
Android lifecycle callbacks
You should follow the Android Activity Lifecycle when developing a Spatial SDK app. The guidance from the official Android site also applies to the Spatial SDK activity lifecycle.
Initialization
onCreate is called when the activity is first created. In a Spatial SDK app, this is where:
Spatial SDK is initialized.
Features and panels are registered.
Components and systems are registered.
glXF resources are usually loaded.
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) // Important: Always call super.onCreate() first
// Register components
componentManager.registerComponent<MyCustomComponent>(MyCustomComponent.Companion)
// Register systems
systemManager.registerSystem(MyCustomSystem())
// Load resources
loadGLXF { composition ->
// Handle loaded 3D models
val environmentEntity = composition.getNodeByName("environment").entity
// Configure entity components
}
}
onStart
Called when the activity becomes visible to the user. The VrActivity implementation forwards this call to all registered features via featureManager.onStart().
onResume
Called when the activity starts interacting with the user.
onPause
Called when the system is about to put the activity into the background. If the activity is finishing in this callback, it will invoke onSpatialShutdown().
onStop
Called when the activity is no longer visible to the user. Consider putting shutdown logic in onSpatialShutdown() instead as onStop is not guaranteed to be called.
onDestroy
Called before the activity is destroyed. Consider putting shutdown logic in onSpatialShutdown() instead as onDestroy is not guaranteed to be called.
Spatial lifecycle callbacks
Some spatial callbacks are tied to the Android lifecycle, while others are not. For example, onVrReady is triggered when 3D graphics is ready and loaded, but it’s not tied to any Android lifecycle. This section describes each callback in detail.
onSceneReady
This callback is triggered on the first onResume(), after the scene is loaded in onCreate(). This is the ideal place to:
Configure the scene environment and lighting.
Set up the reference space for tracking.
Create entities in the scene.
override fun onSceneReady() {
super.onSceneReady() // Important: Always call super.onSceneReady() first
// Set the reference space for tracking
scene.setReferenceSpace(ReferenceSpace.LOCAL_FLOOR)
// Configure lighting
scene.setLightingEnvironment(
ambientColor = Vector3(0f),
sunColor = Vector3(7.0f, 7.0f, 7.0f),
sunDirection = -Vector3(1.0f, 3.0f, -2.0f),
environmentIntensity = 0.3f
)
// Set environment map
scene.updateIBLEnvironment("environment.env")
// Set the view origin
scene.setViewOrigin(0.0f, 0.0f, 0.0f, 0.0f)
// Create entities in the scene
Entity.create(
listOf(
Mesh(Uri.parse("mesh://skybox"), hittable = MeshCollision.NoCollision),
Material().apply {
baseTextureAndroidResourceId = R.drawable.skydome
unlit = true
},
Transform(Pose(Vector3(x = 0f, y = 0f, z = 0f)))
)
)
}
onSceneTick
This callback is triggered every tick when the activity is run. It’s recommended to avoid overriding this method and instead create systems that handle per-tick logic.
onVRReady
This callback is not tied to any Android lifecycle. It is triggered when the VR system is initialized and ready, or when the app changes from 2D mode to immersive (VR) mode. This is different from onSceneReady as it specifically indicates that the VR subsystems (like tracking, controllers, and so on) are ready for use.
onVRPause
This callback is not tied to any Android lifecycle. It is triggered when the VR system is paused or when the app changes from immersive (VR) mode to 2D mode.
onHMDMounted
This callback is not tied to any Android lifecycle. It is triggered when the user puts on the headset. This is useful for:
Starting experiences that should only run when the user is wearing the headset
onHMDUnmounted
This callback is not tied to any Android lifecycle. This callback is triggered when the user takes off the headset. This is useful for:
Pausing experiences that should only run when the user is wearing the headset.
Adjusting UI or interactions based on the user’s absence.
onRecenter
This callback is not tied to any Android lifecycle. This callback is triggered when the VR system is recentered. This is useful for:
Adjusting the position of UI elements or objects in the scene.
Resetting the user’s position in the virtual environment.
onSpatialShutdown
This callback is triggered when the Spatial SDK is shutting down. While Android’s onStop or onDestroy is not guaranteed to be called, onSpatialShutdown is guaranteed to be called before the activity is destroyed. This is useful for doing any final cleanup of Spatial SDK-related resources, such as entities and scene objects.
override fun onSpatialShutdown() {
// Destroy entities
entity.destroy()
super.onSpatialShutdown() // Important: Always call super.onSpatialShutdown() last
}
Registration methods
registerFeatures
This method is called during onCreate to register the features that your app will use. Features are the building blocks of Spatial SDK functionality, such as VR support, input handling, animations, and debugging tools.
override fun registerFeatures(): List<SpatialFeature> {
val features = mutableListOf<SpatialFeature>(
VRFeature(this),
IsdkFeature(this, spatial, systemManager),
PanelAnimationFeature()
)
// Add debug features in development builds
if (BuildConfig.DEBUG) {
features.add(CastInputForwardFeature(this))
features.add(HotReloadFeature(this))
features.add(DataModelInspectorFeature(spatial, this.componentManager))
}
return features
}
registerPanels
This method is called during onCreate to register the UI panels that your app will use. Panels are 2D UI surfaces that can be placed in 3D space.