Xamarin.Forms - Google Maps API

Introduction

This article demonstrates how to use Google Maps API in Xamarin.Forms application and how to make it possible to access the default Google Maps app by a cross-platform application. These features are not listed by default in Xamarin.Forms. So, we need to install a plug-in for this.
 
NuGet Package
 
Xamarin.Forms - search "Xamarin.Forms.Maps" by Xamarin
 
"Xamarin.Forms.Maps" plug-in details

This plug-in has three types of Map Views
  • MapsPageApp
    using default maps application on different mobile platforms
  •  MapsPage
    1. Hybrid
    2. Satellite
    3. Street (the default)
  •  Map Pins
    1. Generic
    2. Place
    3. SavedPin
    4. SearchResult

MapsPageApp

 
 
MapsPage
 
 
 
MapsPins
 
 
 
Let's start :)
 
Step 1

You can create a Xamarin.Forms app by going to File >> New >> Visual C# >> Cross Platform >> Cross Platform App (Xamarin.Forms or Xamarin.Native) and click OK.
 
(Project Name: XamGoogleMapApp)

 
 
Step 2

After the project creation, add the following NuGet Packages for your project.
  • Xamarin.Forms.Maps

For that, open Solution Explorer and select solution, right-click and select "Manage NuGet Packages for the Solution". In the popup window, select the following NuGet package by selecting your projects, then install it.

  • Xamarin.Forms.Maps


 Step 3

Open Solution Explorer >> XamGoogleMapApp(PCL) >> right click and select "Add", followed by select "New Item ". In the popup window, select Visual C# >> Class.
 
In this way, you can create a new class.Now, create a class named MapsPageApp.cs page and click open MapsPageApp.cs. Here is the code.
 
CS code
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Diagnostics;  
  4. using System.Text;  
  5. using Xamarin.Forms;  
  6. using Xamarin.Forms.Maps;  
  7.   
  8. namespace XamGoogleMapsApp  
  9. {  
  10.     public class MapsApi : ContentPage  
  11.     {  
  12.         Map map;  
  13.         public MapsApi()  
  14.         {  
  15.             map = new Map  
  16.             {  
  17.                  
  18.                 HeightRequest = 100,  
  19.                 WidthRequest = 960,  
  20.                 VerticalOptions = LayoutOptions.FillAndExpand  
  21.             };  
  22.   
  23.              
  24.             map.MoveToRegion(new MapSpan(new Position(0, 0), 360, 360));  
  25.   
  26.               
  27.             var slider = new Slider(1, 18, 1);  
  28.             slider.ValueChanged += (sender, e) => {  
  29.                 var zoomLevel = e.NewValue;  
  30.                 var latlongdegrees = 360 / (Math.Pow(2, zoomLevel));  
  31.                 Debug.WriteLine(zoomLevel + " -> " + latlongdegrees);  
  32.                 if (map.VisibleRegion != null)  
  33.                     map.MoveToRegion(new MapSpan(map.VisibleRegion.Center, latlongdegrees, latlongdegrees));  
  34.             };  
  35.   
  36.   
  37.             var street = new Button { Text = "Street" };  
  38.             var hybrid = new Button { Text = "Hybrid" };  
  39.             var satellite = new Button { Text = "Satellite" };  
  40.             street.Clicked += HandleClicked;  
  41.             hybrid.Clicked += HandleClicked;  
  42.             satellite.Clicked += HandleClicked;  
  43.             var segments = new StackLayout  
  44.             {  
  45.                 Spacing = 30,  
  46.                 HorizontalOptions = LayoutOptions.CenterAndExpand,  
  47.                 Orientation = StackOrientation.Horizontal,  
  48.                 Children = { street, hybrid, satellite }  
  49.             };  
  50.   
  51.   
  52.             var stack = new StackLayout { Spacing = 0 };  
  53.             stack.Children.Add(map);  
  54.             stack.Children.Add(slider);  
  55.             stack.Children.Add(segments);  
  56.             Content = stack;  
  57.   
  58.   
  59.             map.PropertyChanged += (sender, e) => {  
  60.                 Debug.WriteLine(e.PropertyName + " just changed!");  
  61.                 if (e.PropertyName == "VisibleRegion" && map.VisibleRegion != null)  
  62.                     CalculateBoundingCoordinates(map.VisibleRegion);  
  63.             };  
  64.   
  65.         }  
  66.         void HandleClicked(object sender, EventArgs e)  
  67.         {  
  68.             var b = sender as Button;  
  69.             switch (b.Text)  
  70.             {  
  71.                 case "Street":  
  72.                     map.MapType = MapType.Street;  
  73.                     break;  
  74.                 case "Hybrid":  
  75.                     map.MapType = MapType.Hybrid;  
  76.                     break;  
  77.                 case "Satellite":  
  78.                     map.MapType = MapType.Satellite;  
  79.                     break;  
  80.             }  
  81.         }  
  82.   
  83.   
  84.         static void CalculateBoundingCoordinates(MapSpan region)  
  85.         {  
  86.             var center = region.Center;  
  87.             var halfheightDegrees = region.LatitudeDegrees / 2;  
  88.             var halfwidthDegrees = region.LongitudeDegrees / 2;  
  89.   
  90.             var left = center.Longitude - halfwidthDegrees;  
  91.             var right = center.Longitude + halfwidthDegrees;  
  92.             var top = center.Latitude + halfheightDegrees;  
  93.             var bottom = center.Latitude - halfheightDegrees;  
  94.   
  95.             if (left < -180) left = 180 + (180 + left);  
  96.             if (right > 180) right = (right - 180) - 180;  
  97.   
  98.             Debug.WriteLine("Bounding box:");  
  99.             Debug.WriteLine("                    " + top);  
  100.             Debug.WriteLine("  " + left + "                " + right);  
  101.             Debug.WriteLine("                    " + bottom);  
  102.         }  
  103.     }  
  104. }   
 
 
Step 4

Similarly, create a new class named MapsPage.cs page. The code is given below.
 
CS code
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Text;  
  4. using Xamarin.Forms;  
  5.   
  6. namespace XamGoogleMapsApp  
  7. {  
  8.     public class MapsPage : ContentPage  
  9.     {  
  10.         public MapsPage()  
  11.         {  
  12.             var l = new Label  
  13.             {  
  14.                 Text = "These buttons leave the current app and open the built-in Maps app for the platform"  
  15.             };  
  16.   
  17.             var openLocation = new Button  
  18.             {  
  19.                 Text = "Open location using built-in Maps app"  
  20.             };  
  21.             openLocation.Clicked += (sender, e) => {  
  22.   
  23.                 if (Device.RuntimePlatform == Device.iOS)  
  24.                 {  
  25.                     Device.OpenUri(new Uri("http://maps.apple.com/?q=394+Pacific+Ave+San+Francisco+CA"));  
  26.                 }  
  27.                 else if (Device.RuntimePlatform == Device.Android)  
  28.                 {  
  29.                     Device.OpenUri(new Uri("geo:0,0?q=394+Pacific+Ave+San+Francisco+CA"));  
  30.   
  31.                 }  
  32.                 else if (Device.RuntimePlatform == Device.UWP )  
  33.                 {  
  34.                     Device.OpenUri(new Uri("bingmaps:?where=394 Pacific Ave San Francisco CA"));  
  35.                 }  
  36.             };  
  37.   
  38.             var openDirections = new Button  
  39.             {  
  40.                 Text = "Get directions using built-in Maps app"  
  41.             };  
  42.             openDirections.Clicked += (sender, e) => {  
  43.   
  44.                 if (Device.RuntimePlatform == Device.iOS)  
  45.                 {  
  46.                       
  47.                     Device.OpenUri(new Uri("http://maps.apple.com/?daddr=San+Francisco,+CA&saddr=cupertino"));  
  48.   
  49.                 }  
  50.                 else if (Device.RuntimePlatform == Device.Android)  
  51.                 {  
  52.                       
  53.                     Device.OpenUri(new Uri("http://maps.google.com/?daddr=San+Francisco,+CA&saddr=Mountain+View"));  
  54.   
  55.                 }  
  56.                 else if (Device.RuntimePlatform == Device.UWP)  
  57.                 {  
  58.                     Device.OpenUri(new Uri("bingmaps:?rtp=adr.394 Pacific Ave San Francisco CA~adr.One Microsoft Way Redmond WA 98052"));  
  59.                 }  
  60.             };  
  61.             Content = new StackLayout  
  62.             {  
  63.                 Padding = new Thickness(5, 20, 5, 0),  
  64.                 HorizontalOptions = LayoutOptions.Fill,  
  65.                 Children = {  
  66.                     l,  
  67.                     openLocation,  
  68.                     openDirections  
  69.                 }  
  70.             };  
  71.         }  
  72.     }  
  73. }   
 
 
Step 5

Create a new class named PinsPage.cs page. Here is the code for this page.
 
CS code
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Text;  
  4. using Xamarin.Forms;  
  5. using Xamarin.Forms.Maps;  
  6.   
  7. namespace XamGoogleMapsApp  
  8. {  
  9.     public class PinPage : ContentPage  
  10.     {  
  11.       Map map;  
  12.   
  13.         public PinPage()  
  14.         {  
  15.             map = new Map  
  16.             {  
  17.                 IsShowingUser = true,  
  18.                 HeightRequest = 100,  
  19.                 WidthRequest = 960,  
  20.                 VerticalOptions = LayoutOptions.FillAndExpand  
  21.             };  
  22.   
  23.             map.MoveToRegion(MapSpan.FromCenterAndRadius(  
  24.                 new Position(36.9628066, -122.0194722), Distance.FromMiles(3)));   
  25.             var position = new Position(36.9628066, -122.0194722);   
  26.             var pin = new Pin  
  27.             {  
  28.                 Type = PinType.Place,  
  29.                 Position = position,  
  30.                 Label = "Santa Cruz",  
  31.                 Address = "custom detail info"  
  32.             };  
  33.             map.Pins.Add(pin);  
  34.   
  35.   
  36.               
  37.             var morePins = new Button { Text = "Add more pins" };  
  38.             morePins.Clicked += (sender, e) => {  
  39.                 map.Pins.Add(new Pin  
  40.                 {  
  41.                     Position = new Position(36.9641949, -122.0177232),  
  42.                     Label = "Boardwalk"  
  43.                 });  
  44.                 map.Pins.Add(new Pin  
  45.                 {  
  46.                     Position = new Position(36.9571571, -122.0173544),  
  47.                     Label = "Wharf"  
  48.                 });  
  49.                 map.MoveToRegion(MapSpan.FromCenterAndRadius(  
  50.                     new Position(36.9628066, -122.0194722), Distance.FromMiles(1.5)));  
  51.   
  52.             };  
  53.             var reLocate = new Button { Text = "Re-center" };  
  54.             reLocate.Clicked += (sender, e) => {  
  55.                 map.MoveToRegion(MapSpan.FromCenterAndRadius(  
  56.                     new Position(36.9628066, -122.0194722), Distance.FromMiles(3)));  
  57.             };  
  58.             var buttons = new StackLayout  
  59.             {  
  60.                 Orientation = StackOrientation.Horizontal,  
  61.                 Children = {  
  62.                     morePins, reLocate  
  63.                 }  
  64.             };  
  65.   
  66.             Content = new StackLayout  
  67.             {  
  68.                 Spacing = 0,  
  69.                 Children = {  
  70.                     map,  
  71.                     buttons  
  72.                 }  
  73.             };  
  74.         }  
  75.     }  
  76. }   
 
 
Step 6

After the design view creation, open Solution Explorer >> XamGoogleMapsApp(PCL) >>App.xaml.cs and double-click to get its design view and copy and paste the below-given code.
 
CS code
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Text;  
  5.   
  6. using Xamarin.Forms;  
  7.   
  8. namespace XamGoogleMapsApp  
  9. {  
  10.     public partial class App : Application  
  11.     {  
  12.         public App ()  
  13.         {  
  14.             InitializeComponent();  
  15.   
  16.             MainPage = new TabbedPage()  
  17.             {  
  18.                 Children =  
  19.                 {  
  20.                     new MapsPage(),  
  21.                     new PinPage(),  
  22.                     new MapsApi()  
  23.   
  24.                 }  
  25.             };  
  26.   
  27.         }  
  28.   
  29.         protected override void OnStart ()  
  30.         {  
  31.             // Handle when your app starts  
  32.         }  
  33.   
  34.         protected override void OnSleep ()  
  35.         {  
  36.             // Handle when your app sleeps  
  37.         }  
  38.   
  39.         protected override void OnResume ()  
  40.         {  
  41.             // Handle when your app resumes  
  42.         }  
  43.     }  
  44. }   
 
 
Step 7

Now, we need to add permissions to each platform.
 
 Android Project 

Open Solution Explorer >>  right click on the Android Project and select Properties >> open AndroidManifest tab and tick the following.
  •  AccessCoarseLocation
  •  AccessFineLocation
  •  AccessLocationExtraCommands
  •  AccessMockLocation
  •  AccessNetworkState
  •  AccessWifiState
  •  Internet

 

Afterwards, you must generate an API key and add it to your Android project. Follow this instruction for generating the API key.
 
Open the browser, go to "develpoer.google.com", and click "Get Key" button. In the popup window, select "Create New projects", give the project name, and click "Next".

 
 
In the popup window, click copy the API key to clipboard.
 
 
 
After following these instructions, paste the API key in the AndroidManifest.xml file.
 
For that, open Solution Explorer >> XamGoogleMapsApp.Android >> Properties >> Click open AndroidManifest.xml.
 
XML code
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="com.companyname.XamGoogleMapsApp" android:installLocation="auto">  
  3.     <uses-sdk android:minSdkVersion="13" />  
  4.     <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />  
  5.     <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />  
  6.     <uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />  
  7.     <uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION" />  
  8.     <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />  
  9.     <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />  
  10.     <uses-permission android:name="android.permission.INTERNET" />  
  11.     <application android:label="XamGoogleMapsApp.Android">  
  12.     <meta-data android:name="com.google.android.geo.API_KEY"  
  13.                android:value="AIzaSyDjd3wposlRaz0VoubNOIul-cI29qqR1hs"></meta-data>  
  14.   </application>  
  15. </manifest>   
 

Windows Project 

Add the following permissions
  • Location
  •  Internet
Follow these docs for generating the API key - "msdn.microsoft.com".

IOS Project

Add API key to Info.plist file. For that, go to Solution Explorer >> XamGoogleMapsApp.IOS app>>Info.plist file.
  1. <key>NSLocationAlwaysUsageDescription</key>     
  2.  <string>Can we use your location</string>   
  3. <key>NSLocationWhenInUseUsageDescription</key>    
  4.   <string>We are using your location</string
Now, we need to call Xamarin.Forms.Maps to each platform.
 
Android Project - MainActivity.cs file, inside the OnCreate method.
  1. Xamarin.FormsMaps.Init(this, bundle); 
IOS Project -  AppDelegate.cs  file, inside  FinishedLaunching  method.
  1. Xamarin.FormsMaps.Init(); 
UWP project - MainPage.xaml file, inside MainPage constructor.
  1. Xamarin.FormsMaps.Init("INSERT_AUTHENTICATION_TOKEN_HERE");              
Step 8

Go to "Build" menu and click "Configure Manager". Here, you can configure your startup projects. Click F5 or start to build and run your application. Running this project, you will get the result like below.
 
MapsPageApp

 
Maps Page
 
 
 
Maps Pins

 
 
Finally, we have successfully created Google Maps API in Xamarin.Forms application.