{"id":15394,"plugin_id":"plugin_asdk_app_6a2c0bf33cb48191884d842b15ad3c20","kind":"skill","collection_source":null,"comparison_source":null,"observed_at":"2026-09-30T23:11:22.217Z","digest":"dcf3c7cc85c436fa11071a45fb7041c29bd114f243ede91a69caaca72f2064fc","against":null,"payload":{"name":"mapbox-android-patterns","description":"Official integration patterns for Mapbox Maps SDK on Android. Covers installation, adding markers, user location, custom data, styles, camera control, and featureset interactions. Based on official Mapbox documentation.","included_files":[{"relative_path":"AGENTS.md","size_in_bytes":8189},{"relative_path":"evals/evals.json","size_in_bytes":4010},{"relative_path":"references/annotations.md","size_in_bytes":1090},{"relative_path":"references/camera-styles.md","size_in_bytes":2397},{"relative_path":"references/compose.md","size_in_bytes":3613},{"relative_path":"references/custom-data.md","size_in_bytes":2391},{"relative_path":"references/interactions.md","size_in_bytes":3894},{"relative_path":"references/location-tracking.md","size_in_bytes":2261}],"skill_md_contents":"---\nname: mapbox-android-patterns\ndescription: Official integration patterns for Mapbox Maps SDK on Android. Covers installation, adding markers, user location, custom data, styles, camera control, and featureset interactions. Based on official Mapbox documentation.\n---\n\n# Mapbox Android Integration Patterns\n\nOfficial patterns for integrating Mapbox Maps SDK v11 on Android with Kotlin, Jetpack Compose, and View system.\n\n**Use this skill when:**\n\n- Installing and configuring Mapbox Maps SDK for Android\n- Adding markers and annotations to maps\n- Showing user location and tracking with camera\n- Adding custom data (GeoJSON) to maps\n- Working with map styles, camera, or user interaction\n- Handling feature interactions and taps\n\n**Official Resources:**\n\n- [Android Maps Guides](https://docs.mapbox.com/android/maps/guides/)\n- [API Reference](https://docs.mapbox.com/android/maps/api-reference/)\n- [Example Apps](https://github.com/mapbox/mapbox-maps-android/tree/main/Examples)\n\n---\n\n## Installation & Setup\n\n### Requirements\n\n- Android SDK 21+\n- Kotlin or Java\n- Android Studio\n- Free Mapbox account\n\n### Step 1: Configure Access Token\n\nCreate `app/res/values/mapbox_access_token.xml`:\n\n```xml\n<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources xmlns:tools=\"http://schemas.android.com/tools\">\n    <string name=\"mapbox_access_token\" translatable=\"false\"\n        tools:ignore=\"UnusedResources\">YOUR_MAPBOX_ACCESS_TOKEN</string>\n</resources>\n```\n\n**Get your token:** Sign in at [mapbox.com](https://account.mapbox.com/access-tokens/)\n\n### Step 1b: Internet permission (required)\n\nMaps need network access. Include this in `AndroidManifest.xml` — agents often omit it and only list location permissions later:\n\n```xml\n<uses-permission android:name=\"android.permission.INTERNET\" />\n```\n\n### Step 2: Add Maven Repository\n\nIn `settings.gradle.kts`:\n\n```kotlin\ndependencyResolutionManagement {\n    repositories {\n        google()\n        mavenCentral()\n        maven {\n            url = uri(\"https://api.mapbox.com/downloads/v2/releases/maven\")\n        }\n    }\n}\n```\n\n### Step 3: Add Dependency\n\nIn module `build.gradle.kts`:\n\n```kotlin\nandroid {\n    defaultConfig {\n        minSdk = 21\n    }\n}\n\ndependencies {\n    implementation(\"com.mapbox.maps:android:11.18.1\")\n}\n```\n\n**For Jetpack Compose:**\n\n```kotlin\ndependencies {\n    implementation(\"com.mapbox.maps:android:11.18.1\")\n    implementation(\"com.mapbox.extension:maps-compose:11.18.1\")\n}\n```\n\n---\n\n## Map Initialization\n\n### Jetpack Compose Pattern\n\n**Basic map:**\n\n```kotlin\nimport androidx.compose.runtime.*\nimport androidx.compose.foundation.layout.fillMaxSize\nimport androidx.compose.ui.Modifier\nimport com.mapbox.maps.extension.compose.*\nimport com.mapbox.maps.Style\nimport com.mapbox.geojson.Point\n\n@Composable\nfun MapScreen() {\n    MapboxMap(\n        modifier = Modifier.fillMaxSize()\n    ) {\n        // Initialize camera via MapEffect (Style.STANDARD loads by default)\n        MapEffect(Unit) { mapView ->\n            // Set initial camera position\n            mapView.mapboxMap.setCamera(\n                CameraOptions.Builder()\n                    .center(Point.fromLngLat(-122.4194, 37.7749))\n                    .zoom(12.0)\n                    .build()\n            )\n        }\n    }\n}\n```\n\n**With ornaments:**\n\n```kotlin\nMapboxMap(\n    modifier = Modifier.fillMaxSize(),\n    scaleBar = {\n        ScaleBar(\n            enabled = true,\n            position = Alignment.BottomStart\n        )\n    },\n    compass = {\n        Compass(enabled = true)\n    }\n) {\n    // Style.STANDARD loads by default\n}\n```\n\n### View System Pattern\n\n**Layout XML (activity_map.xml):**\n\n```xml\n<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<androidx.constraintlayout.widget.ConstraintLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\">\n\n    <com.mapbox.maps.MapView\n        android:id=\"@+id/mapView\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\" />\n\n</androidx.constraintlayout.widget.ConstraintLayout>\n```\n\n**Activity:**\n\n```kotlin\nimport android.os.Bundle\nimport androidx.appcompat.app.AppCompatActivity\nimport com.mapbox.maps.MapView\nimport com.mapbox.maps.Style\nimport com.mapbox.geojson.Point\n\nclass MapActivity : AppCompatActivity() {\n    private lateinit var mapView: MapView\n\n    override fun onCreate(savedInstanceState: Bundle?) {\n        super.onCreate(savedInstanceState)\n        setContentView(R.layout.activity_map)\n\n        mapView = findViewById(R.id.mapView)\n\n        mapView.mapboxMap.setCamera(\n            CameraOptions.Builder()\n                .center(Point.fromLngLat(-122.4194, 37.7749))\n                .zoom(12.0)\n                .build()\n        )\n\n        mapView.mapboxMap.loadStyle(Style.STANDARD)\n    }\n\n    override fun onStart() {\n        super.onStart()\n        mapView.onStart()\n    }\n\n    override fun onStop() {\n        super.onStop()\n        mapView.onStop()\n    }\n\n    override fun onDestroy() {\n        super.onDestroy()\n        mapView.onDestroy()\n    }\n}\n```\n\n---\n\n## Add Markers (Point Annotations)\n\nPoint annotations are the most common way to mark locations on the map.\n\n**Jetpack Compose:**\n\n```kotlin\nMapboxMap(modifier = Modifier.fillMaxSize()) {\n    MapEffect(Unit) { mapView ->\n        // Load style first\n        mapView.mapboxMap.loadStyle(Style.STANDARD)\n\n        // Create annotation manager and add markers\n        val annotationManager = mapView.annotations.createPointAnnotationManager()\n        val pointAnnotation = PointAnnotationOptions()\n            .withPoint(Point.fromLngLat(-122.4194, 37.7749))\n            .withIconImage(\"custom-marker\")\n        annotationManager.create(pointAnnotation)\n    }\n}\n\n// Note: Compose doesn't have declarative PointAnnotation component\n// Markers must be added imperatively via MapEffect\n```\n\n**View System:**\n\n```kotlin\n// Create annotation manager (once, reuse for updates)\nval pointAnnotationManager = mapView.annotations.createPointAnnotationManager()\n\n// Create marker\nval pointAnnotation = PointAnnotationOptions()\n    .withPoint(Point.fromLngLat(-122.4194, 37.7749))\n    .withIconImage(\"custom-marker\")\n\npointAnnotationManager.create(pointAnnotation)\n```\n\n**Multiple markers:**\n\n```kotlin\nval locations = listOf(\n    Point.fromLngLat(-122.4194, 37.7749),\n    Point.fromLngLat(-122.4094, 37.7849),\n    Point.fromLngLat(-122.4294, 37.7649)\n)\n\nval annotations = locations.map { point ->\n    PointAnnotationOptions()\n        .withPoint(point)\n        .withIconImage(\"marker\")\n}\n\npointAnnotationManager.create(annotations)\n```\n\n---\n\n## Show User Location (Display)\n\n**Step 1: Add permissions to AndroidManifest.xml:**\n\n```xml\n<uses-permission android:name=\"android.permission.INTERNET\" />\n<uses-permission android:name=\"android.permission.ACCESS_FINE_LOCATION\" />\n<uses-permission android:name=\"android.permission.ACCESS_COARSE_LOCATION\" />\n```\n\n**Step 2: Request permissions and show location:**\n\n```kotlin\n// Request permissions first (use ActivityResultContracts)\n\n// Show location puck\nmapView.location.updateSettings {\n    enabled = true\n    puckBearingEnabled = true\n}\n```\n\n---\n\n## Performance Best Practices\n\n### Reuse Annotation Managers\n\n```kotlin\n// Don't create new managers repeatedly\n// val manager = mapView.annotations.createPointAnnotationManager() // each call\n\n// Create once, reuse\nval pointAnnotationManager = mapView.annotations.createPointAnnotationManager()\n\nfun updateMarkers() {\n    pointAnnotationManager.deleteAll()\n    pointAnnotationManager.create(markers)\n}\n```\n\n### Batch Annotation Updates\n\n```kotlin\n// Create all at once\npointAnnotationManager.create(allAnnotations)\n\n// Don't create one by one in a loop\n```\n\n### Lifecycle Management\n\n```kotlin\n// Always call lifecycle methods\noverride fun onStart() {\n    super.onStart()\n    mapView.onStart()\n}\n\noverride fun onStop() {\n    super.onStop()\n    mapView.onStop()\n}\n\noverride fun onDestroy() {\n    super.onDestroy()\n    mapView.onDestroy()\n}\n```\n\n### Use Standard Style\n\n```kotlin\n// Standard style is optimized and recommended\nStyle.STANDARD\n\n// Use other styles only when needed for specific use cases\nStyle.STANDARD_SATELLITE // Satellite imagery\n```\n\n---\n\n## Troubleshooting\n\n### Map Not Displaying\n\n**Check:**\n\n1. Token in `mapbox_access_token.xml`\n2. Token is valid (test at mapbox.com)\n3. Maven repository configured\n4. Dependency added correctly\n5. Internet permission in manifest\n\n### Style Not Loading\n\n```kotlin\nmapView.mapboxMap.subscribeStyleLoaded { _ ->\n    Log.d(\"Map\", \"Style loaded successfully\")\n    // Add layers and sources here\n}\n```\n\n### Performance Issues\n\n- Use `Style.STANDARD` (recommended and optimized)\n- Limit visible annotations to viewport\n- Reuse annotation managers\n- Avoid frequent style reloads\n- Call lifecycle methods (onStart, onStop, onDestroy)\n- Batch annotation updates\n\n---\n\n## Reference Files\n\nLoad these references when you need detailed patterns for specific topics:\n\n- **`references/compose.md`** -- Jetpack Compose: dependencies, token setup, MapboxMap, annotations with click, GeoJSON, MapEffect\n- **`references/annotations.md`** -- Circle, Polyline, and Polygon annotation patterns\n- **`references/location-tracking.md`** -- Camera follow user location + get current location once\n- **`references/custom-data.md`** -- GeoJSON sources and layers: lines, polygons, points, update/remove\n- **`references/camera-styles.md`** -- Camera control (set, animate, fit) + map styles (built-in and custom)\n- **`references/interactions.md`** -- Featureset interactions, custom layer taps, long press, gestures\n\n---\n\n## Additional Resources\n\n- [Android Maps Guides](https://docs.mapbox.com/android/maps/guides/)\n- [API Reference](https://docs.mapbox.com/android/maps/api/11.18.1/)\n- [Interactions Guide](https://docs.mapbox.com/android/maps/guides/user-interaction/interactions/)\n- [Jetpack Compose Guide](https://docs.mapbox.com/android/maps/guides/using-jetpack-compose/)\n- [Example Apps](https://github.com/mapbox/mapbox-maps-android/tree/main/Examples)\n- [Migration Guide (v10 -> v11)](https://docs.mapbox.com/android/maps/guides/migrate-to-v11/)\n"},"changes":[],"summary":"First saved snapshot. No earlier version is available for comparison.","summary_kind":"deterministic","summary_metadata":{}}