Rewrite or serve map requests
MapLibre downloads the style, tiles, fonts, and icons from URLs in the style. You can change these requests from Kotlin code. Do this when:
- your tile server needs an API key or an
Authorizationheader, - requests must go to a different server than the URLs in the style, or
- the app has tiles or fonts in its resources, in a database, or in a file that MapLibre cannot read directly.
A MapRequestInterceptor changes the URL or headers of a request
before MapLibre sends it. A MapResourceProvider returns the data
for a request from your code, so MapLibre sends no request. Both work on every
platform, and they also apply to snapshots and offline downloads.
Add headers
Section titled “Add headers”This interceptor adds a token to requests for one tile server:
val interceptor = MapRequestInterceptor( headers = { request -> val currentToken = token.value if (request.url.startsWith("https://tiles.example.com/") && currentToken != null) { mapOf("Authorization" to "Bearer $currentToken") } else { emptyMap() } } )Check the URL before you add credentials. A style often loads resources from several servers, and a token for your server should not go to the others.
The example reads the token from a StateFlow on each request, so a new token
applies to later requests.
Rewrite URLs
Section titled “Rewrite URLs”rewriteUrl returns the URL to fetch instead, or null to keep the original.
This interceptor adds an API key as a query parameter:
val interceptor = MapRequestInterceptor( rewriteUrl = { request -> if (request.url.startsWith("https://tiles.example.com/")) { val separator = if ('?' in request.url) '&' else '?' "${request.url}${separator}key=$apiKey" } else { null } } )Serve data from app code
Section titled “Serve data from app code”A provider returns the bytes for URLs it accepts. Give these URLs your own
scheme in the style, such as app://tiles/{z}/{x}/{y}.pbf as a vector source’s
tile URL. This provider reads them from the app’s Compose resources:
// Serves app://tiles/14/2627/5721.pbf from composeResources/files/tiles/14/2627/5721.pbfval provider = MapResourceProvider(scheme = "app") { request -> Res.readBytes("files/" + request.url.removePrefix("app://")) }To choose the requests yourself, pass accepts and load, and return a
MapResourceLoad. Return
MapResourceLoad.NoContent for a tile that has no data, so MapLibre
draws an empty tile and reports no error. If load throws, the request fails:
val provider = MapResourceProvider( accepts = { request -> request.kind == MapResourceKind.Tile && request.url.startsWith("app://tiles/") }, load = { request -> when (val bytes = readTile(request.url)) { null -> MapResourceLoad.NoContent() else -> MapResourceLoad.Bytes(bytes) } }, )Install the interceptor and provider
Section titled “Install the interceptor and provider”Set them on the default runtime with DefaultMapRuntime.configure.
Call it once at app startup, such as in Application.onCreate on Android or in
main on desktop, before the app shows a map:
fun configureMaps(interceptor: MapRequestInterceptor, provider: MapResourceProvider) { DefaultMapRuntime.configure { requestInterceptor = interceptor resourceProvider = provider }}The settings cannot change after the runtime exists. To change a token, update the value that the interceptor reads.
To use different settings for some maps only, create a separate runtime with
createMapRuntime and pass it to rememberMapState.
Close the runtime when you no longer need it:
val runtime = remember { createMapRuntime { requestInterceptor = interceptor } }DisposableEffect(runtime) { onDispose { runtime.close() } }
val state = rememberMapState( runtime = runtime, baseStyle = BaseStyle.Uri("https://tiles.openfreemap.org/styles/liberty"), )MaplibreMap(state = state)