How to implement Google maps in Xamarin Forms (Android and iOS)?

Viewed 8162

I have a Google map API key and I want to use that to show maps in my Android app and iOS app using Xamarin Forms. Which library would you use to have less conflict on both OS?

1 Answers

An easy way to implement that is using the NuGet Xamarin.Forms.GoogleMaps

Xamarin.Forms.GoogleMaps features:

  • Map types
  • Traffic map
  • Map events
  • Panning with animation
  • Panning directly
  • Pins
  • Custom Pins
  • Pin drag & drop
  • Polygons
  • Lines
  • Circles
  • Custom map tiles

Follow the next steps to set up maps in your project:

  1. Install the NuGet package Xamarin.Forms.GoogleMaps in all projects.

  2. Android. Initialize the library in your MainActivity.cs in the OnCreate method:

    protected override void OnCreate(Bundle savedInstanceState)
    {
        TabLayoutResource = Resource.Layout.Tabbar;
        ToolbarResource = Resource.Layout.Toolbar;
    
        base.OnCreate(savedInstanceState);
    
        Xamarin.Essentials.Platform.Init(this, savedInstanceState);
        global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
        Xamarin.FormsGoogleMaps.Init(this, savedInstanceState); //Initialize GoogleMaps here
        LoadApplication(new App());
    }
  1. In your AndroidManifest.xml.

Add the properties com.google.android.geo.API_KEY com.google.android.gms.version org.apache.http.legacy inside the tag <application>.

Also adds the required permissions ACCESS_COARSE_LOCATION ACCESS_FINE_LOCATION.

Add some uses-feature if you will use geolocation.

Your AndroidManifest.xml should look like this:

    <?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="yvan.eht.nioj" android:installLocation="auto">
        <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="28" />
        <application android:label="YourApp.Android">
            <meta-data android:name="com.google.android.geo.API_KEY" android:value="Your_Api_Key_Here" />
            <meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version" />
            <uses-library android:name="org.apache.http.legacy" android:required="false" />
        </application>
        <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
        <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
        <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
        <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
        <uses-permission android:name="android.permission.INTERNET" />
        <uses-feature android:name="android.hardware.location" android:required="false" />
        <uses-feature android:name="android.hardware.location.gps" android:required="false" />
        <uses-feature android:name="android.hardware.location.network" android:required="false" />
    </manifest>
  1. iOS. Initialize the library in your AppDelegate.cs in the FinishedLaunching method:
   public override bool FinishedLaunching(UIApplication app, NSDictionary options)
   {
       global::Xamarin.Forms.Forms.Init();
       Xamarin.FormsGoogleMaps.Init("Your_Api_Key_Here");
       LoadApplication(new App());

       return base.FinishedLaunching(app, options);
   }
  1. In your Info.plist add the properties NSLocationAlwaysUsageDescription NSLocationWhenInUseUsageDescription NSLocationAlwaysAndWhenInUseUsageDescription
    <? xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    <plist version="1.0">
      <dict>
        <!--Your other Permissions may be on top -->
        <!-- Just add the Permissions below -->

        <key>NSLocationAlwaysUsageDescription</key>
        <string>Can we use your location at all times?</string>
        <key>NSLocationWhenInUseUsageDescription</key>
        <string>Can we use your location when your application is being used?</string>
        <key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
        <string>Can we use your location at all times?</string>
      </dict>
    </plist>

DONE


Now you can add a map in your xaml and show it in your Android and iOS app like this:

    <?xml version="1.0" encoding="utf-8"?>
    <ContentPage
        xmlns="http://xamarin.com/schemas/2014/forms"
        xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
        xmlns:d="http://xamarin.com/schemas/2014/forms/design"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:maps="clr-namespace:Xamarin.Forms.GoogleMaps;assembly=Xamarin.Forms.GoogleMaps"
        mc:Ignorable="d"
        x:Class="YourApp.MainPage">
        <ContentPage.Content>
            <Grid HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
                <Grid.RowDefinitions>
                    <RowDefinition Height="*" />
                </Grid.RowDefinitions>
    
                <maps:Map x:Name="map" VerticalOptions="FillAndExpand"></maps:Map>
            </Grid>
        </ContentPage.Content>
    </ContentPage>

OPTIONAL

Request runtime location permissions

If your application targets API 23 or later and needs to access the user's location, it must check to see if it has the required permission at runtime, and request it if it does not have it. This can be accomplished as follows:

  1. In the MainActivity class, add the following fields:
    const int RequestLocationId = 0;
    
    readonly string[] LocationPermissions =
    {
        Manifest.Permission.AccessCoarseLocation,
        Manifest.Permission.AccessFineLocation
    };
  1. In the MainActivity class, add the following OnStart override:
    protected override void OnStart()
    {
        base.OnStart();
    
        if ((int)Build.VERSION.SdkInt >= 23)
        {
            if (CheckSelfPermission(Manifest.Permission.AccessFineLocation) != Permission.Granted)
            {
                RequestPermissions(LocationPermissions, RequestLocationId);
            }
            else
            {
                // Permissions already granted - display a message.
            }
        }
    }
  1. (Not necessary if you are using Xamarin Essentials) In the MainActivity class, add the following OnRequestPermissionsResult override:
    public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Permission[] grantResults)
    {
        if (requestCode == RequestLocationId)
        {
            if ((grantResults.Length == 1) && (grantResults[0] == (int)Permission.Granted))
                // Permissions granted - display a message.
            else
                // Permissions denied - display a message.
        }
        else
        {
            base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
        }
    }
Related