Skip to Content
Android OptionsState and Lifecycle

State observation and session lifecycle

Keep one SDK instance per logical session and one active hosted view or fragment. Use the main thread for Android UI attachment and navigation controls. sdk.state is safe to read from any thread; listener callbacks are dispatched on the main dispatcher.

Current state and listener

state returns GraffityARState, with isSceneReady, vpsState, optional navigation, and optional lastError. See state fields.

Assign a retained GraffityARCloudListener to sdk.listener for state changes and discrete content, URL, guidance, and navigation events. The reference is weak. Setting it to null detaches the listener.

StateFlow

Observe with your host’s lifecycle so collection stops when that host is stopped:

import androidx.fragment.app.FragmentActivity import androidx.lifecycle.Lifecycle import androidx.lifecycle.lifecycleScope import androidx.lifecycle.repeatOnLifecycle import kotlinx.coroutines.flow.collect import kotlinx.coroutines.launch import tech.graffity.android.arcloud.publicapi.* fun FragmentActivity.observeSession(sdk: GraffityARCloudSDK) { lifecycleScope.launch { repeatOnLifecycle(Lifecycle.State.STARTED) { sdk.stateFlow.collect { state -> when (val vps = state.vpsState) { is GraffityARVPSState.Localized -> println("Localized section: ${vps.sectionId}") is GraffityARVPSState.Failed -> println(vps.error.localizedMessage(this@observeSession)) else -> Unit } } } } }

For a Fragment observing its view, use viewLifecycleOwner.lifecycleScope and viewLifecycleOwner.repeatOnLifecycle after its view exists.

Flow view and Compose

stateStream() returns the same backing StateFlow typed as Flow<GraffityARState>. It does not create an independent localization session or a new cold producer. Both APIs immediately provide the current value and share updates.

Compose apps can use sdk.stateFlow.collectAsStateWithLifecycle() for status UI. Keep the SDK in a stable owner; create its surface through AndroidView(factory = { sdk.createView(it) }), with teardown owned by the host.

StateFlow does not finish when the SDK shuts down. Lifecycle observation is cancelled with its owner; cancel any independently launched collector yourself.

Reset

sdk.reset() is suspending. It resets VPS and the current navigation leg, then requests a fresh localization. The selected destination is retained, so a navigation journey is planned again after localization. Reset does not replace configuration or credentials.

Launch reset from a coroutine while the surface is active, and handle GraffityARCloudError. Propagate CancellationException when catching coroutine failures.

End a session

  1. Stop your own observation and detach the listener.
  2. Remove the hosted view or fragment when the experience ends.
  3. Call the suspending sdk.shutdown() using a cleanup scope that can complete.
  4. Release the session owner and construct a fresh SDK for another experience.

Shutdown unregisters the session and closes services, SDK coroutines, renderer resources, and location updates. It is idempotent and terminal; do not reuse the instance.

A coroutine launched in lifecycleScope from onDestroy can be cancelled before cleanup completes. The quick-start host uses a separate scope for shutdown.

Surface and Activity lifecycle

Factory fragments start location/coordinator work in onStart and stop it in onStop. Factory views do so when attached/detached from the window. Removing a surface does not itself destroy the SDK.

GraffityARCloudHost lets a host Activity supply val graffityARCloudSDK when a restored surface’s registry ID no longer resolves. Create a valid SDK before a restored fragment needs its view. SDK registry IDs and instances do not survive process death.

Choose how your app handles Activity recreation. The quick-start Activity creates a fresh session and remounts its surface. A retained owner can reuse a live SDK across configuration changes, but must rebind its listener and shut down only when that logical session ends.

Authentication errors

A server HTTP 401 maps to InvalidAccessToken. The Android API has no token setter. Remove the failed experience, shut down its SDK, obtain a valid token through your app’s authentication flow, and construct a fresh session.