Skip to content

PMTiles

Note

You can find the full source code of this example in PMTilesActivity.kt of the MapLibreAndroidTestApp.

Starting MapLibre Android 11.7.0, PMTiles archives are supported as tile sources. Prefix any tile source URL with pmtiles:// to read from a PMTiles archive:

  • pmtiles://https:// — stream tiles from a remote file
  • pmtiles://file:// — read a file from device storage (use getExternalFilesDir or filesDir for the path)

The pmtiles:// prefix works with any tile source type (e.g. vector, raster, raster-dem, etc.), from a style JSON or dynamically.

Unlike MapLibre GL JS, which resolves relative URLs against the style's base URL, MapLibre Native requires the URL inside pmtiles:// to be fully specified (e.g. pmtiles://https://example.com/tiles.pmtiles, not pmtiles://tiles.pmtiles).

Note: PMTiles sources do not support offline pack downloads or caching.

Loading a style that uses PMTiles sources

Load a style JSON that references pmtiles:// sources. The example below loads a satellite imagery basemap of the Central Alps and sets the initial camera position:

map.setStyle("https://demotiles.maplibre.org/pmtiles/raster/style-imagery.json") { style ->
    map.cameraPosition = CameraPosition.Builder()
        .target(LatLng(47.5, 12.0))
        .zoom(9.0)
        .build()

Adding a PMTiles source directly

Add vector sources from PMTiles archives to an already-loaded style. The example overlays two places datasets — Overture Maps (yellow) and Foursquare OS Places (blue) — both using CircleLayer. The setSourceLayer call names the layer within the archive to render:

val overtureSource = VectorSource(
    "overture-places",
    "pmtiles://https://overturemaps-tiles-us-west-2-beta.s3.amazonaws.com/2026-01-21/places.pmtiles"
)
style.addSource(overtureSource)
val overtureLayer = CircleLayer("overture-layer", "overture-places")
overtureLayer.setSourceLayer("place")
overtureLayer.setProperties(
    PropertyFactory.circleColor(Color.parseColor("#f5c800")),
    PropertyFactory.circleRadius(4f),
    PropertyFactory.circleOpacity(0.6f)
)
style.addLayer(overtureLayer)

The same pattern works for raster archives using RasterSource and RasterLayer.

Note: raster-dem sources added programmatically cannot specify encoding via the current Android API. Define raster-dem sources with terrarium encoding in the style JSON instead, where the encoding field is fully supported.

Loading a local PMTiles file

For files on device storage, use file:// with an absolute path. The example below uses getExternalFilesDir(null) to locate a file downloaded to the app's external files directory:

val path = getExternalFilesDir(null)?.absolutePath + "/watercolor.pmtiles"
val source = RasterSource(
    "watercolor",
    "pmtiles://file://$path",
    256
)
style.addSource(source)
style.addLayer(RasterLayer("watercolor", "watercolor"))

Note: pmtiles://asset:// (files in src/main/assets/) is not currently supported. AssetManagerFileSource does not implement byte-range reads, which PMTiles requires to read its header and metadata. Use file:// from device storage instead. See the open issue for status.