Develop
Develop
Select your platform

Spatial SDK activity lifecycle

Updated: Sep 17, 2025

Overview

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.
Spatial SDK activity Lifecycle
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.

Inheritance hierarchy

Activity (Android)
   ↓
VrActivity (Spatial SDK)
   ↓
AppSystemActivity (Spatial SDK)
   ↓
YourActivity (Your immersive app)
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.
override fun registerPanels(): List<PanelRegistration> {
    return listOf(
        LayoutXMLPanelRegistration(
            R.id.main_panel,
            layoutIdCreator = { R.layout.main_panel },
            settingsCreator = {
                UIPanelSettings(
                    shape = CylinderShapeOptions(radius = 1.0f),
                    display = DpDisplayOptions(width = 720f),
                    style = PanelStyleOptions(themeResourceId = R.style.PanelAppThemeTransparent),
                    rendering = LayerRenderOptions()
                )
            }
        ),
        LayoutXMLPanelRegistration(
            R.id.settings_panel,
            layoutIdCreator = { R.layout.settings_panel },
            settingsCreator = { UIPanelSettings() }
        )
    )
}
Did you find this page helpful?
Thumbs up icon
Thumbs down icon