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:
// Remove:
// implementation 'com.google.android.gms:play-services-maps:18.x.x'
// Add:
implementation 'org.mapmetrics.android-sdk:latest-version'Remove the Google Maps API key from AndroidManifest.xml:
<!-- Remove this: -->
<!-- <meta-data android:name="com.google.android.geo.API_KEY" android:value="..." /> -->Step 2: Replace the Map View
Layout 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
// ========== 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.MapMetricsMap
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.org/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 Maps | MapMetrics |
|---|---|
GoogleMap | MapMetricsMap |
MapView (gms) | MapView (maplibre) |
SupportMapFragment | SupportMapFragment |
OnMapReadyCallback | Lambda in getMapAsync {} |
com.google.android.gms.maps.model.LatLng | org.maplibre.android.geometry.LatLng |
Camera
| Google Maps | MapMetrics |
|---|---|
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 Maps | MapMetrics |
|---|---|
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 Maps | MapMetrics |
|---|---|
setOnMapClickListener | addOnMapClickListener |
setOnMapLongClickListener | addOnMapLongClickListener |
setOnMarkerClickListener | setOnMarkerClickListener |
setOnCameraMoveListener | addOnCameraMoveListener |
setOnCameraIdleListener | addOnCameraIdleListener |
UI Settings
| Google Maps | MapMetrics |
|---|---|
googleMap.uiSettings.isZoomControlsEnabled | No built-in controls (add custom) |
googleMap.uiSettings.isCompassEnabled | map.uiSettings.isCompassEnabled |
googleMap.uiSettings.isScrollGesturesEnabled | map.uiSettings.isScrollGesturesEnabled |
googleMap.uiSettings.isZoomGesturesEnabled | map.uiSettings.isZoomGesturesEnabled |
googleMap.uiSettings.isRotateGesturesEnabled | map.uiSettings.isRotateGesturesEnabled |
googleMap.uiSettings.isTiltGesturesEnabled | map.uiSettings.isTiltGesturesEnabled |
What's Different in MapMetrics
| Feature | Google Maps | MapMetrics |
|---|---|---|
| Styling | Limited JSON style | Full MapLibre style spec |
| Data layers | Limited overlays | GeoJSON sources + layers (fill, line, circle, symbol, heatmap, fill-extrusion) |
| Expressions | Not available | Data-driven styling with expressions |
| Vector tiles | Not available | Full MVT support |
| Offline | Limited caching | Full offline region management |
| Open source | Proprietary | Built on MapLibre GL (open source) |
| Pricing | Pay per load | MapMetrics pricing model |
Step 4: Lifecycle
Both SDKs require forwarding lifecycle events. The pattern is identical:
// 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
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.Marker API is similar — Basic
MarkerOptionswork almost identically. For advanced markers (100+), switch to symbol layers.No built-in zoom controls — MapMetrics doesn't have default on-screen zoom buttons. See Navigation Controls to add your own.
Powerful layer system — MapMetrics gives you GeoJSON sources, data-driven expressions, and multiple layer types that far exceed Google Maps' overlay API.
Next Steps
- Getting Started — Fresh setup guide
- Configuration — Map configuration options
- GeoJSON Guide — Leverage the layer system
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.