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
- Hybrid
- Satellite
- Street (the default)
- Generic
- Place
- SavedPin
- 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.
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.
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
- using System;
- using System.Collections.Generic;
- using System.Diagnostics;
- using System.Text;
- using Xamarin.Forms;
- using Xamarin.Forms.Maps;
-
- namespace XamGoogleMapsApp
- {
- public class MapsApi : ContentPage
- {
- Map map;
- public MapsApi()
- {
- map = new Map
- {
-
- HeightRequest = 100,
- WidthRequest = 960,
- VerticalOptions = LayoutOptions.FillAndExpand
- };
-
-
- map.MoveToRegion(new MapSpan(new Position(0, 0), 360, 360));
-
-
- var slider = new Slider(1, 18, 1);
- slider.ValueChanged += (sender, e) => {
- var zoomLevel = e.NewValue;
- var latlongdegrees = 360 / (Math.Pow(2, zoomLevel));
- Debug.WriteLine(zoomLevel + " -> " + latlongdegrees);
- if (map.VisibleRegion != null)
- map.MoveToRegion(new MapSpan(map.VisibleRegion.Center, latlongdegrees, latlongdegrees));
- };
-
-
- var street = new Button { Text = "Street" };
- var hybrid = new Button { Text = "Hybrid" };
- var satellite = new Button { Text = "Satellite" };
- street.Clicked += HandleClicked;
- hybrid.Clicked += HandleClicked;
- satellite.Clicked += HandleClicked;
- var segments = new StackLayout
- {
- Spacing = 30,
- HorizontalOptions = LayoutOptions.CenterAndExpand,
- Orientation = StackOrientation.Horizontal,
- Children = { street, hybrid, satellite }
- };
-
-
- var stack = new StackLayout { Spacing = 0 };
- stack.Children.Add(map);
- stack.Children.Add(slider);
- stack.Children.Add(segments);
- Content = stack;
-
-
- map.PropertyChanged += (sender, e) => {
- Debug.WriteLine(e.PropertyName + " just changed!");
- if (e.PropertyName == "VisibleRegion" && map.VisibleRegion != null)
- CalculateBoundingCoordinates(map.VisibleRegion);
- };
-
- }
- void HandleClicked(object sender, EventArgs e)
- {
- var b = sender as Button;
- switch (b.Text)
- {
- case "Street":
- map.MapType = MapType.Street;
- break;
- case "Hybrid":
- map.MapType = MapType.Hybrid;
- break;
- case "Satellite":
- map.MapType = MapType.Satellite;
- break;
- }
- }
-
-
- static void CalculateBoundingCoordinates(MapSpan region)
- {
- var center = region.Center;
- var halfheightDegrees = region.LatitudeDegrees / 2;
- var halfwidthDegrees = region.LongitudeDegrees / 2;
-
- var left = center.Longitude - halfwidthDegrees;
- var right = center.Longitude + halfwidthDegrees;
- var top = center.Latitude + halfheightDegrees;
- var bottom = center.Latitude - halfheightDegrees;
-
- if (left < -180) left = 180 + (180 + left);
- if (right > 180) right = (right - 180) - 180;
-
- Debug.WriteLine("Bounding box:");
- Debug.WriteLine(" " + top);
- Debug.WriteLine(" " + left + " " + right);
- Debug.WriteLine(" " + bottom);
- }
- }
- }
Step 4
Similarly, create a new class named MapsPage.cs page. The code is given below.
CS code
- using System;
- using System.Collections.Generic;
- using System.Text;
- using Xamarin.Forms;
-
- namespace XamGoogleMapsApp
- {
- public class MapsPage : ContentPage
- {
- public MapsPage()
- {
- var l = new Label
- {
- Text = "These buttons leave the current app and open the built-in Maps app for the platform"
- };
-
- var openLocation = new Button
- {
- Text = "Open location using built-in Maps app"
- };
- openLocation.Clicked += (sender, e) => {
-
- if (Device.RuntimePlatform == Device.iOS)
- {
- Device.OpenUri(new Uri("http://maps.apple.com/?q=394+Pacific+Ave+San+Francisco+CA"));
- }
- else if (Device.RuntimePlatform == Device.Android)
- {
- Device.OpenUri(new Uri("geo:0,0?q=394+Pacific+Ave+San+Francisco+CA"));
-
- }
- else if (Device.RuntimePlatform == Device.UWP )
- {
- Device.OpenUri(new Uri("bingmaps:?where=394 Pacific Ave San Francisco CA"));
- }
- };
-
- var openDirections = new Button
- {
- Text = "Get directions using built-in Maps app"
- };
- openDirections.Clicked += (sender, e) => {
-
- if (Device.RuntimePlatform == Device.iOS)
- {
-
- Device.OpenUri(new Uri("http://maps.apple.com/?daddr=San+Francisco,+CA&saddr=cupertino"));
-
- }
- else if (Device.RuntimePlatform == Device.Android)
- {
-
- Device.OpenUri(new Uri("http://maps.google.com/?daddr=San+Francisco,+CA&saddr=Mountain+View"));
-
- }
- else if (Device.RuntimePlatform == Device.UWP)
- {
- Device.OpenUri(new Uri("bingmaps:?rtp=adr.394 Pacific Ave San Francisco CA~adr.One Microsoft Way Redmond WA 98052"));
- }
- };
- Content = new StackLayout
- {
- Padding = new Thickness(5, 20, 5, 0),
- HorizontalOptions = LayoutOptions.Fill,
- Children = {
- l,
- openLocation,
- openDirections
- }
- };
- }
- }
- }
Step 5
Create a new class named PinsPage.cs page. Here is the code for this page.
CS code
- using System;
- using System.Collections.Generic;
- using System.Text;
- using Xamarin.Forms;
- using Xamarin.Forms.Maps;
-
- namespace XamGoogleMapsApp
- {
- public class PinPage : ContentPage
- {
- Map map;
-
- public PinPage()
- {
- map = new Map
- {
- IsShowingUser = true,
- HeightRequest = 100,
- WidthRequest = 960,
- VerticalOptions = LayoutOptions.FillAndExpand
- };
-
- map.MoveToRegion(MapSpan.FromCenterAndRadius(
- new Position(36.9628066, -122.0194722), Distance.FromMiles(3)));
- var position = new Position(36.9628066, -122.0194722);
- var pin = new Pin
- {
- Type = PinType.Place,
- Position = position,
- Label = "Santa Cruz",
- Address = "custom detail info"
- };
- map.Pins.Add(pin);
-
-
-
- var morePins = new Button { Text = "Add more pins" };
- morePins.Clicked += (sender, e) => {
- map.Pins.Add(new Pin
- {
- Position = new Position(36.9641949, -122.0177232),
- Label = "Boardwalk"
- });
- map.Pins.Add(new Pin
- {
- Position = new Position(36.9571571, -122.0173544),
- Label = "Wharf"
- });
- map.MoveToRegion(MapSpan.FromCenterAndRadius(
- new Position(36.9628066, -122.0194722), Distance.FromMiles(1.5)));
-
- };
- var reLocate = new Button { Text = "Re-center" };
- reLocate.Clicked += (sender, e) => {
- map.MoveToRegion(MapSpan.FromCenterAndRadius(
- new Position(36.9628066, -122.0194722), Distance.FromMiles(3)));
- };
- var buttons = new StackLayout
- {
- Orientation = StackOrientation.Horizontal,
- Children = {
- morePins, reLocate
- }
- };
-
- Content = new StackLayout
- {
- Spacing = 0,
- Children = {
- map,
- buttons
- }
- };
- }
- }
- }
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
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
-
- using Xamarin.Forms;
-
- namespace XamGoogleMapsApp
- {
- public partial class App : Application
- {
- public App ()
- {
- InitializeComponent();
-
- MainPage = new TabbedPage()
- {
- Children =
- {
- new MapsPage(),
- new PinPage(),
- new MapsApi()
-
- }
- };
-
- }
-
- protected override void OnStart ()
- {
-
- }
-
- protected override void OnSleep ()
- {
-
- }
-
- protected override void OnResume ()
- {
-
- }
- }
- }
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
- <?xml version="1.0" encoding="utf-8"?>
- <manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="com.companyname.XamGoogleMapsApp" android:installLocation="auto">
- <uses-sdk android:minSdkVersion="13" />
- <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
- <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
- <uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
- <uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION" />
- <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
- <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
- <uses-permission android:name="android.permission.INTERNET" />
- <application android:label="XamGoogleMapsApp.Android">
- <meta-data android:name="com.google.android.geo.API_KEY"
- android:value="AIzaSyDjd3wposlRaz0VoubNOIul-cI29qqR1hs"></meta-data>
- </application>
- </manifest>
Windows Project
Add the following permissions
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.
- <key>NSLocationAlwaysUsageDescription</key>
- <string>Can we use your location</string>
- <key>NSLocationWhenInUseUsageDescription</key>
- <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.
- Xamarin.FormsMaps.Init(this, bundle);
IOS Project - AppDelegate.cs file, inside FinishedLaunching method.
- Xamarin.FormsMaps.Init();
UWP project - MainPage.xaml file, inside MainPage constructor.
- 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.