Skip to main content
Version: 1.x (beta)

GeoARSDK with Jetpack Compose

WemapGeoARComposeSDK adds one composable, WemapGeoAR, over WemapGeoARSDK's GeoARView. It is the Compose counterpart of GeoAR in the iOS SDK's SwiftUI layer.

For the View-based API — and for creating a session, which is identical either way — see GeoARSDK Getting Started. Much of this page mirrors MapSDK with Jetpack Compose; only the differences are spelled out here.

Installation

implementation("com.getwemap.sdk:geo-ar-compose:<version>")

It brings com.getwemap.sdk:geo-ar with it, and requires minSdk 24 and Java 17 — ARCore and SceneView set that floor, not this module. A Compose BOM of 2026.06.01 or newer is needed.

Usage

@Composable
fun ARScreen(session: CoreSession, locationSource: LocationSource) {

var arView by remember { mutableStateOf<GeoARView?>(null) }

WemapGeoAR(
session = session,
modifier = Modifier.fillMaxSize(),
onLoaded = { view ->
arView = view
view.locationManager.locationSource = locationSource
},
onFailed = { error -> Log.e("GeoAR", "Failed to load the AR view", error) }
)

val coordinate by (arView?.locationManager?.coordinates ?: emptyFlow())
.collectAsStateWithLifecycle(null)

coordinate?.let { CoordinateReadout(it) }
}

Camera permission must be granted before this composable enters composition, and the scene needs a LocationSource from WemapPositioningSDK attached to locationManager to be positioned at all.

Parameters

ParameterPurpose
sessionThe session this view renders. Required. Note the type is CoreSession, not MapSession.
modifierStandard Compose modifier.
configGeoARViewConfig. Read once, at creation.
isOpaqueWhether the scene draws an opaque background. Read once, at creation; ignored when factory is supplied.
onLoadedInvoked with the loaded AR view. Its managers are available from here on.
onFailedInvoked with the loading error.
onPhaseChangeEvery LoadPhase transition, including the initial Loading.
factoryBuilds the view — see below.

What is deliberately missing

  • No camera state. WemapMap has cameraPositionState because a map camera is app state you may want to persist, restore or drive. The AR camera follows the device and the user's position, so there is nothing to drive. This matches the iOS SDK, where GeoAR has no camera binding either.
  • No onTouch. The Map SDK reports taps that selected no POI; the AR scene has no equivalent signal. Collect pointOfInterestManager.touchedPois for the taps that did hit something.
  • No wrapper parameters for the user coordinate, navigation info or POI selection. They are already flows — locationManager.coordinates, navigationManager.navigationInfoUpdates, pointOfInterestManager.selectionUpdates — so collectAsStateWithLifecycle() reads them directly.

factory is not for a subclass here

WemapMap's factory exists for integrators with a WemapMapView subclass. GeoARView is final, so this one exists for a different reason: reaching the constructor arguments the composable does not expose, above all sharedLifecycle.

Supply it when the view tree has no lifecycle owner for the view to discover — a plain ComposeView inside a Dialog, for example:

val lifecycle = LocalLifecycleOwner.current.lifecycle

WemapGeoAR(
session = session,
factory = { context -> GeoARView(context, sharedLifecycle = lifecycle) }
)

Note this is safe on GeoARView — unlike WemapMapView, where assigning the lifecycle before the view attaches would drop its save-state registration. GeoARView has no save state.

Everything else

Session ownership, onLoaded not being replayed, and mirroring an event flow into state all work exactly as on the Map side — see MapSDK with Jetpack Compose.