Overlapped Maps
This example demonstrates how to layer map views: a full-screen default map with a smaller, independent second map view overlapped on top of it. Each view has its own camera, so the two maps can be panned, zoomed and rotated independently.
Map Display and Cleanup
MainActivity overrides onCreate, which inflates the view binding, calls setContentView(binding.root) for the layout in res/layout/activity_main.xml, and enables edge-to-edge drawing so the map fills the screen. It then registers the SDK listeners.
When the activity is destroyed, onDestroy clears the listeners, deinitializes the SDK with GemSdk.release(), and exits the process so all native resources are freed.
The layout hosts a single com.magiclane.sdk.core.GemSurfaceView that fills the screen and renders the default map, with a toolbar pinned to the top.
Creating the Overlapped Map
The second map is created inside onDefaultMapViewCreated, which fires once the full-screen (default) map is ready and can be safely accessed. At that point the example:
- Pins the Magic Lane watermark logo to the bottom-right corner of the full-screen map, where it stays clear of the overlapped view.
- Produces the second map view on the same screen with
MapView.produce. - Calls
updateFocusViewport()to keep the logo clear of the system bars.
MapView.produce(screen, screenRatio, camera, postLambdasOnMain) creates a new map view on the given screen. The screenRatio is a normalized RectF expressed as a fraction of the parent screen - here SECOND_VIEW_RECT = RectF(0.0f, 0.0f, 0.5f, 0.5f), which places the second view in the bottom-left quarter of the screen. Passing null for the camera lets the SDK create and assign a dedicated one, which is what makes the second map independently navigable.
The remaining callbacks handle the map's lifecycle: onSdkInitFailed shows an error dialog and closes the activity if the SDK cannot initialize, onSurfaceChanged re-aligns the logo on resize (e.g. rotation), and SdkSettings.onApiTokenRejected warns the user when the API token is invalid. The UI work is marshalled onto the main thread by runOnAliveUi, which only runs while the activity is still alive.
Keeping the Logo Clear of the System Bars
Because the full-screen map draws edge-to-edge, it extends underneath the status and navigation bars. updateFocusViewport() sets the map view's focusViewport to the region left after subtracting the system window insets, so the bottom-right watermark logo stays visible. Map access must run on the SDK thread, so the work is wrapped in SdkCall.runSynced.
Releasing the Listeners
clearSdkListeners() is called from onDestroy to detach every callback and drop the reference to the second map view before the activity goes away. Resetting the listeners to empty lambdas guarantees that a late SDK callback can never touch a destroyed activity.
