Using Mapbox in Your Flutter Project
By: Peter Aleksander Bizjak
Tags: Android, Flutter, iOS, Mapbox, Software Development

Mapping providers targeting mobile platforms need to establish a frictionless experience that is fast and responsive. For years, the pioneer in the field has been Google with its Maps service, used globally by millions of people. Their APIs are state-of-the-art, and it shows; everywhere, from the way developers manage their services through Google Developers Console to the excellent documentation and multi-platform support. You would expect nothing but the best from a company like that.

Apple, of course, has its service as well, which is equally capable and well-optimized for their devices.

However, the mapping game becomes a pretty barren outside of Google and Apple, largely because the service itself requires substantial investment into building it grounds up; acquiring data via government departments of transportation and private data providers is not a joke when you’re planning on creating service available globally.

To put it in perspective, Mapbox, as a company, in their Series C funding got $164 million from SoftBank. All of that is necessary to build a highly performant mapping service (SDKs and APIs) used by thousands of developers. They succeeded big time, and are regarded today as one of the best mapping providers in the world, with their services used by companies like Facebook, Snapchat, CNN, etc.

Mappy: The Mapbox Demo Project

As a demo, I’ve created a simple mobile application called Mappy and even recorded my first YouTube tutorial explaining the use of Mapbox plugin in a Flutter app. With that being said, this article is a complement to the video and source code, offering a much more in-depth look into deliberations a developer needs to be aware of.

Mapbox gives you SDKs targeting native Android and iOS, but there are no official Flutter plugins. Your best bet is mapbox_gl, a community-driven project that has matured a lot, and is pretty decent. Of course, nothing beats the native SDKs, which are incredibly powerful, as the Flutter version comes with a few caveats.

Permissions

For starters, let’s discuss location services on mobile platforms. No, I will not be talking about special cases, like Android’s need to ask for location permissions to initialize a WiFi access points scan.

Google has incredible documentation dedicated both to requesting permissions in general, as well as a dedicated section to requesting location permissions. I strongly encourage you to read both. Since we’re developing cross-platform apps, read about requesting permissions on iOS as well.

Instead of worrying about correct implementations ourselves, we can use the location package.

MapboxMap Widget

To use Mapbox products, you require an access token. On Android, you’d typically rely on Gradle properties to store sensitive tokens, but please check the official documentation regardless.

For Flutter, this doesn’t help, as there is an accessToken property in the MapboxMap widget that accepts a plain text string. During development, you can create a configuration file and read the key from it, in production, you should keep the tokens on the backend side (if possible). Note for Firebase users: you might find it tempting to use Remote Config for that, but the answer is congruent no. If you wonder where this note comes from, read their policies and limits.

You can download the config variable remotely, and then store it into KeyChain/Keystore file, under iOS and Android respectively, during the initial configuration stage. There are a lot of articles available on that topic, so I will not go into details.

Assuming you’ve come to the point where you can read the access token from whichever source of truth, the initial configuration is extremely simple. Just create a MapboxMap widget, as a body to your Scaffold.

Displaying Initial and Current Location

Depending on the use case, you can choose an arbitrary initial location, and by calling the animateCamera method move the user to their current location. With the help of the aforementioned location plugin, you can do that inside the onMapCreated callback.

Personally, I went with displaying a circle denoting the user’s current location, you could display an image or a marker, but a simple circle seemed to be the easiest component.

One of the caveats when it comes to adding any asset on top of the map, whether this is a circle, a style, an image, is the geometry parameter, which is never defined as required, so it quickly slips as a silent exception, only caught when you refer back to your stack trace and discover something like this:

Unhandled Exception: PlatformException(error, geometry field is required, null, java.lang.RuntimeException: geometry field is required...

Keeping that in mind, it might save you some time debugging your app. The default style seems to fail as well, so a custom implementation of the icon is required.

Another relatively important caveat refers to animateCamera result, which is a boolean value true when the animation is completed (you need to await it). If you’re planning on drawing anything after the method has completed on iOS, read the note in the documentation which states that

Note: this currently always returns immediately with a value of null on iOS

You can simply wrap the whole code into if statement checking if the platform is iOS, in which case, you do not evaluate the animateCamera statement.

Adding Symbols

Adding symbols to the Mapbox map can either be achieved programmatically at runtime or via pre-populating your map style with some markers.

Here are the couple of caveats to look after:

You do not have an API for displaying all possible iconImage strings, so you need to use the Mapbox Studio to manually check for icon names

strings, so you need to use the Mapbox Studio to manually check for icon names The infamous geometry the field will cause you problems in case it’s not implemented

This is how you retrieve the string value for the iconImage

Closing Thoughts

When targeting native mobile platforms or web, Mapbox is an incredibly powerful provider that gets the job done with the minimum setup required. On Flutter, however, the issue stems from the community-driven development. Although they are doing a good job bringing Mapbox to Flutter using the native C++ implementation, some issues have to be fixed.

Once the basic caveats are fixed, the Flutter implementation becomes trivial and extremely powerful. Build the Mappy app that I’ve mentioned above yourselves, and check how smooth the interaction is!