RootRecovery
, accessed via FMTCRoot.recovery
, allows access to the bulk download recovery system, which is designed to allow rescue (salvation and restarting) of failed downloads when they crashed due to an unexpected event.
RecoveredRegion
RecoveredRegion
s are wrappers containing recovery & some downloadable region information, around a DownloadableRegion
.
Once a RecoveredRegion
has been retreived, it contains the original BaseRegion
in the region
property.
To create a DownloadableRegion
using the other available information with a provided TileLayer
, use toDownloadable
.
A RecoveredRegion
(and a DownloadableRegion
generated from it) will point to only any remaining, un-downloaded tiles from the failed download.
The start
tile will be adjusted from the original to reflect the progress of the download before it failed, meaning that tiles already successfully cached (excluding buffered) will not be downloaded again, saving time and network transfers.
The end
tile will be either the original, or the maximum number of tiles normally in the region (which will have no resulting difference than null
, but allows for a quick estimate of the number of remaining tiles to be made without needing to recheck
the entire region).
FMTC provides the ability to bulk download areas of maps in one-shot, known as 'regions'. There are multiple different types/shapes of regions available.
Before using FMTC, especially to bulk download or import/export, ensure you comply with the appropriate restrictions and terms of service set by your tile server. Failure to do so may lead to any punishment, at the tile server's discretion.
This library and/or the creator(s) are not responsible for any violations you make using this package.
For example, OpenStreetMap's tile server forbids bulk downloading: https://operations.osmfoundation.org/policies/tiles. And Mapbox has restrictions on importing/exporting from outside of the user's own device.
For testing purposes, check out the testing tile server included in the FMTC project: Testing Tile Server.
Downloading is extremely efficient and fast, and uses multiple threads and isolates to achieve write speeds of hundreds of tiles per second (if the network/server speed allows). After downloading, no extra setup is needed to use them in a map (other than the usual Integrating With A Map).
Before you can get started, make sure you've initialised FMTC & created one or more Stores!
A region represents a geographical area only, not any of the other information required to start a download.
All types of region inherit from BaseRegion
.
RectangleRegion
s are defined by a LatLngBounds
: two opposite LatLng
s.
CircleRegion
s are defined by a center LatLng
and radius in kilometers.
If you instead have two coordinates, one in the center, and one on the edge, you can use 'latlong2's Distance.distance()
method, as below:
LineRegion
s are defined by a list of LatLng
s, and a radius in meters.
This could be used to download tiles along a planned travel route, for example hiking or long-distance driving. Import coordinates from a routing engine, or from a GPX/KML file for maximum integration!
This region may generate more tiles than strictly necessary to cover the specified region. This is due to an internal limitation with the region generation algorithm, which uses (rotated) rectangles to approximate the actual desired shape.
This type of region may consume more memory/RAM when generating tiles than other region types.
CustomPolygonRegion
s are defined by a list of LatLng
s defining the outline of a simple polygon.
Polygons should not contain self-intersections. These may produce unexpected results.
Holes are not supported, however multiple CustomPolygonRegion
s may be downloaded at once using a MultiRegion
.
MultiRegion
s are defined by a list of multiple BaseRegion
s (which may contain more nested MultiRegion
s).
When downloading, each sub-region specified is downloaded consecutively (to ensure that any start
& end
tile range defined is respected consistently.
Regions which overlap will still have the overlapping tiles downloaded for each region.
Multi region's advantage is that it reduces the number of costly setup and teardown operations. It also means that statistic measuring applies over all sub-regions, so it does not need to be managed indepedently.
It is also possible to reconstruct the region from a RecoveredRegion
: #recoveredregion.
BaseRegion
s must be converted to DownloadableRegion
s before they can be used to download tiles.
These contain the original BaseRegion
, but also some other information necessary for downloading, such as zoom levels and URL templates.
The TileLayer
passed to the options
parameter must include both a urlTemplate
(or WMS configuration) and a userAgentPackageName
, unless it is only being used to check
the number of tiles in the region.
Before continuing to downloading the region, use countTiles()
to count the number of tiles it will attempt to download. This is accessible through FMTCStore().download
.
The method takes the DownloadableRegion
generated above, and will return an int
number of tiles. For larger regions, this may take a few seconds.
This figure will not take into account any skipped sea tiles or skipped existing tiles, as those are handled at the time of download.
To start the download, use the startForeground
method on the existing store you wish to download to:
There are many options available to customize the download, which are described fully in the API reference:
The download starts as soon as the method is called; it does not wait for listeners.
Listening to the output streams of the download is something most apps will want to do, to display information to the user (unless operating in a headless mode or in the background).
There are two output streams returned as a record. One stream emits events that contain information about the download as a whole, whilst the other stream independently emits an event after the fetch/download of each tile in the region is attempted. See the API documentation for information on the exact emission frequencies of each stream. These are returned separately as the first stream emits events more frequently than the second, and this prevents tile events from needed to be repeated*.
An emitted TileEvent
may refer to a tile for which an event has been emitted previously.
See the API documentation for more information.
Listening, pausing, resuming, or cancelling subscriptions to the output streams will not start, pause, resume, or cancel the download. It will only change whether the download emits updates.
Instead, there are methods available to control the download itself.
If your user needs to temporarily pause the download, with the ability to resume it at some point later (within the same app session), use pause
and resume
.
Pausing does not interrupt any tiles that are being downloaded when pause
is invoked. Instead, the download will pause after the tile has been downloaded. pause
's returned Future
completes when the download has actually paused (or after resume
is called whilst still pausing).
Pausing also does not cause the buffer to be flushed (if buffering is in use).
If listening to the DownloadProgress
stream, an event will be emitted when pausing and resuming.
Use isPaused
to check whether the download is currently paused.
If your user needs to stop the download entirely, use cancel
.
Cancelling does not interrupt any tiles that are being downloaded when cancel
is invoked. The returned future completes when the download has stopped and been cleaned-up.
Any buffered tiles are written to the store before the future returned by cancel
is completed.
It is safe to use cancel
after pause
without resume
ing first.
A miniature tile server, intended to test and calibrate FMTC, has been included in the project.
Avoid making too many costly and slow requests to your chosen tile server during development by using this miniature tile server!
For internal testing and development purposes, it also doubles down as a handy way to test your application without making too many costly and slow requests to your chosen tile server. When in use with the example application, it can handle over 2000 tiles/second.
It is a very simple web HTTP server written in Dart, that responds to all* requests with a tile. There is a theoretically 90% chance that this tile will be a specific land tile, and a 10% chance that it will be a sea tile - designed to test the sea tile skipping functionality. There are only these two tiles - it is not a full tile server.
To use this tile server:
The tile server is hardcoded to use standard HTTP port 7070 to serve content, which is usually free. Other programs must not be using this port.
Download/compile & start the tile server (no permanent installation required)
On Windows or Linux Download a copy of the latest '<platform>-ts' artifact from GitHub Actions, and run the executable inside: https://nightly.link/JaffaKetchup/flutter_map_tile_caching/workflows/main/main
On other platforms Clone the FMTC GitHub repository to your device, then run '/tile_server/bin/tile_server.dart' manually
Use the following URL to connect to it
From the local device: http://localhost:7070/{z}/{x}/{y}.png
From the same network (on another device): http://<your-local-ip>:7070/{z}/{x}/{y}.png
To find your local IP address, follow the instructions for your OS here
Control the tile server using keyboard key presses in the console window
q
: Release port 7070 and quit the executable
UP arrow: Increase the artificial delay between request and response by 2ms
DOWN arrow: Decrease the artificial delay between request and response by 2ms