Choosing the right Map Integration for your Cordova App
While developing a mobile app, you may find yourself in a position where you need to integrate a map into it. Choosing the right solution can not only enhance the user experience but also provides extra perks like revenue increase, product image improvement etc., depending on the target audience and the app scope.
There are many factors to consider for the best solution. For example:
- Private/Open Source: while maps provided by private services, like Google Maps, may provide a good accuracy and details, but at the same time they may lack the customization that Open Source maps, like OpenStreetMap, provide (advanced toponymy modifications for example).
- Performance: each map may provide different optimization and APIs for specific OS and devices. That’s why it’s a good idea to always have in mind the target audience, use cases and integration plan.
- Pricing: while most services provide some free quota, you’ll likely need to switch to a paid plan when the app generates high traffic or needs to integrate advanced functionalities. It is definitely advisable to think about the usage expectation prior to choosing a map service.
- Features: while everybody’s got the basic features, the most advanced ones may only be provided by some of them.
- Updates: as the world topography is in constant evolution, maps need to adapt accordingly. Plus, they are not the only part that requires updates. Choosing a service that also provides a good support to new mobile and mapping technologies, like the recently introduced Galileo global navigation satellite system, may be a wise choice.
To compare these two approaches, I pick both private and open source solutions, and mainly focus on the performance rather than the features, as they may be very subjective. For the private maps service, the choice clearly went to Google Maps, while for the Open Source one I tried to find a successful service based on OpenStreetMap. After taking a look at a dozen of services, I decided to try Mapbox GL, which provides great features and uses WebGL to render interactive maps from Vector Tiles and customizable styles. Nevertheless, keep in mind that there are dozens of great services out there, so you may want to research a little bit more on your own after reading this article.
To develop the sample app, I used Monaca because it offers an immediate feedback during the development through its Live Debugger. (Full disclosure: I’m one of the developers at Monaca :-). Nevertheless, feel free to use any service you like or the standard Cordova SDK if you feel more comfortable doing so. You can find this sample app in this GitHub repository or import it directly into Monaca by clicking the image below.
If you just want to check it out, just perform the initial configuration as follows a little bit below and you are ready to go!
Generally, I expect the Cordova Plugin implementation to be smoother and more performant, rendering the map faster than the pure JS approach and making use of all the features available in the native SDK. On the other hand, I expect the JS API solution to be easier to implement and maintain, and also work flawlessly on mobile devices as well as on web browsers.
First of all, to be able to use both services you need to have an API key for each one. While Mapbox requires just one key, Google Maps distinguishes between JS API key and Mobile API Key. The latter one is not actually just a single key, but one key per platform. This means that if you want to run the plugin in both iOS and Android you need to generate an API for each platform. The instructions can be found in the plugin’s documentation or on the related service website. I found that the Mapbox configuration is a lot more immediate and intuitive, while the Google Maps ‘getting started’ is a bit tedious, making it easy to get lost in the documentation.
At this point, if you want to follow the procedure I performed by using Monaca, keep reading this section, otherwise take a look at the official documentation once again in order to understand how to import the API keys in your sample app and jump to the next section.
Open Monaca Dashboard and create a new Onsen UI V2 JS Tabbar template, go to
config -> Manage Cordova Plugins and import the two previously downloaded plugins. Once done, click
Configure in each of them and add the previously generated API keys as follows:
ACCESS_TOKEN=xxxxxxxfor the Mapbox plugin.
API_KEY_FOR_IOS=xxxxxxxfor Google Maps. Note that only target platform API key is required. For example, if you just want to build for Android you don’t need to add the iOS API key.
Now you can create a Custom Debugger which includes the two Plugins and allows you to check your app development result in real-time. For example, if you want to build the Android Custom Debugger, go to
Build -> Build App for Android and select
Custom Debugger . Once built, you just need to install it on your device and you are ready to live debug your code, fetching the new changes each time a save operation has been performed.
Sample App Development
All the initial setup has been performed and we are ready to start developing the sample app. While the Cordova Plugins API keys have already been setup, the JS API keys need to be specified in the code itself. Open
www/index.html and add the following content:
<link href='https://api.tiles.mapbox.com/mapbox-gl-js/v0.41.0/mapbox-gl.css' rel='stylesheet' />
<script async defer src="https://maps.googleapis.com/maps/api/js?key=YOUR_GOOGLE_MAPS_KEY&callback=initGoogleMapsJS">
// Provide your access token
L.mapbox.accessToken = 'YOUR_MAPBOX_KEY';
Now the app has completely been configured and we can start adding the maps to the app. I chose the Onsen UI Tab Bar template because my idea was to render each map in a separate tab, making it easier to switch between and test the performance. Unfortunately, here I encountered the first main issue. It looks like the Cordova Plugin for Mapbox does not support the map rendering into a specific container, as reported in this GitHub issue. This is a real deal breaker as it greatly limits the map integration into the app as it does not allow an easy navigation. For this reason, I decided to drop it and continue the test with the remaining three alternatives.
The Cordova Google Maps plugin integration was quite easy to perform, with one exception. Because the generated map is a native view, and not an HTML element, it’s being added under the HTML content itself. This means that the view in which you are planning to display the map should have a transparent background in order to be able to see the map content. Onsen UI, and probably other UI frameworks as well, don’t always have a white background so it is good to keep in mind that a CSS modification may be required. Except for that, I haven’t encountered any other issue during the implementation.
The two JS map integrations were even smoother. I just had to define the container where I wanted to display the map and specify it during the map initialization.
At this point, all I wanted to do was to check the map performance and user experience. All three implementations took approximately the same time to render the map once the app has been opened. While switching between the two JS implementation, the transition appears to be very smooth and linear. The Cordova plugin implementation generates a small flickering once its container is being displayed, not something that could greatly compromise the general user experience however. The map navigation to a new location feels smoother on the Cordova plugin implementation as it seems that being able to use the native OS SDK allows the map to be always pre-rendered, while the information are being fetched progressively. The touch actions appear to be very responsive in the two JS API implementations, while the Cordova plugin map seems sometimes missing some gestures recognition, pinch-to-zoom specifically.
From what I could notice, neither solution had an automatic cache management, which would surely be useful to reduce the loading time if the app is being frequently opened and closed. It is still possible to implement the cache manually for the Vector Tiles, which is available only in Google Maps Cordova and Mapbox GL JS API. Moreover, both these implementations offer animations support while the Google Maps JS API does not. For example, a specific point on the map could be zoomed in/out progressively at the specified speed. I played a little bit with this feature, as it looked like a good way to (partially) test the smoothness of the map rendering. By implementing two zoom in/out features, I noticed that both Google Maps Cordova and Mapbox GL JS API were handling the task very well, providing a nice effect while rendering.
After trying various solutions, I feel that no one is strictly superior to the other. All have their peculiarities and all provide the basic features needed by the most developers. Nevertheless, there are some points that need to be considered very carefully.
First of all, choosing between a JS API or a native SDK (accessible through Cordova plugin) may produce very different results. While the JS API offers more compatibility, easy integration and maintainability, it may lack in performance and integration with the mobile device hardware and services. On the other hand, a Cordova Plugin integration may provide great performance by taking advantage of the hardware and OS integration but that’s not always guaranteed and may have very different results depending by the OS or the hardware in which it runs and the developer’s implementation.
Another big thing to consider is if the solution has been made available directly by the service provider or by a third party. For example, neither Mapbox and Google Maps provide an official Cordova plugin. While the tested Google Maps plugin seems to be well implemented, it may be hard to constantly keep it up to date with all the official features and offer compatibility with the new native SDKs. At the moment, going for the JS APIs seems to be the safer way to have continuous support and updates, along with good performance.
The way the Tiles are implemented is also something that should be carefully considered. If an advanced personalization is required, Vector Tiles are surely the way to go as they offer great customization and features, like caching, scaling and 3D views. The classic Image Tiles are more than fine in the case where the map does not need to be heavily customized and the necessary information is already integrated.
Personally, I liked the Mapbox GL service for its potential and performance, but I definitely did not dislike the two Google Maps alternatives, which are still more than enough for most use cases and offer a complete integration with a huge set of points of interest mapped by Google itself.