Using multiple Map Providers
It is possible to use MapsIndoors with multiple map providers, from this point we will call them platforms, like Mapbox and Google Maps, in the same app. The basics of this approach is to create a generic interface for accessing the maps, as well as provide some utility in setting up MapsIndoors.
In this article we will: Install multiple platforms, create a Map interface, create a Fragment interface to hold the MapViews, create implementations of the Map interface for each platform, and then blend them together in a single app.
We will use Google Maps and Mapbox as examples.
Build gradle
First we have to add both platforms to our build file, it is important that both versions of MapsIndoors use the same version, otherwise we might experience issue with the interface.
ext {
mapsindoors = "4.12.1"
google_maps = "18.1.0"
mapbox = "11.11.0"
}
dependencies {
implementation "com.mapspeople.mapsindoors:mapbox-v11:$mapsindoors"
implementation "com.mapspeople.mapsindoors:googlemaps:$mapsindoors"
implementation "com.mapbox.maps:android:$mapbox"
implementation "com.google.android.gms:play-services-maps:$google_maps"
// MapsIndoors and Mapbox repos
repositories {
maven {
url 'https://maven.mapsindoors.com/'
}
maven {
url 'https://api.mapbox.com/downloads/v2/releases/maven'
authentication {
basic(BasicAuthentication)
}
credentials {
// Do not change the username below.
// This should always be `mapbox` (not your username).
username = "mapbox"
// Use the secret token you stored in gradle.properties as the password
password = project.properties['MAPBOX_DOWNLOADS_TOKEN'] ?: ""
}
}
}
}Map Interface
The map interface should be as lean as possible, only containing the methods you need to use on the maps, in this example we have added 3 methods for moving the camera, as well the ability to read the current position, projection as well as turning the compass on/off.
This interface can be extended or shrunk to your hearts content, but remember that each method added will have to be implemented on both platforms.
MapFragment Class
The MapFragment is a container for the platforms' MapViews, it should be able to tell when the MapView is ready for content, be able to create a Map instance for us, and create the start of a MPMapConfig which ensure the app can remain ignorant of the platform implementations.
First we create the interface we should follow, it should implement the Fragment class so that we can manage it like a fragment.
Interface
Map Fragment
Then we create the platform implementations, but lets just leave actual implementations blank for now, and focus on creating the Map implementation.
For Google Maps we also implement the OnMapCallback to get a callback when the map is ready for use.
Go here to see how the fragment layout is made.
Go here to see how the fragment layout is made.
Map implementation
We create the Map implementation as a internal class in the MapFragment, this helps encapsulate it, as well as keeping all the platform implementation in a single file.
Init and isReady
Lets go back to the MapFragment, and begin filling out the methods:
On Google Maps we use the onMapReady method to get a GoogleMap instance after we call getMapAsync on our MapView, we then wrap the GoogleMap in our Map implementation MIGoogleMap, and inform the app via isReady that the MapView is ready.
On Mapbox we load up the MapView and get the MapboxMap from it, which we then wrap in our Map implementation MIMapboxMap, once that is done we update the isReady field and trigger the isReady listener to inform the app that the MapView is ready.
MapConfigBuilder
The MapConfigBuilder is quite straigthforward, but it needs to be implemented in the Fragment to keep the app completely platform independant.
To create a MPMapConfig we usually need the Activity, the platform Map, a platform secret key, and the MapView.
Final class
This is how our MapFragment with MIMap is going to look like:
Views
Main Activity view
The MainAcitivty only needs a single FragmentContainerView, which in this case fills the entire parent.
The actual fragments contains a Mapview inside a FrameLayout.
Secrets
Your platform keys should be kept safely in your resources where they can be fetched during runtime.
Use in App
Now we have everything we need to set up the App. Here the approach is quite straightforward, we have made a method buildConfig which takes the name of a platform, an MapsIndoors API key, and an error listener, and builds the appropriate MapFragment, and loads MapsIndoors as well.
When the fragment is ready, we call initMapControl which starts building a MapControl using the fragments' MPMapConfig, which we can extend in this example to also enable blue dot positioning.
Once MapControl has been create we use it to get the default venue, then use our animateCamera method to move the camera to the venue bounds.
If we call buildConfig again, but with a different platform, we will reload the solution, and use the other platform, all without making a new app!
We can even move the MapsIndoors.load() out of the buildConfig method, and switch platform without reloading the solution.
Final words
We now know how to create an interface for using multiple platforms in the same app for MapsIndoors.
Last updated
Was this helpful?