Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
In a one word answer: Yes.
FMTC aims to provide all the functionality you will need for caching, in a way that requires little knowledge of the internals of 'flutter_map' and other caching fundamentals, and little effort from you (for most setups).
However, there are two main concerns that apply to most people:
Do you require all the functionality and control that FMTC offers?
Answering the second question is the more difficult than answering the first one, but it will tell you whether it's worth your while getting an alternative proprietary license if you need it.
---
You'll want to consider using FMTC over a custom DIY solution if you need any of the features below. These take a long time to reproduce and get right, but we've already done the hard work for you!
You need to provide bulk downloading or import/export functionality to your users
You or your users need a lot of fine-grain control over the cached tiles
However, if you match all of the following, you may find that a DIY/custom solution will work better for you.
You are developing a proprietary application, and we can't reach an agreement for an alternative license I aim to agree a price or deal that works for the both of us, so please do get in touch even if you're unsure if you can afford a license
You need only very basic caching
You need only browse caching
Can you abide by the GPL v3 license, or do you need an alternative proprietary license? See for more information about this
If you're still not sure, please get in touch: . I'm always happy to offer guidance :)
FMTC is licensed under GPL-v3.
Before using FMTC, ensure you comply with the appropriate rules and ToS set by your tile server. Failure to do so may lead to a permenant ban, or any other punishment.
This library and/or the creator(s) are not responsible for any violations you make using this package.
This page guides you through a simple, fast setup of FMTC that just enables basic browse caching, without any of the bells and whistles that you can discover throughout the rest of this documentation.
Depend on the latest version of the package from pub.dev, then import it into the appropriate files of your project.
Perform the startup procedure to allow usage of FMTC's APIs and connect to the underlying systems.
Create an isolated space to store tiles and other information to be accessed by the map and other methods.
Enable your FlutterMap
widget to use the caching and underlying systems of FMTC.
You should now have a basic working implementation of FMTC that caches tiles for you as you browse the map!
There's a lot more to discover, from management to bulk downloading, and from statistics to exporting/importing.
This package contains a full example application - prebuilt for Android and Windows - showcasing the most important features of this package and it's modules.
There are prebuilt applications for Android and Windows available on GitHub.
These are automatically built (using GitHub Actions) from the latest available commits every time the source files change, so may include functionality not yet available via pub.dev installation.
You can verify that these applications are built directly from the source code, and have not been maliciously modified to included malware, because the committer is always the GitHub Actions Bot, which can be verified by the profile icon linking to a non-profile page.
After installation, it will appear in the launcher like any other application.
It will require a very simple installation with no administrator privileges required, then it will appear in the Start Menu and search bars like any other application. You can optionally choose to create a desktop shortcut.
For other platforms, there are no prebuilt applications.
If you're developing a proprietary (non open-source) application, this affects you and your application's legal right to distribution. For more information, please see .
OpenStreetMap's can be : specifically bulk downloading is discouraged, and forbidden after zoom level 13. Other servers may have different terms.
To start using FMTC in your own app, please check out the guide instead.
To run the prebuilt Android application on most devices, download the .apk package (from ) to your device, then execute it to install it.
To run the prebuilt Windows application on most devices, download the .exe package (from ) to your device, then execute it to install it.
You'll have to , open the 'example' directory, and then build for your desired platform using Dart and Flutter as normal.
flutter_map
Installation & SetupYou must make sure you follow flutter_map
's installation and additional setup instructions.
This module is only supported on Android.
To install this module, follow the Installation instructions for this package.
Add the following to 'android\app\src\main\AndroidManifest.xml' and any other manifests:
This will allow the application to acquire the necessary permissions (should the user allow them at runtime) to a background process.
FOREGROUND_SERVICE
: allows the application to start a foreground service - a type of Android service that can run in the background, as long as the application isn't force stopped.
WAKE_LOCK
: allows the background process (technically foreground service) to run even when the device is locked/asleep. Also allows the acquisition of a WiFi lock.
REQUEST_IGNORE_BATTERY_OPTIMIZATIONS
(must be requested at runtime): assists with the background process not being killed by the system.
Background downloading needs to show notifications, which requires a 3rd party package. See it's installation/setup instructions:
To install this module, follow the Installation instructions for this package.
Please follow these additional instructions for supporting Android versions above 11 and building for release:
It is unknown whether this setup is needed in all cases, so it is recommended to follow these only when you receive errors during building your app.
Annotate that access is not needed to the Media, Audio, and Documents directories - this package uses only custom file types. Add these lines to your Podfile just before target 'Runner' do
.
Add UIBackgroundModes
capability with the fetch
and remote-notifications
keys to Xcode, to describe why your app needs to access background tasks - in this case to bulk download maps in the background.
Looking to start using FMTC in your project? Check out the Quickstart guide!
FMTC is currently somewhat unstable for applications with a wide public reach, due to some issues with the Isar dependency.
v8 is much more stable than v7.
This is the recommended method of installing this package as it ensures you only receive the latest stable versions, and you can be sure pub.dev is reliable.
Just import the package as you would normally, from the command line:
If you urgently need the latest version, a specific branch, or a specific fork, you can use this method.
Add the following lines to your pubspec.yaml file under the 'dependencies_override' section:
After installing the package, import it into the necessary files in your project:
Applies only to Roots
The recovery system is designed to rescue failed bulk downloads, in the event of an unexpected error - such as a fatal crash or other external event.
A plugin for 'flutter_map' providing advanced offline functionality
You're viewing documentation for an older version of FMTC (v8).
I work on all of my projects in my spare time, including maintaining (along with a team) Flutter's № 1 (non-commercially maintained) mapping library 'flutter_map', bringing it back from the brink of abandonment, as well as my own plugin for it ('flutter_map_tile_caching') that extends it with advanced caching and downloading. Additionally, I also own the Dart encoder/decoder for the QOI image format ('dqoi') - and I am slowly working on 'flutter_osrm', a wrapper for the Open Source Routing Machine.
Many thanks for any amount you can spare, it means a lot to me!
I am not a lawyer, and this information is to the best of my understanding. You are urged to read the license yourself for a thorough understanding.
Permissions of this strong copyleft license are conditioned on making available complete source code of licensed works and modifications, which include larger works using a licensed work, under the same license. Copyright and license notices must be preserved. Contributors provide an express grant of patent rights.
Essentially, whilst you can use this code within commercial projects, they must not be proprietary - they incorporate this 'licensed work' so they must be available under the same license. You must distribute your source code on request (under the same GPL v3 license) to anyone who uses your program.
However, I am willing to sell custom alternative proprietary licenses on a case-by-case basis and on request.
I learnt (and am still learning) to code with free, open-source software due to my age and lack of money, and for that reason, I believe in promoting open-source wherever possible to give equal opportunities to everybody, no matter their age or financial position. I'm not sure it's fair for commercial proprietary applications to use software made by people for free out of generosity. On the other hand, I am also trying to make a small amount of money from my projects, by donations or by selling licenses. And I recognise that commercial businesses may want to use my projects for their own proprietary applications.
Not quite sure about something? No problem. Please get in touch via any of these methods, and I'll be with you as soon as possible:
Some developers may have issues when releasing the app or uploading to TestFlight - see for the first report of this problem. This is due to some of this library's dependencies on platform plugins.
For more information about what this means, see .
For the latest documentation, see .
For more information about what this means, see .
Sponsorships & donations allow me to continue my projects and upgrade my hardware/setup, as well as allowing me to have some starting amount for further education and such-like. And of course, a small amount will find its way into my Jaffa Cakes fund () - why do you think my username has "Jaffa" in it?
This project is released under GPL v3. For detailed information about this license, see . summarises the license with the following paragraph:
Therefore, if you would like a license to use this software within a proprietary, I am willing to sell a (preferably yearly or usage based) license for a reasonable price. If this seems like what you want/need, please do not hesitate to get in touch at .
For bug reports & feature requests:
For implementation/general support: The #plugin channel on the
For other inquires:
◉ 📲
Caching × Downloading
Get both dynamic caching that works automatically as the user browses the map, and bulk downloading to preload regions onto the user's device, all in one convenient package!
◉ 🏃
Ultra-fast & Performant
No need to bore your users to death anymore! Bulk downloading is super-fast, and can even reach speeds of over 600 tiles per second. Existing cached tiles can be displayed on the map almost instantly. Don't even mention memory consumption: you won't realise there is any.
Multi-threaded downloads
Tile buffering to reduce database writes
Streamlined behind-the-scenes to reduce memory consumption
◉ 🧩
Import & Export
◉ 💖
Quick To Implement (& Quicker To Love)
Once you can access FlutterMapTileCaching.instance
after Initialisation, chaining of methods and accessors is used to access functionality.
Base Chains are used as an intermediate step to access functionality on Roots and Stores
Additional Chains are added to Base Chains to reach the actual functionality.
To get the Root, chain on rootDirectory
(the name of the accessor is a remnant leftover from previous versions).
To get a Store, there are two possible methods. FMTC does not use code generation, so store names are flexible, and so use String
s to access the Store.
This is the recommended method. Always use this method where possible.
call()
/()
gets a StoreDirectory
by the name inside the parentheses.
Note that the store will not be automatically created once accessed, as this requires asynchronous tasks, so it is important to create the store manually (if necessary).
This method is not recommended, for the reasons listed below. Prefer using Without Automatic Creation wherever possible.
It is synchronous and therefore blocks the main thread
It results in hard to trace code, as the creation calls are no longer obvious
It encourages minimizing accesses to increase performance, which is against the philosophy of the chaining strategy
[]
gets a StoreDirectory
by the name inside the parenthesis.
Note that the store will be automatically created once accessed, although it will be done synchronously in a way that blocks the main thread.
After this, you can chain any of the following members/accessors (each will be accessible on a Root, a Store, or both).
Prefer using asynchronous versions of sub-methods where possible, as these won't block the UI thread.
If running inside an isolate, or blocking the UI thread doesn't matter, use the synchronous versions wherever possible, as they have slightly better performance.
Applies to Roots & Stores
FMTC is licensed under GPL-v3.
If you're developing a proprietary (non open-source) application, this affects you and your application's legal right to distribution. For more information, please see (Proprietary) Licensing.
Before using FMTC, ensure you comply with the appropriate rules and ToS set by your tile server. Failure to do so may lead to a permenant ban, or any other punishment.
This library and/or the creator(s) are not responsible for any violations you make using this package.
The main basis of this package is the FlutterMapTileCaching
object, which exposes the majority of FMTC's APIs (through FMTC.instance
), and also contains most of the state needed to connect and communicate with the underlying systems.
Therefore, it must be asynchronously initialised on every app startup, usually in the main
method that runs directly after the Flutter environment starts.
FMTC
is a shorthand type alias for FlutterMapTileCaching
, and works in exactly the same way. Often, documentation will use the shortened version to save space, and you should do so in your code as well.
You must call initialise()
before trying to use instance.
Failure to do so will throw a StateError
.
In this case, it is currently impossible to avoid a fatal crash during initialisation, as the database reader/parser crashes all Dart threads & isolates without warning. Please see this issue I opened:
However, FMTC has a workaround.
By using a basic temporary text file, the IDs/filenames of successfully opened databases can be recorded. Once all databases have been opened, the file is deleted, meaning that the safety system will not intervene on the next app launch. However, if a database open attempt crashes the app, the file will not be deleted, and it will contain the list of safe databases.
Because the order in which databases are opened is determinate (alphabetical), the app can open every database one by one, (metaphorically) crossing it off the list. When there are no more safe databases, but more database files, the next database is deleted instead of being opened. The initialisation then continues as normal, still using the file appropriatley.
Therefore, one fatal crash is enough to detect one faulty database, and delete it, allowing the app to initialise normally on the next launch.
If there are multiple corrupted databases (n
), one fatal crash is needed per database, so the app will successfully open after n + 1
.
All of this means that FMTC can usually recover from a database corruption with minimal data loss. However, if the database filenames/IDs are also changed, the behaviour is unspecified, especially if the initialisation file already exists.
Creating regions is designed to be easy for the user and you (the developer).
All regions (before conversion to DownloadableRegion
) implement BaseRegion
.
All BaseRegions
can be drawn on a map with minimal effort from you or the user, using toDrawable()
.
Internally, this uses the toOutline(s)
method to generate the points forming the Polygon
, then it places this/these polygons into a PolygonLayer
.
Applies to Roots & Stores
Applies only to Stores
This library provides a very simple persistent key-value pair storage system, designed to store any custom information about the store. These are stored alongside tiles in the tile database.
For example, your application may use one store per urlTemplate
, in which case, the URL can be stored in the metadata.
Both asynchronous and synchronous versions of the below methods are available.
Add a new key-value pair to the store. For example:
Read all the key-value pairs from the store, and return them in a Map<String, String>
. For example:
Remove a key-value pair from the store. For example:
Remove all the key-value pairs from the store. For example:
Settings change the functionality of FMTC throughout a project, and can be useful to setup customizations that are needed across multiple calls.
This package provides the ability to download areas of maps, known as 'regions' throughout this documentation. There are built in region shapes that even large apps, such as Google Maps, don't have!
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).
Before using FMTC, ensure you comply with the appropriate rules and ToS set by your tile server. Failure to do so may lead to a permenant ban, or any other punishment.
This library and/or the creator(s) are not responsible for any violations you make using this package.
All APIs listed in this section are children of the download
getter.
The recovery system is designed to support bulk downloading, and provide some form of recovery if the download fails unexpectedly - this might happen if the app crashes, for example.
Read more about the recovery system here:
Stores also have the method getTileProvider()
. This is the point of integration with flutter_map, providing browse caching through a custom image provider, and can be used as so:
FMTCTileProviderSettings
can take the following arguments:
This enumerable contains 3 values, which are used to dictate which logic should be used to store and retrieve tiles from the store.
If you've got a value (such as a token or a key) in the URL's query parameters (the key-value pairs list found after the '?') that you need to keep secret or that changes frequently, make use of obscuredQueryParams
.
Pass it the list of query keys who's values need to be removed/omitted/obscured in storage. For example, 'api_key' would remove the 'api_key', and any other characters until the next key-value pair, or the end of the URL, as seen below:
Using one of our , allow your users to share and backup their cached tiles! You could even remote control your organization's devices, by pushing tiles to them, keeping your tile requests (& costs) low!
A basic caching implementation can be setup in four quick steps, and shouldn't even take 5 minutes to set-up. Check out our instructions.
When you've done this, you'll realise how great your app is with FMTC
FMTC uses Roots and Stores to structure it's data. Previously, these represented actual directories (hence the reference to directories within the codebase), but now they just represent databases.
There is usually only one root (formed of a directory and some miscellaneous databases) per application, which contains multiple stores (formed of a single database holding a descriptor, multiple tiles, and ).
Install
OpenStreetMap's can be : specifically bulk downloading is discouraged, and forbidden after zoom level 13. Other servers may have different terms.
Whilst it is (almost) impossible for one of the underlying databases to become corrupted during normal usage, or even due to a bug, it can happen if the database file is modified manually.
The contains a great way you might want to allow your users to choose a region to download, and it shows how to use Provider to share a created region and the number of approximate tiles it has to a download screen.
The most basic type of region, defined by two North West and South East coordinates that create a LatLngBounds
.
A more advanced type of region, defined by a center coordinate and radius (in kilometers).
If you have two coordinates, one center, and one on the edge of the circle you want, you can use method, as below:
The most advanced type of region, defined by a list of coordinates and radius (in meters).
After you've created your region, you can convert it to a drawable polygon (below), or ready for downloading.
For example, a project with multiple calls can configure the here, to reduce duplication and improve maintainability.
After downloading, tiles are stored in the same place as when Browse Caching, meaning that no extra setup is needed to use them in a map (other than the usual ).
OpenStreetMap's can be : specifically bulk downloading is discouraged, and forbidden after zoom level 13. Other servers may have different terms.
Start downloading that region, either in the or
This method (and others) optionally take a FMTCTileProviderSettings
. These configure the behaviour of the tile provider. Defaults to the settings specified in the , or the package default (see table below) if that is not specified.
A backport of this functionality to v6 is also available - see , and install it through GitHub: .
manage
Control, modify, and configure an actual structure ('physical' directory or database) itself
stats
Retrieve statistics about a structure (Root or Store) itself
cacheFirst
Get tiles from the local cache if possible.
Only uses the Internet if it doesn't exist, or to update it if it has expired.
onlineFirst
Get tiles from the Internet if possible.
Updates every cached tile every time it is fetched (ignores expiry).
cacheOnly
Only get tiles from the local cache, and throw an error if not found.
Recommended for dedicated offline modes.
Available since v7
Without buffering, every tile is written directly to the database before continuing to the next one (within each simultaneous thread). This requires a write transaction for every tile, which are relatively slow. Without buffering, the database write speed is usually the limiting factor in the download speed.
To avoid this problem, buffering can be used. Tiles are written to an intermediate buffer before being written to the database, in bulk. This means a transaction is only needed for every bulk write operation, which can lead to huge speed improvements (>2x is possible). However, there are two major cons that you should consider before implementing this in your application:
Memory usage increases significantly When in use, the Memory usage graph within DevTools will likely look like a sawtooth wave. The peak memory usage may be too high for some devices, so you should consider your audience.
An app crash can lead to data loss Tiles in the buffer will be lost in the event of an app crash, meaning their download will have been wasted. Tiles that have been written previously will not be lost.
It may be appropriate to leave the decision up to each user individually. In this case, ensure you thoroughly explain these cons to the user, to allow them to make an informed decision. Alternatively, you might make a decision based on the platform. Desktop platforms are likely to have enough RAM capable of holding the buffer, whereas some older mobile devices may struggle.
Buffering is disabled by default, and can be enabled in the startForeground
method call (the property is not part of the DownloadableRegion
).
Buffering can be defined by one of two types of limit, shown below. Neither has a disadvantage in terms of performance, but memory allows finer grain control, at the expense of being less obvious to the user.
Memory (buffer bytes size)
Tiles (buffer length)
Start a download in the foreground
Start a download in the background
Check the number of tiles in a certain region
Cancel any ongoing downloads
Determine the logic used during handling storage and retrieval of browse caching
CacheBehavior.cacheFirst
cachedValidDuration
: Duration
Length of time a tile remains valid, after which it must be fetched again (ignored in onlineFirst
mode)
const Duration(days: 16)
maxStoreLength
: int
Maximum number of tiles allowed in a cache store (deletes oldest tile)
0
: disabled
obscuredQueryParams
: List<String>
[]
: empty
fmtc_plus_background_downloading Module
Unfortunately, background downloading is available on Android only, due to the strict limitations imposed by iOS. This is unlikely to change in the future, especially as I am currently unable to develop for iOS.
In addition, there is no planned support for other platforms.
There is some confusion about the way background process handling works on Android, so let me clear it up for you: it is confusing.
Each vendor (eg. Samsung, Huawei, Motorola) has their own methods of handling background processes.
Some manage it by providing the bare minimum user-end management, resulting in process that drain battery because they can't be stopped easily; others manage it by altogether banning/strictly limiting background processes, resulting in weird problems and buggy apps; many manage it by some layer of control on top of Android's original controls, making things more confusing for everyone.
To try and help your users get to the right settings quicker, use the requestIgnoreBatteryOptimizations()
method before starting a background download. This will interrupt the app with either a dialog or a settings page where they can opt-in to reduced throttling. There is no guarantee that this will work, but it should help: this is not required and the background download will still try to run even if the user denies the permissions.
Internally, a foreground service is actually used. This allows the service to run as long as the app hasn't been force stopped.
The effectiveness of the Recovery system is reduced by background downloading.
If the user leaves the application, then the recovery system may report the ongoing background download as failed, as it has no way of knowing about it. If the user tries to retry the download, both downloads may then fail, and the recovery system may fail also.
There is no way of resolving this situation. You may prefer to disable recovery on background downloads.
Unlike foreground downloading, where you can Listen For Progress, background downloading does not provide any way to do this, so it is much less customisable.
The download progress notification only displays the percentage progress and number of tiles attempted/max number of tiles (see #available-statistics).
Buffering is not supported by background downloads.
Before using FMTC, ensure you comply with the appropriate rules and ToS set by your tile server. Failure to do so may lead to a permenant ban, or any other punishment.
This library and/or the creator(s) are not responsible for any violations you make using this package.
These contain the original BaseRegion
, but also some other information necessary for downloading, such as zoom levels and URL templates.
See this basic example:
By not storing pure tiles of sea, we can save a bunch of space on the user's device with every download. But how to do this?
Well, this package does it by analysing the bytes of the tile and checking if it's identical to a sample taken at lat/lng 0, 0 (Null Island) with zoom level 17. This tile should always be sea, and therefore any matching tile must also be sea.
In this way, we can delete tiles after we've checked them, if they are indeed sea. This method also means that tiles with ferry paths and other markings remain safe.
Before downloading the region, you can count the number of tiles it will attempt to download. This is done by the check()
method.
The method takes the DownloadableRegion
generated above, and will return an int
number of tiles.
fmtc_plus_background_downloading Module
Note this functionality is only available on Android.
See the fmtc_plus_background_downloading Installation & Setup instructions to add this module.
Before using FMTC, ensure you comply with the appropriate rules and ToS set by your tile server. Failure to do so may lead to a permenant ban, or any other punishment.
This library and/or the creator(s) are not responsible for any violations you make using this package.
This is designed to stop the app from terminating when it is taken off the widget tree, such as when the user closes the application. It is safe to leave there even when not downloading: it is intelligent enough to only keep the application alive if there is an ongoing background download.
Before using FMTC, ensure you comply with the appropriate rules and ToS set by your tile server. Failure to do so may lead to a permenant ban, or any other punishment.
This library and/or the creator(s) are not responsible for any violations you make using this package.
To start downloading tiles, you must Listen For Progress, even if you do not plan to use the #available-statistics.
fmtc_plus_sharing Module
To listen for progress events, you can listen to the Stream
of DownloadProgress
events returned by the startForeground()
method, which contains useful statistics about the download.
Listening can be done through any method, such as listen()
or the await for
loop.
v7 documentation is no longer available.
This page highlights the biggest changes made that will affect the most users - feature additions are not included. Smaller changes are described by in-code documentation or should be self explanatory.
Don't forget to add and configure the migrator method (StoreManagement.migrator
) before publishing your app.
Due to the change in the underlying storage system, initialisation has changed to be asynchronous itself, meaning that the previous method of defining the rootDirectory
was now overly complicated. So the RootDirectory
system has also been simplified.
Some methods have been removed from store management due to limitations in Isar. The deprecation documentation in-code suggests replacements.
Changes have been made, which has improved cross-platform stability and performance. Some properties have changed: consult the documentation for more information. Migration should be self explanatory.
Validation options have been removed, as any store name (within UTF8) is now acceptable, because the limitations of the filesystem have been removed.
Some Isar database options have been added to manage the database files themselves. These have sensible defaults, although you should check them to make sure they fit your use-case.
persistedTiles
and persistedSize
now report the number of tiles and size that has actually been written to the database.
Handling collisions with existing stores during imports has gotten easier, with a built-in callback parameter.
These functionalities have been separated into their own modules, in order to simplify the installation of this package.
Methods and fields related to statistic caching have been removed, along with the underlying statistic cache system. This is because the new Isar databases are fast enough to calculate statistics, to the point where caching would likely result in reduced performance.
fmtc_plus_sharing Module
Attempting to import a damaged/corrupted store may result in a fatal app crash, or major errors at least.
withGUI
)File
(manual
)In the event that a store with the same name already exists as the store that is trying to be imported, FMTC has only simple conflict resolution behaviour.
When a collision is detected, the defined callback collisionHandler
is called asynchronously, with the filename of the import file in addition to the real name of the contained store. It can return either:
true
: Override the entire existing store and its contents
false
: Skip/cancel the import
recovery
Recover failed bulk downloads, and prepare them to restart
import
Import and prepare a store from a previously exported archive file
download
Prepare, start, and manage a store's bulk downloads
metadata
A simple key-value pair store designed for storing simple, store related information
export
Export a store to an archive file, for future importing
behavior
:
See
Therefore there is no guaranteed behaviour when using this functionality. You can see how many vendors will treat background processes here: ; you may wish to link your users to this site so they can properly configure your app to run in the background.
OpenStreetMap's can be : specifically bulk downloading is discouraged, and forbidden after zoom level 13. Other servers may have different terms.
must be converted to
DownloadableRegions
before they can be used to download tiles.
The module is required to use the background bulk downloading functionality.
You should read about the before you start using it.
OpenStreetMap's can be : specifically bulk downloading is discouraged, and forbidden after zoom level 13. Other servers may have different terms.
You should also wrap your application's root widget (such as a Scaffold
) with the widget.
OpenStreetMap's can be : specifically bulk downloading is discouraged, and forbidden after zoom level 13. Other servers may have different terms.
Exporting a store copies the internal store database, 'compresses' it slightly, then renames it appropriately. The files are in the binary format that uses, so they cannot easily be read or modified.
v7 was due to a package upgrading its version without following semantic versioning, meaning that the pub package resolver could never successfully resolve a working v7 package.
v8 contains all functionality from v7. Therefore, follow these migrations, then the instructions to upgrade to v8 (retaining the StoreManagement.migrator
) method.
v6 and v7 have significantly different underlying storage systems, and therefore different APIs. Pre-v6 uses a multi-directory filesystem-based structure, whereas v7 uses a multi-database structure based on .
With the introduction of for bulk downloading, there are now two additional statistics. The existing statistics successfulTiles
and successfulSize
will remain work, but with altered functionality: they now report the number of downloaded, not-necessarily persisted (still in buffer), tiles and size respectivley.
To add this functionality again, see and .
If you don't use this functionality in your app, you can undo the instructions related to these modules.
It is possible to re-import a store generated by an .
See for more information about how this may be handled in future.
If you need to stop a bulk download early, you can use the cancel()
method to safely exit. No more tiles will be downloaded, and any tiles still within the buffer (see Buffering) will be written.
fmtc_plus_sharing Module
See the fmtc_plus_sharing Installation & Setup instructions to add this module.
Note that some tile servers, such as Mapbox, forbid the sharing of their cached tiles, but this should still be acceptable as long as a user only imports their own exports (for example, backup purposes).
For example, they can be used to create backup systems, sharing systems, or to distribute a preset package of tiles to all users without worrying about managing IO or managing assets!
v8 brings major performance & stability improvements, along with support for Isar v3.1 and 'flutter_map' v4.
Some migrations are necessary for a small number of users. These migrations are listed below, theoretically in decreasing number of affected users.
The underlying storage structure is directly compatible with v7, and so migration for that is not required.
Return type is now ImportResult
This contains both the real store name (may be different to the filename) and whether the import was successful.
Collision handlers are now called with an additional argument The filename and real store name are now both passed to the collision handler. See Collision/Conflict Resolution.
FMTCInitialisationException
's fields have changed to be more useful in debugging initialisation issues, both internally and externally. If processing these issues manually, you'll need to migrate. See the in-code documentation for more information.
HttpClient
UsageIn many of the places where HttpClient
s where previously accepted as arguments, BaseClient
subtypes are now required. To continue using a custom HttpClient
, wrap it with an IOClient
.
Where issues originate in FMTC, I try my hardest to fix them quickly where possible, or provide workarounds if necessary.
Some problems will take longer than others to fix, so please be patient. If you think you can fix the issue, please get in touch and/or create a PR - contributions are always welcome!
FMTC is currently somewhat unstable for applications with a wide public reach, due to some issues with the Isar dependency.
These issues are being worked on behind the scenes, but unfortunately, there is no planned release date for the v4, which is planned to include these fixes.
FMTC should behave correctly on the majority of devices, but it can cause fatal app crashes on some devices. v8 is much more stable than v7, as it depends on Isar 3.1.0.
This project is currently maintained by JaffaKetchup (Luka S). I am currently a maintainer of flutter_map, but this project has no other internal links.
Thanks to all contributors, and 'bugDim88' who originally came up with the idea and created a PR for flutter_map. When that PR was closed (it was decided a plugin would be more suitable), I took over the project. Also thanks to all of the 3rd party dependencies and their maintainers.
Many thanks to all my sponsors, not matter how much or how little they donated (in no particular order):
+ 3 anonymous or private donors
3rd party cookies are in use by default, for the purpose of internally tracking visits to this site. We use Google Analytics and GitBook's own built-in analytics to perform this. Data collected is kept confidential to the author of this site, and is only used for improvement/insight purposes.
The Google Analytics property in use is not connected to any Ad tracking/provider any more than by default. No ads are shown on this site.
Please get in touch if you have more questions!
The module is required to use the import/export functionality.
It is possible to an entire store (including tiles and metadata) to a standalone file that can be easily shared and distributed between devices, then on any device.
The module is required to use the import/export functionality.
FMTC now supports HTTP/2, through ! HTTP/2 support is enabled by default, with a fallback to HTTP/1.1 (both with a timeout of 5 seconds).
Where they don't originate directly in FMTC, I consider donating or creating a bounty to get the bug resolved, if I can't help fix it myself. This money can only come from and payments to FMTC.
If you're significantly concerned about stability, consider using the '' branch instead of v8. v6 has significantly worse performance, and has some other major downsides, but is likely to be more stable across more platforms. The v6 is still available.
migrator
Migrate the incompatible file/directory structure of a previous version