mapbox-android-patterns
Installation
SKILL.md
Mapbox Android Integration Patterns
Official patterns for integrating Mapbox Maps SDK v11 on Android with Kotlin, Jetpack Compose, and View system.
Use this skill when:
- Installing and configuring Mapbox Maps SDK for Android
- Adding markers and annotations to maps
- Showing user location and tracking with camera
- Adding custom data (GeoJSON) to maps
- Working with map styles, camera, or user interaction
- Handling feature interactions and taps
Official Resources:
Installation & Setup
Requirements
- Android SDK 21+
- Kotlin or Java
- Android Studio
- Free Mapbox account
Step 1: Configure Access Token
Create app/res/values/mapbox_access_token.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools">
<string name="mapbox_access_token" translatable="false"
tools:ignore="UnusedResources">YOUR_MAPBOX_ACCESS_TOKEN</string>
</resources>
Get your token: Sign in at mapbox.com
Step 2: Add Maven Repository
In settings.gradle.kts:
dependencyResolutionManagement {
repositories {
google()
mavenCentral()
maven {
url = uri("https://api.mapbox.com/downloads/v2/releases/maven")
}
}
}
Step 3: Add Dependency
In module build.gradle.kts:
android {
defaultConfig {
minSdk = 21
}
}
dependencies {
implementation("com.mapbox.maps:android:11.18.1")
}
For Jetpack Compose:
dependencies {
implementation("com.mapbox.maps:android:11.18.1")
implementation("com.mapbox.extension:maps-compose:11.18.1")
}
Map Initialization
Jetpack Compose Pattern
Basic map:
import androidx.compose.runtime.*
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.ui.Modifier
import com.mapbox.maps.extension.compose.*
import com.mapbox.maps.Style
import com.mapbox.geojson.Point
@Composable
fun MapScreen() {
MapboxMap(
modifier = Modifier.fillMaxSize()
) {
// Initialize camera via MapEffect (Style.STANDARD loads by default)
MapEffect(Unit) { mapView ->
// Set initial camera position
mapView.mapboxMap.setCamera(
CameraOptions.Builder()
.center(Point.fromLngLat(-122.4194, 37.7749))
.zoom(12.0)
.build()
)
}
}
}
With ornaments:
MapboxMap(
modifier = Modifier.fillMaxSize(),
scaleBar = {
ScaleBar(
enabled = true,
position = Alignment.BottomStart
)
},
compass = {
Compass(enabled = true)
}
) {
// Style.STANDARD loads by default
}
View System Pattern
Layout XML (activity_map.xml):
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.mapbox.maps.MapView
android:id="@+id/mapView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Activity:
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import com.mapbox.maps.MapView
import com.mapbox.maps.Style
import com.mapbox.geojson.Point
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.mapboxMap.setCamera(
CameraOptions.Builder()
.center(Point.fromLngLat(-122.4194, 37.7749))
.zoom(12.0)
.build()
)
mapView.mapboxMap.loadStyle(Style.STANDARD)
}
override fun onStart() {
super.onStart()
mapView.onStart()
}
override fun onStop() {
super.onStop()
mapView.onStop()
}
override fun onDestroy() {
super.onDestroy()
mapView.onDestroy()
}
}
Add Markers (Point Annotations)
Point annotations are the most common way to mark locations on the map.
Jetpack Compose:
MapboxMap(modifier = Modifier.fillMaxSize()) {
MapEffect(Unit) { mapView ->
// Load style first
mapView.mapboxMap.loadStyle(Style.STANDARD)
// Create annotation manager and add markers
val annotationManager = mapView.annotations.createPointAnnotationManager()
val pointAnnotation = PointAnnotationOptions()
.withPoint(Point.fromLngLat(-122.4194, 37.7749))
.withIconImage("custom-marker")
annotationManager.create(pointAnnotation)
}
}
// Note: Compose doesn't have declarative PointAnnotation component
// Markers must be added imperatively via MapEffect
View System:
// Create annotation manager (once, reuse for updates)
val pointAnnotationManager = mapView.annotations.createPointAnnotationManager()
// Create marker
val pointAnnotation = PointAnnotationOptions()
.withPoint(Point.fromLngLat(-122.4194, 37.7749))
.withIconImage("custom-marker")
pointAnnotationManager.create(pointAnnotation)
Multiple markers:
val locations = listOf(
Point.fromLngLat(-122.4194, 37.7749),
Point.fromLngLat(-122.4094, 37.7849),
Point.fromLngLat(-122.4294, 37.7649)
)
val annotations = locations.map { point ->
PointAnnotationOptions()
.withPoint(point)
.withIconImage("marker")
}
pointAnnotationManager.create(annotations)
Show User Location (Display)
Step 1: Add permissions to AndroidManifest.xml:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
Step 2: Request permissions and show location:
// Request permissions first (use ActivityResultContracts)
// Show location puck
mapView.location.updateSettings {
enabled = true
puckBearingEnabled = true
}
Performance Best Practices
Reuse Annotation Managers
// Don't create new managers repeatedly
// val manager = mapView.annotations.createPointAnnotationManager() // each call
// Create once, reuse
val pointAnnotationManager = mapView.annotations.createPointAnnotationManager()
fun updateMarkers() {
pointAnnotationManager.deleteAll()
pointAnnotationManager.create(markers)
}
Batch Annotation Updates
// Create all at once
pointAnnotationManager.create(allAnnotations)
// Don't create one by one in a loop
Lifecycle Management
// Always call lifecycle methods
override fun onStart() {
super.onStart()
mapView.onStart()
}
override fun onStop() {
super.onStop()
mapView.onStop()
}
override fun onDestroy() {
super.onDestroy()
mapView.onDestroy()
}
Use Standard Style
// Standard style is optimized and recommended
Style.STANDARD
// Use other styles only when needed for specific use cases
Style.STANDARD_SATELLITE // Satellite imagery
Troubleshooting
Map Not Displaying
Check:
- Token in
mapbox_access_token.xml - Token is valid (test at mapbox.com)
- Maven repository configured
- Dependency added correctly
- Internet permission in manifest
Style Not Loading
mapView.mapboxMap.subscribeStyleLoaded { _ ->
Log.d("Map", "Style loaded successfully")
// Add layers and sources here
}
Performance Issues
- Use
Style.STANDARD(recommended and optimized) - Limit visible annotations to viewport
- Reuse annotation managers
- Avoid frequent style reloads
- Call lifecycle methods (onStart, onStop, onDestroy)
- Batch annotation updates
Reference Files
Load these references when you need detailed patterns for specific topics:
references/annotations.md-- Circle, Polyline, and Polygon annotation patternsreferences/location-tracking.md-- Camera follow user location + get current location oncereferences/custom-data.md-- GeoJSON sources and layers: lines, polygons, points, update/removereferences/camera-styles.md-- Camera control (set, animate, fit) + map styles (built-in and custom)references/interactions.md-- Featureset interactions, custom layer taps, long press, gestures
Additional Resources
Weekly Installs
272
Repository
mapbox/mapbox-a…t-skillsGitHub Stars
41
First Seen
Feb 1, 2026
Security Audits
Installed on
opencode246
gemini-cli246
codex245
github-copilot241
cursor236
kimi-cli232