How to add a link to a maps application in your Cordova app

Devops

Cordova

Android

Edit: The example shown here is for the Android platform. For iOS, use themaps:// uri.

TL;DR: Instead of adding a map to your app, use a geo URI. To do so, you need to whitelist to external map apps (whitelist) and sanitize your anchor href using angular ( aHrefSanitizationWhitelist ).

If you're a hands on person, feel free to try the ionic tutorial on the bottom first and then come back. If you're more of a documentation person, check the links in the TL;DR:.

Why use geo URI instead of maps

Sometimes you just need to add a map to your app. Sometimes you might even need to do so offline. But other times, you just need something fast, something that you can implement in less than 30 minutes and that will work great. For that, you can provide your users with the option of opening the geolocation coordinates in the app of their choosing. In fact sometimes that is not only easier to implement, exactly what you need.
Here are some scenarios where you might want to use geo URIs instead of a map API:

  • you don't have the screen realstate to add a map
  • adding a map will harm the user experience
  • the feature you want to add relies on the user being able to get the directions in their own app

One real life example were I recently used this was in an app were the user could find a nearby bar and then open it in his map application to get directions. This way, the user can use the maps interface that he is used to, share the location with friends, etc.

Now, how do we actually use geo URIs?

Ionic tutorial

Supposing you have already installed ionic and all, start a new project (why not name it geo?) and add Android to your platform list:

ionic start geo blank && cd geo
ionic platform add android

Now we need some data to use in our tutorial. For that add a controller with your favorite location(s):

angular.module('starter').controller('locationsController',function($scope){
  $scope.locations = 
[
{
  label: 'BAM',
  latitude: 48.882916,
  longitude: 2.322315
},
{
  label: 'Tour Eiffel',
  latitude: 48.858370,
  longitude: 2.294550
},
{
  label: 'Le Café des Chats',
  latitude: 48.862846,
  longitude: 2.356235
}
  ];
});

And we show them using a list and some ngRepeat magic. Each list item will contain the name of our location, and a geo: uri to its position. For that, add our controller to the ion-content (ng-controller="locationsController") and add the following code between the ion-content tags.

    <ul class="list">
      <li class="item" ng-repeat="location in locations">
        <a 
        ng-href="geo:,?q=,()" 
        ng-click="$event.stopPropagation()"
        target="_blank">
          
        </a>
      </li>
    </ul>

This will show our list, but our href will not work just quite yet. In order to make them work, we need to whitelist the geo locations for external apps and sanitize the geo uris.
To whitelist external maps' apps, open your config.xml file. There, you will find and you should add:

<access origin="geo:*" launch-external="yes"/>

Right after it.
To sanitize your geo uris, you can use angular's $compileProvider. To do so, add:

angular.module('starter')
.config(function($compileProvider ){
  $compileProvider.aHrefSanitizationWhitelist(/^\s*(geo):/);
}); 

Note: When sanitizing, remember that only one string is used for sanitization, so if you want to sanitize tel and geo, you don't add that line twice with tel and geo, but rather once for the string /^\s*(geo|tel):/.

Now just go ahead and test your app, using cordova run.

ionic run android

Final thoughts

If you made it this far, I might aswell give you a few extra details about the geo query.

geo:<reference.latitude>,<reference.longitude>?q=<destination.latitude>,<destination.longitude>(label)

The first coordinates are a reference for the application to base itself before a query. Setting them to 0,0 works fine. The coordinates that come after are the actual destination coordinates. They are the coordinates that are used for the query (?q=). The query doesn't have to be with actual latitude and longitude. You can use a street addres, for example:

geo:0,0?q=my+street+address

Here it's where the reference latitude and longitude might help in your query. For example:

geo:0,0?q=Fnac

Will give you different results from:

geo:48.865347,2.348276?q=Fnac

Last thing, the label is... well, a label. You can add any label you want to your query and it will show up in the coordinates you specify. For example, Eiffel Tower is nice, but Candy Mountain is equally nice, so you could make your href as follows:

<li class="item">
   <a href="geo:48.858370,2.294550?q=48.858370,2.294550(Candy Mountain)">Candy Mountain</a>
</li>

And now when your map opens up, you will find that Candy Mountain is exactly where the Eiffel Tower used to be. Now that you know your way to the Candy Mountain, you can finally go to the Candy Mountain, Eiffel Tower, Candy Cave Charlie.