Hello Map
In this example you will learn how to render an interactive map centered on a desired location. The map is fully 3D, supporting pan, pinch-zoom, rotate and tilt. The example also shows how to react to SDK readiness, recover gracefully from an initialization failure or a rejected API token, and keep the map drawing edge-to-edge while respecting the system bars.
Map Display and Cleanup
The following code outlines the main activity, which displays the map and handles resource clean-up.
The MainActivity overrides onCreate, which inflates the view binding and calls setContentView(binding.root) for the layout defined in res/layout/activity_main.xml. It enables edge-to-edge drawing so the map fills the entire screen, then registers the SDK listeners.
When the activity is destroyed, onDestroy clears those listeners, deinitializes the SDK with GemSdk.release(), and exits the process so all native resources are freed.
The com.magiclane.sdk.core.GemSurfaceView is a custom View, part of Magic Lane's SDK, that displays the map. Here it fills the whole screen so the map is the only visible content.
Reacting to SDK Initialization and Map Events
registerSdkListeners() wires up the callbacks that drive the map's lifecycle. Because GemSurfaceView initializes the SDK asynchronously, these callbacks are how the activity learns when the map is ready or when something goes wrong:
onSdkInitFailedfires if the SDK fails to initialize. Since the SDK is not running at this point, the error message is resolved directly and shown in a dialog that closes the activity on dismissal.onDefaultMapViewCreatedfires once the first map view is ready - the moment the map can be safely accessed.onSurfaceChangedfires whenever the surface is resized, for example on screen rotation.SdkSettings.onApiTokenRejectedfires when the provided API token is rejected, prompting the user to supply a valid one.
The error callbacks marshal their UI work onto the main thread with runOnAliveUi, a small helper that only runs the block while the activity is still alive, avoiding callbacks that reach a destroyed activity.
Keeping the Logo Clear of the System Bars
Because the map draws edge-to-edge, it extends underneath the status and navigation bars. updateFocusViewport() keeps the Magic Lane logo (and other map decorations) inside the visible area by setting the map view's focusViewport to the region left over after subtracting the system window insets.
Map access must run on the SDK thread, so the work is wrapped in SdkCall.runSynced. This method is called once the map is ready (onDefaultMapViewCreated) and again on every resize (onSurfaceChanged), so the layout stays correct across rotations.
Releasing the Listeners
clearSdkListeners() is called from onDestroy to detach every callback before the activity goes away. Resetting them to empty lambdas guarantees that a late SDK callback can never touch a destroyed activity.
