Download maps for offline use
An offline pack holds the resources needed to show a region without a network:
map tiles, the style, and other assets. The OfflineManager
creates, tracks, and deletes packs.
Get the manager from the map runtime. A composable, a view model, a background
worker, or main can hold and use it:
val offlineManager = DefaultMapRuntime.instance.offlineManagerDownload a region
Section titled “Download a region”A pack is defined by a style URL, a bounding box, and a zoom range.
OfflineManager.create registers the pack in a paused state; call
OfflineManager.resume to start the download:
Button( onClick = { scope.launch { val pack = offlineManager.create( definition = OfflinePackDefinition.TilePyramid( styleUrl = "https://tiles.openfreemap.org/styles/liberty", bounds = BoundingBox(west = -123.0, south = 47.0, east = -122.0, north = 48.0), pixelRatio = pixelRatio, minZoom = 10, maxZoom = 14, ), metadata = "Seattle".encodeToByteArray(), ) offlineManager.resume(pack) } }) { Text("Download Seattle")}The library does not interpret the metadata bytes. Use them to identify the
pack later, for example with a display name.
OfflinePackDefinition.Shape downloads the region that covers a
GeoJSON geometry instead of a bounding box.
Track download progress
Section titled “Track download progress”OfflineManager.packs and OfflinePack.downloadProgress
are StateFlows. A composition collects them with collectAsState and
recomposes as the download proceeds:
val packs by offlineManager.packs.collectAsState()for (pack in packs) { key(pack) { val metadata by pack.metadata.collectAsState() val progress by pack.downloadProgress.collectAsState() val name = metadata?.decodeToString() ?: "Unnamed" when (val current = progress) { is DownloadProgress.Healthy -> Text("$name: ${current.completedResourceCount} resources, ${current.status}") is DownloadProgress.Error -> Text("$name: ${current.message}") is DownloadProgress.TileLimitExceeded -> Text("$name: tile limit ${current.limit}") is DownloadProgress.Unknown -> Text("$name: waiting for status") } }}A background worker can collect downloadProgress until the pack reports
DownloadStatus.Complete. The runtime lists stored packs before it becomes
available, so the first value of packs includes every pack from earlier
sessions.
pause and resume switch a pack between the Paused and Downloading
states. OfflineManager.invalidate re-checks a pack’s tiles
against the server and updates the ones that changed.
Delete a pack
Section titled “Delete a pack”OfflineManager.delete unregisters the pack and frees the
resources that no remaining pack requires:
for (pack in packs) { key(pack) { val metadata by pack.metadata.collectAsState() Button(onClick = { scope.launch { offlineManager.delete(pack) } }) { Text("Delete ${metadata?.decodeToString()}") } }}Once a pack is downloaded, the map uses its resources automatically when the device has no network. No map configuration is required.