メインコンテンツまでスキップ

Manage Offline Data

This guide covers implementation of offline data. For details on the concepts behind style packs, tile regions, and tile packs, see the Concepts and Constraints guide.

Working with style packs

Style packs contain all non-tile resources required to render a map style offline. This includes loaded sources, fonts, styles and sprites. Style packs are usually much smaller than map data, typically only a few megabytes, and only need to be downloaded once per style.

Download a style pack

To download a style pack, call OfflineManager.loadStylePack(), providing a style URI and StylePackLoadOptions.

StylePackLoadOptions allows you to add custom metadata to the style pack (useful for tracking which styles are downloaded or storing user preferences), specify how glyphs should be rasterized, and whether to accept expired resources.

import com.mapbox.maps.MapboxMap
import com.mapbox.maps.OfflineManager
import com.mapbox.common.Value

val stylePackLoadOptions = StylePackLoadOptions.Builder()
.glyphsRasterizationMode(GlyphsRasterizationMode.IDEOGRAPHS_RASTERIZED_LOCALLY)
.metadata(hashMapOf(
"region" to Value.valueOf("tokyo"),
"downloaded" to Value.valueOf("2024-11-07")
))
.acceptExpired(false)
.build()

loadStylePack returns a Cancelable object, allowing you to abort the download by calling cancel(), and provides you with two callbacks:

  1. StylePackLoadProgressCallback tracks the progress of the download.
  2. StylePackCallback tracks the completion of the download or any errors that occur. It returns a StylePack object when the download completes successfully, which you can use to check the downloaded style package, including its expiration date.
// These callbacks are called on a background thread.
// You may need to switch to the main thread for UI updates.
val stylePackCancelable = offlineManager.loadStylePack(
StyleURI.STANDARD,
stylePackLoadOptions,
{ progress ->
//
// Handle progress here
//
}
) { expected ->
//
// Handle StylePack result
//
expected.fold(
{ stylePack ->
// Style pack download finishes successfully
println("Process $stylePack")
},
{ error ->
// Handle error occurred during the style pack download
if (error is StylePackError && error.type == StylePackErrorType.CANCELED) {
handleCancelation()
} else {
handleFailure()
}
}
)
}

// Cancel the download if needed
stylePackCancelable.cancel()

List available style packs

The OfflineManager offers a getAllStylePacks() method which returns an Expected type, encapsulating the array of style packs available or an error.

// Get a list of style packs that are currently available.
offlineManager.getAllStylePacks { expected ->
expected.fold(
{ stylePacks ->
handleStylePacks(stylePacks)
},
{ error ->
if (error is StylePackError) {
handleStylePackError(error)
} else {
handleFailure()
}
}
)
}

Update a style pack

Map styles are accessible via their style URI, but the underlying style resources may be updated over time. Even if a new version of the style exists, a style that is used offline in your app will not automatically update when a user returns to an area with network services and views the map while connected. This includes loaded sources, glyphs, sprites and 3D models. Your app will use the existing offline style pack until you explicitly refresh it.

You can manually refresh an existing style pack using OfflineManager.loadStylePack, passing it the same StyleURI and a StylePackLoadOptions with acceptExpired set to false (note that if the acceptExpired flag is set to true, the existing outdated resources will not be refreshed). During the refresh, any missing resources will be loaded and expired resources will be updated.

// Refresh an existing style pack
val refreshOptions = StylePackLoadOptions.Builder()
.glyphsRasterizationMode(GlyphsRasterizationMode.IDEOGRAPHS_RASTERIZED_LOCALLY)
.metadata(hashMapOf())
.acceptExpired(false)
.build()

offlineManager.loadStylePack(
StyleURI.STANDARD,
refreshOptions,
{ progress ->
// Handle progress
}
) { expected ->
// Handle completion
}

Delete a style pack

To remove offline data from the database, you must first retrieve the list of style packs as explained in the List available style packs section. Once this list has been retrieved, it may be used to select the style pack to be deleted.

Delete a style pack using the OfflineManager.removeStylePack API and the style's URI.

offlineManager.removeStylePack(StyleURI.STANDARD)
Deletion may not happen immediately

After calling OfflineManager.removeStylePack, the downloaded style pack may not be immediately deleted. Instead, it will mark the underlying resources as not being a part of an offline style pack and they will be removed from the disk cache during its normal cleanup process.

Working with tile regions

Tile regions define the geographic areas and zoom levels that will be available offline. Before downloading tiles, you must define the region parameters and create tileset descriptors.

Define tile region load options

Before you can download a tile region, you must define the TileRegionLoadOptions that specify the geographic area, zoom levels, and style to be used for offline rendering.

TileRegionLoadOptions requires a geometry defining the area to be downloaded, an array of one or more tileset descriptors, and options for how to handle expired resources.

The tileset descriptor associates tile data (stored in a tile pack) with a given style (stored in a style pack). Use the tileset descriptor to define a tileset's zoom ranges and pixel ratio.

The tile region is a geographic region and its metadata. It is used to calculate which tile packs will be necessary to provide offline functionality in that region.

import com.mapbox.maps.MapboxMap
import com.mapbox.maps.OfflineManager
import com.mapbox.common.TileStore
import com.mapbox.geojson.Point
import com.mapbox.geojson.Geometry
import com.mapbox.common.Value

// When creating an OfflineManager instance, you must ensure that
// an access token is initialized
MapboxOptions.accessToken = "YOUR_ACCESS_TOKEN"

val offlineManager = OfflineManager()

// 1. Create the tileset descriptor
val options = [`TilesetDescriptorOptions`](https://docs.mapbox.com/android/maps/api/11.16.4/mapbox-maps-android/com.mapbox.maps/-tileset-descriptor-options/).Builder()
.styleURI(StyleURI.STANDARD)
.pixelRatio(resources.displayMetrics.density)
.minZoom(11)
.maxZoom(15)
.build()
val tilesetDescriptor = offlineManager.createTilesetDescriptor(options)

// 2. Create the TileRegionLoadOptions
val tokyoCoord = Point.fromLngLat(139.7671, 35.6812)
val tileRegionLoadOptions = TileRegionLoadOptions.Builder()
.geometry(tokyoCoord)
.descriptors(listOf(tilesetDescriptor))
.metadata(hashMapOf(
"name" to Value.valueOf("Tokyo"),
"type" to Value.valueOf("point")
))
.acceptExpired(false)
.build()

Download a tile region

With TileRegionLoadOptions defined, you can now trigger the download of the tile region, which will include all tile packs needed to cover the specified area and zoom range.

To create an asynchronous tile region download, call the tile store's loadTileRegion method and pass in the TileRegionLoadOptions you created. loadTileRegion will return a Cancelable object, which may be used to abort the download.

loadTileRegion will provide you with two callbacks:

  1. TileRegionLoadProgressCallback tracks the download progress.
  2. TileRegionCallback tracks the completion of the download or any errors that occur. It provides a TileRegion object when the download completes successfully, which you can use to check the downloaded tile region, including its expiration date.
val tileStore = TileStore.create()
val tileRegionId = "tokyo-downtown"

// Load the tile region
val tileRegionLoadOptions = TileRegionLoadOptions.Builder()
.geometry(tokyoCoord)
.descriptors(listOf(tilesetDescriptor))
.metadata(hashMapOf(
"name" to Value.valueOf("Tokyo"),
"type" to Value.valueOf("point")
))
.acceptExpired(false)
.build()

val tileRegionCancelable = tileStore.loadTileRegion(
tileRegionId,
tileRegionLoadOptions,
{ progress ->
//
// Handle progress here
//
}
) { expected ->
//
// Handle TileRegion result
//
expected.fold(
{ tileRegion ->
// Tile region download finishes successfully
println("Process $tileRegion")
},
{ error ->
// Handle error occurred during the tile region download
if (error is TileRegionError && error.type == TileRegionErrorType.CANCELED) {
handleCancelation()
} else {
handleFailure(error)
}
}
)
}

// Cancel the download if needed
tileRegionCancelable.cancel()

List available tile regions

Similarly, the TileStore offers a getAllTileRegions() method which returns an Expected type, encapsulating the list of tile regions available or an error.

// Get a list of tile regions that are currently available.
tileStore.getAllTileRegions { expected ->
expected.fold(
{ tileRegions ->
handleTileRegions(tileRegions)
},
{ error ->
if (error is TileRegionError) {
handleTileRegionError(error)
} else {
handleFailure()
}
}
)
}

Update a tile region

Downloaded tile regions can be refreshed using the same TileStore.loadTileRegion call you made when you initialized your download. Provide the same tile region ID (tileRegionId in the download initialization example above) and a TileRegionLoadOptions with acceptExpired set to false (note that if the acceptExpired flag is set to true, the existing outdated resources will not be refreshed). During the refresh, any missing resources will be loaded and any expired resources will be updated.

Normally, the map does not load new tile packs from the network, unless MapboxMapsOptions.tileStoreUsageMode is set to .readAndUpdate. If MapboxMapsOptions.tileStoreUsageMode is set to .readAndUpdate, the map will replace the outdated visible tile packs with fresh ones for all the tile regions that refer to these tile packs.

// Refresh an existing tile region
let refreshOptions = TileRegionLoadOptions(
geometry: Geometry(coordinate: tokyoCoord),
descriptors: [tilesetDescriptor],
metadata: ["name": "Tokyo", "type": "point"],
acceptExpired: false)!

tileStore.loadTileRegion(forId: tileRegionId, loadOptions: refreshOptions) { progress in
// Handle progress
} completion: { result in
// Handle completion
}

Delete a tile region

To remove offline data from the database, you must first retrieve the list of tile regions as explained in the List available tile regions section. Once this list has been retrieved, it may be used to select the tile region to be deleted.

You can delete a tile region with TileStore.removeTileRegion.

tileStore.removeTileRegion("tokyo-downtown")
Deletion may not happen immediately

Calling TileStore.removeTileRegion may not immediately delete the downloaded tile packs. Instead, it will mark the tile packs as not being a part of an offline tile region and they will be removed from the disk cache during its normal cleanup process.

You can fully remove tiles that have been downloaded by setting the disk quota to zero. This will make sure tile regions are fully removed. See the section on Tile store disk quota in the Concepts guide.

Performance Considerations

When implementing offline maps, keep these performance tips in mind:

  • Download timing: Download tile regions during off-peak hours or when connected to WiFi to avoid excessive cellular data usage
  • Battery impact: Large downloads can drain battery; inform users and allow them to control when downloads occur
  • Storage management: Watch available device storage before initiating downloads
  • Progressive downloads: For large regions, consider breaking them into smaller sub-regions that can be downloaded incrementally
  • Background downloads: Consider implementing background downloads for a better user experience

Troubleshooting Common Issues

Download fails or times out

  • Check network connectivity and Mapbox access token validity
  • Verify the geometry and zoom range are valid
  • Make sure enough storage space is available
  • Check if the 750 tile pack limit has been reached

Map appears blank offline

  • Verify both the style pack AND tile region have been downloaded
  • Check that the offline style URI matches the online map style URI
  • Confirm the zoom level is within the downloaded range
  • Make sure the user's location is within the downloaded geometry

Excessive storage usage

  • Review downloaded regions and remove unused ones
  • Adjust zoom ranges to avoid downloading unnecessary detail
  • Use more precise geometries (points/lines) instead of large polygons
  • Configure a disk quota to limit storage usage
この{Type}は役に立ちましたか?