In Focus

Implementing Google Maps In Xamarin.Forms and Creating Custom Map For Tapping Functionality

Google map service is very popular in various enterprise level mobile applications. I will discuss here how to use Google maps in xamarin.forms and customize it using custom renderer for further functionality. So, let’s create a Xamarin.Forms project in Visual Studio under visual C# and cross platform and name it GoogleMapUsingXamarinForms.

Google Maps Service is very popular in various enterprise-level mobile applications. I will discuss here how to use Google Maps in Xamarin.Forms and customize it using custom renderer for further functionality. So, let’s create a Xamarin.Forms project in Visual Studio under Visual C# and cross-platform, and name it as GoogleMapUsingXamarinForms.

Let’s start with the basics. First of all, we will see how to obtain the latitude and longitude using the mobile's GPS. And then, we will use the coordinates in the Google Maps to show the exact current location. In this project, we will use C# for both, design and coding.

First of all, let’s create a folder named ‘Pages’ in Portable Class Library (PCL) and add a class named GoogleMapScreen.cs. We have to include some NuGet Packages. Go to ‘Manage NuGet Packages For Solution’. Browse for ‘Xam.Plugin.Geolocator’ (Version 3.0.4). Install it in both, PCL and GoogleMapUsingXamarinForms.Droid, projects.

Then, right-click on the Android project and go to properties. Check the required permissions.

  • ACCESS_COARSE_LOCATION
  • ACCESS_FINE_LOCATION
  • ACCESS_MOCK_LOCATION
  • ACCESS_LOCATION_EXTRA_COMMANDS
  • INTERNET
  • ACCESS_WIFI_STATE

Then, in GoogleMapScreen.cs, write the following code. 

  1. class GoogleMapScreen : ContentPage  
  2.     {  
  3.         public GoogleMapScreen()  
  4.         {  
  5.             GoogleMapScreenLayout();  
  6.         }  
  7.  
  8.         #region initialize  
  9.         Label lblLat = new Label();  
  10.         Label lblLong = new Label();          
  11.         #endregion  
  12.   
  13.         public void GoogleMapScreenLayout()  
  14.         {  
  15.             #region label latitude  
  16.             lblLat = new Label  
  17.             {  
  18.                 Text = "Lat",  
  19.                 FontSize = 20,  
  20.                 TextColor = Color.Gray  
  21.             };  
  22.             StackLayout slLblLat = new StackLayout  
  23.             {  
  24.                 Children = { lblLat },  
  25.                 Orientation = StackOrientation.Horizontal,  
  26.                 Padding = new Thickness(10, 10, 10, 10)  
  27.             };  
  28.             #endregion  
  29.  
  30.             #region label longitude  
  31.             lblLong = new Label  
  32.             {  
  33.                 Text = "Long",  
  34.                 FontSize = 20,  
  35.                 TextColor = Color.Gray  
  36.             };  
  37.             StackLayout slLblLong = new StackLayout  
  38.             {  
  39.                 Children = { lblLong },  
  40.                 Orientation = StackOrientation.Horizontal,  
  41.                 Padding = new Thickness(10, 10, 10, 10)  
  42.             };  
  43.             #endregion  
  44.  
  45.             #region button for current location  
  46.             Button btnLatLong = new Button  
  47.             {  
  48.                 Text = "Choose location",  
  49.                 HorizontalOptions = LayoutOptions.FillAndExpand,  
  50.                 BackgroundColor = Color.FromHex("4690FB"),  
  51.                 TextColor = Color.White,  
  52.                 BorderRadius = 10,  
  53.                 WidthRequest = 100,  
  54.                 HeightRequest = 50,  
  55.                 FontAttributes = FontAttributes.Bold  
  56.             };  
  57.             btnLatLong.Clicked += BtnLatLong_Clicked;  
  58.   
  59.             StackLayout slBtnLatLong = new StackLayout  
  60.             {  
  61.                 Children = { btnLatLong },  
  62.                 Orientation = StackOrientation.Horizontal,  
  63.                 Padding = new Thickness(20, 20, 20, 20)  
  64.             };  
  65.             #endregion  
  66.  
  67.             #region stack layouts and contents  
  68.             StackLayout slGoogleMapScreen = new StackLayout  
  69.             {  
  70.                 Children = { slLblLat, slLblLong, slBtnLatLong },  
  71.                 HorizontalOptions = LayoutOptions.FillAndExpand,  
  72.                 VerticalOptions = LayoutOptions.FillAndExpand,  
  73.                 Padding = new Thickness(0, 0, 0, 0),  
  74.                 BackgroundColor = Color.FromHex("DDEEFD")  
  75.             };  
  76.   
  77.             ScrollView svGoogleMapScreen = new ScrollView  
  78.             {  
  79.                 Content = slGoogleMapScreen  
  80.             };  
  81.   
  82.             Content = svGoogleMapScreen;  
  83.             #endregion  
  84.         }  
  85.   
  86.         private async void BtnLatLong_Clicked(object sender, EventArgs e)  
  87.         {  
  88.             await RetrieveLocation();  
  89.         }  
  90.   
  91.         private async Task RetrieveLocation()  
  92.         {  
  93.             var locator = CrossGeolocator.Current;  
  94.             locator.DesiredAccuracy = 20;  
  95.             var position = await locator.GetPositionAsync(timeoutMilliseconds: 10000);  
  96.   
  97.             lblLat.Text = "Latitude : " + position.Latitude.ToString();  
  98.             lblLong.Text = "Longitude : " + position.Longitude.ToString();  
  99.         }  
  100.     }  

And also, we have to make some changes in App.cs.

  1. public class App : Application  
  2.     {  
  3.         static NavigationPage navPage;  
  4.         public App()  
  5.         {  
  6.             MainPage = FrontPage();  
  7.         }  
  8.   
  9.         public static Page FrontPage()  
  10.         {  
  11.             navPage = new NavigationPage(new GoogleMapScreen());  
  12.             return navPage;  
  13.         }  
  14.     }  

After running the project on a real device, the output will look like this.

 

To implement this latitude and longitude in Google Maps, we need to obtain Google MapsAPIi key first. For that, we have to go to this page : https://console.developers.google.comhttps://console.developers.google.com

Then, create a new project here and name it “GoogleMapUsingXamarinForms”. Click “Enable API and Services”. On the next page, you will find a list of APIs. Click on “Google Maps Android API”. Enable it and click “Create Credentials”. Then, on the next page, click “What credentials do I need”. Then, click “Restrict Key”.

In the next page, you will find several radio buttons under key restrictions. As we will use this key for Android app, click the “Android apps” radio button and then click on “Add Package Name and Fingerprint” button. Here, there will be two fields you need to insert the data in. “Package name” and “SHA-1 Certificate Fingerprint”. For obtaining “SHA-1 Certificate Fingerprint”, you have to go to the directory where java jdk is installed. In my case, it was installed here : “C:\Program Files\Java\jdk1.8.0_131\bin”. Then open Command Prompt here, in this directory. Write this command 
keytool -list -v -keystore "C:\Users\USERNAME_OF_THE_MACHINE\AppData\Local\Xamarin\Mono for Android\debug.keystore" -alias androiddebugkey -storepass android -keypass android

If everything is all right, you will get data after pressing enter. Here you will find SHA-1 Certificate Fingerprint. Copy this and paste it in the “SHA-1 Certificate Fingerprint” field of the page. And for “Package name”, go to properties of “GoogleMapUsingXamarinForms.Droid”. Then go to Android Manifest. You will find Package name there. After filling the information correctly, save it. Now the api is ready for use. We will use this api into our project.

Now, let’s flip to our project. First of all, we need to install xamarin.forms.maps(version 2.3.2.127) form nuget in both PCL and GoogleMapUsingXamarinForms.Droid project. First initialize the map in initialize region,

  1. Map map = new Map();  

 Then, add this code to make a map in the view screen. Then pass the stacklayout of the map into main stacklayout.

  1. #region Map  
  2.             map = new Map  
  3.             {  
  4.                 WidthRequest = 320,  
  5.                 HeightRequest = 200,  
  6.                 IsShowingUser = true,  
  7.                 MapType = MapType.Street  
  8.             };  
  9.             StackLayout slMap = new StackLayout  
  10.             {  
  11.                 Children = { map },  
  12.                 Orientation = StackOrientation.Horizontal,  
  13.                 Padding = new Thickness(10, 10, 10, 10)  
  14.             };  
  15.             #endregion  

And write this code into button click.

  1. map.MoveToRegion(  
  2.                 MapSpan.FromCenterAndRadius(new Xamarin.Forms.Maps.Position(position.Latitude, position.Longitude)  
  3.                 , Distance.FromMiles(1)));  

Then, go to “AndroidManifest.xml” – which is in the properties of “GoogleMapUsingXamarinForms.Droid”. Here, in the Application segment, we have to define the api key, which we have obtained earlier

  1. <application android:label="GoogleMapUsingXamarinForms" android:icon="@drawable/icon">  
  2.     <meta-data android:name ="com.google.android.geo.API_KEY" android:value="YOUR_API_KEY"></meta-data>  
  3.   </application>  

After building, run the application. If everything is all right, you will see the Google map pointing at your place after clicking the button.

 

Now, if we want to add some simple functionality into this Google map like, clicking over an area will show the latitude and longitude of the place. Then we won’t be able to make that in this map. In that case, we will need a custom map, that can be generated by custom renderer of xamarin.forms. To make that, let’s create a folder named “CustomRenderer” in both PCL and Android project. In PCL CustomRenderer, add a class named “CustomMapForClickEvent.cs”. And in Android CustomRendered, add a class named “CustomMapForClickEventRenderer.cs”.

CustomMapForClickEventRenderer.cs

  1. [assembly: ExportRenderer(typeof(GoogleMapUsingXamarinForms.CustomRenderer.CustomMapForClickEvent), typeof(CustomMapForClickEventRenderer))]  
  2.   
  3. namespace GoogleMapUsingXamarinForms.Droid.CustomRenderer  
  4. {  
  5.     public class CustomMapForClickEventRenderer : MapRenderer, IOnMapReadyCallback  
  6.     {  
  7.         private GoogleMap _map;  
  8.   
  9.         public void OnMapReady(GoogleMap googleMap)  
  10.         {  
  11.             _map = googleMap;  
  12.             if (_map != null)  
  13.                 _map.MapClick += _map_MapClick;  
  14.         }  
  15.   
  16.         protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.View> e)  
  17.         {  
  18.             if (_map != null)  
  19.                 _map.MapClick -= _map_MapClick;  
  20.             base.OnElementChanged(e);  
  21.             if (Control != null)  
  22.                 ((MapView)Control).GetMapAsync(this);  
  23.         }  
  24.   
  25.   
  26.   
  27.         private void _map_MapClick(object sender, GoogleMap.MapClickEventArgs e)  
  28.         {  
  29.             ((CustomMapForClickEvent)Element).OnTap(new Xamarin.Forms.Maps.Position(e.Point.Latitude, e.Point.Longitude));  
  30.         }    }  
  31. }  

CustomMapForClickEvent.cs

 

  1. namespace GoogleMapUsingXamarinForms.CustomRenderer  
  2. {  
  3.     public class CustomMapForClickEvent : Map  
  4.     {  
  5.         public event EventHandler<TapEventArgs> Tap;  
  6.   
  7.         public CustomMapForClickEvent()  
  8.         {  
  9.   
  10.         }  
  11.   
  12.         public CustomMapForClickEvent(MapSpan region) : base(region)  
  13.         {  
  14.   
  15.         }  
  16.   
  17.         public void OnTap(Position coordinate)  
  18.         {  
  19.             OnTap(new TapEventArgs { Position = coordinate });  
  20.         }  
  21.   
  22.         protected virtual void OnTap(TapEventArgs e)  
  23.         {  
  24.             var handler = Tap;  
  25.             if (handler != null) handler(this, e);  
  26.         }  
  27.     }  
  28.   
  29.     public class TapEventArgs : EventArgs  
  30.     {  
  31.         public Position Position { get; set; }  
  32.     }  
  33. }  

Then, in the design view, let’s make an instance of this custom map and use the tap event. First of all, initialize the custom map in the initialize region,

  1. CustomMapForClickEvent customMap = new CustomMapForClickEvent();  

Then, add a new region for custom map writing necessary code and stacklayouts. Then add the stacklayout in the main stacklayout children.

  1. #region custom map  
  2.             customMap = new CustomMapForClickEvent  
  3.             {  
  4.                 WidthRequest = 320,  
  5.                 HeightRequest = 200,  
  6.                 IsShowingUser = true,  
  7.                 MapType = MapType.Street  
  8.             };  
  9.             customMap.Tap += CustomMap_Tap;  
  10.             StackLayout slCustomMap = new StackLayout  
  11.             {  
  12.                 Children = { customMap },  
  13.                 Orientation = StackOrientation.Horizontal,  
  14.                 Padding = new Thickness(10, 10, 10, 10)  
  15.             };  
  16.             #endregion  
  17.   
  18. private void CustomMap_Tap(object sender, TapEventArgs e)  
  19.         {  
  20.             var latt = e.Position.Latitude;  
  21.             var longg = e.Position.Longitude;  
  22.   
  23.             lblLat.Text = latt.ToString();  
  24.             lblLong.Text = longg.ToString();  
  25.   
  26.             Pin pin = new Pin  
  27.             {  
  28.                 Position = e.Position,  
  29.                 Label = "Position"  
  30.             };  
  31.   
  32.             customMap.Pins.Add(pin);  
  33.         }  

And in the button click code, let’s add these lines.

  1. customMap.MoveToRegion(  
  2.                 MapSpan.FromCenterAndRadius(new Xamarin.Forms.Maps.Position(position.Latitude, position.Longitude)  
  3.                 , Distance.FromMiles(1)));  

That’s it. If we run the project and click button to choose location we will get the output like this. And we can also tap the second custom map to find the coordinate.