Skip to content

Both copy text to your clipboard — Build with AI copies a setup prompt to paste into Claude Code, Cursor, Codex or Copilot; Copy page as Markdown copies this page to paste into a chat. How it works

Migrate from Google Maps to MapMetrics ​

This guide helps you migrate an existing Android app from the Google Maps SDK to the MapMetrics SDK, covering the key API differences and code changes needed.

Prerequisites ​

  • An existing Android project using com.google.android.gms:play-services-maps
  • A MapMetrics API key from the MapMetrics Portal

Step 1: Update Dependencies ​

Replace the Google Maps dependency in build.gradle:

gradle
// Remove:
// implementation 'com.google.android.gms:play-services-maps:18.x.x'

// Add:
implementation 'org.mapmetrics.android-sdk:mapmetrics-native-sdk:1.0.3'

Remove the Google Maps API key from AndroidManifest.xml:

xml
<!-- Remove this: -->
<!-- <meta-data android:name="com.google.android.geo.API_KEY" android:value="..." /> -->

Step 2: Replace the Map View ​

Layout XML ​

xml
<!-- Google Maps -->
<!-- <com.google.android.gms.maps.MapView ... /> -->

<!-- MapMetrics -->
<org.maplibre.android.maps.MapView
    android:id="@+id/mapView"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

Activity Code ​

kotlin
// ========== GOOGLE MAPS ==========
import com.google.android.gms.maps.GoogleMap
import com.google.android.gms.maps.MapView
import com.google.android.gms.maps.OnMapReadyCallback
import com.google.android.gms.maps.model.LatLng
import com.google.android.gms.maps.model.MarkerOptions
import com.google.android.gms.maps.CameraUpdateFactory

class MapActivity : AppCompatActivity(), OnMapReadyCallback {
    private lateinit var mapView: MapView

    override fun onMapReady(googleMap: GoogleMap) {
        googleMap.moveCamera(
            CameraUpdateFactory.newLatLngZoom(LatLng(48.8566, 2.3522), 12f)
        )
        googleMap.addMarker(
            MarkerOptions().position(LatLng(48.8584, 2.2945)).title("Eiffel Tower")
        )
    }
}

// ========== MAPMETRICS ==========
import org.maplibre.android.maps.MapView
import org.maplibre.android.maps.MapLibreMap
import org.maplibre.android.maps.Style
import org.maplibre.android.geometry.LatLng
import org.maplibre.android.annotations.MarkerOptions
import org.maplibre.android.camera.CameraPosition
import org.maplibre.android.camera.CameraUpdateFactory

class MapActivity : AppCompatActivity() {
    private lateinit var mapView: MapView

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_map)

        mapView = findViewById(R.id.mapView)
        mapView.onCreate(savedInstanceState)
        mapView.getMapAsync { map ->
            map.setStyle(
                Style.Builder().fromUri(
                    "https://gateway.mapmetrics-atlas.net/styles/YOUR_STYLE_ID?token=YOUR_API_KEY"
                )
            )
            map.cameraPosition = CameraPosition.Builder()
                .target(LatLng(48.8566, 2.3522))
                .zoom(12.0)
                .build()
            map.addMarker(
                MarkerOptions()
                    .position(LatLng(48.8584, 2.2945))
                    .title("Eiffel Tower")
            )
        }
    }
}

Step 3: API Mapping Reference ​

Core Classes ​

Google MapsMapMetrics
GoogleMapMapLibreMap
MapView (gms)MapView (maplibre)
SupportMapFragmentSupportMapFragment
OnMapReadyCallbackLambda in getMapAsync {}
com.google.android.gms.maps.model.LatLngorg.maplibre.android.geometry.LatLng

Camera ​

Google MapsMapMetrics
CameraUpdateFactory.newLatLng()CameraUpdateFactory.newLatLng()
CameraUpdateFactory.newLatLngZoom()CameraUpdateFactory.newLatLngZoom()
CameraUpdateFactory.newLatLngBounds()CameraUpdateFactory.newLatLngBounds()
googleMap.moveCamera()map.moveCamera()
googleMap.animateCamera()map.animateCamera()
—map.easeCamera() (constant speed)
CameraPosition.Builder().target().zoom().bearing().tilt()Same pattern, same methods

Markers ​

Google MapsMapMetrics
googleMap.addMarker(MarkerOptions)map.addMarker(MarkerOptions)
MarkerOptions().position().title().snippet()Same pattern
BitmapDescriptorFactory.fromResource()IconFactory.getInstance(ctx).fromBitmap()
marker.remove()map.removeMarker(marker)
googleMap.clear()map.clear()

Event Listeners ​

Google MapsMapMetrics
setOnMapClickListeneraddOnMapClickListener
setOnMapLongClickListeneraddOnMapLongClickListener
setOnMarkerClickListenersetOnMarkerClickListener
setOnCameraMoveListeneraddOnCameraMoveListener
setOnCameraIdleListeneraddOnCameraIdleListener

UI Settings ​

Google MapsMapMetrics
googleMap.uiSettings.isZoomControlsEnabledNo built-in controls (add custom)
googleMap.uiSettings.isCompassEnabledmap.uiSettings.isCompassEnabled
googleMap.uiSettings.isScrollGesturesEnabledmap.uiSettings.isScrollGesturesEnabled
googleMap.uiSettings.isZoomGesturesEnabledmap.uiSettings.isZoomGesturesEnabled
googleMap.uiSettings.isRotateGesturesEnabledmap.uiSettings.isRotateGesturesEnabled
googleMap.uiSettings.isTiltGesturesEnabledmap.uiSettings.isTiltGesturesEnabled

What's Different in MapMetrics ​

FeatureGoogle MapsMapMetrics
StylingLimited JSON styleFull MapLibre style spec
Data layersLimited overlaysGeoJSON sources + layers (fill, line, circle, symbol, heatmap, fill-extrusion)
ExpressionsNot availableData-driven styling with expressions
Vector tilesNot availableFull MVT support
OfflineLimited cachingFull offline region management
Open sourceProprietaryBuilt on MapLibre GL (open source)
PricingPay per loadMapMetrics pricing model

Step 4: Lifecycle ​

Both SDKs require forwarding lifecycle events. The pattern is identical:

kotlin
// Same for both Google Maps and MapMetrics
override fun onStart() { super.onStart(); mapView.onStart() }
override fun onResume() { super.onResume(); mapView.onResume() }
override fun onPause() { super.onPause(); mapView.onPause() }
override fun onStop() { super.onStop(); mapView.onStop() }
override fun onDestroy() { super.onDestroy(); mapView.onDestroy() }
override fun onSaveInstanceState(outState: Bundle) {
    super.onSaveInstanceState(outState)
    mapView.onSaveInstanceState(outState)
}

Step 5: Key Things to Note ​

  1. Style URL required — MapMetrics uses vector tile styles, so you must provide a style URL via setStyle(). There's no default map appearance without it.

  2. Marker API is similar — Basic MarkerOptions work almost identically. For advanced markers (100+), switch to symbol layers.

  3. No built-in zoom controls — MapMetrics doesn't have default on-screen zoom buttons. See Navigation Controls to add your own.

  4. Powerful layer system — MapMetrics gives you GeoJSON sources, data-driven expressions, and multiple layer types that far exceed Google Maps' overlay API.

Next Steps ​


Tip: The migration is mostly mechanical — class names change but patterns stay similar. The biggest win is gaining access to GeoJSON layers, data-driven styling, and vector tile sources that aren't available in Google Maps.