Using the Google Maps API in your application

Using the Maps application is great, but sometimes you want to include maps directly in your application. In addition to the built-in maps application, Google also offers a native mapping API for Android. The Maps API is suitable for cases where you want to maintain more control over the mapping experience. Things that are possible with the Maps API include:

  • Programmatically changing the viewpoint of the map.
  • Adding and customizing markers.
  • Annotating a map with overlays.

Unlike the now-deprecated Google Maps Android API v1, Google Maps Android API v2 is part of Google Play Services. A Xamarin.Android app must meet some mandatory prerequisites before it is possible to use the Google Maps Android API.

Google Maps API prerequisites

Several steps need to be taken before you can use the Maps API, including:

Obtain a Google Maps API Key

The first step is to get a Google Maps API key (note that you cannot reuse an API key from the legacy Google Maps v1 API). For information about how to obtain and use the API key with Xamarin.Android, see Obtaining A Google Maps API Key.

Install the Google Play Services SDK

Google Play Services is a technology from Google that allows Android applications to take advantage of various Google features such as Google+, In-App Billing, and Maps. These features are accessible on Android devices as background services, which are contained in the Google Play Services APK.

Android applications interact with Google Play Services through the Google Play Services client library. This library contains the interfaces and classes for the individual services such as Maps. The following diagram shows the relationship between an Android application and Google Play Services:

Diagram illustrating the Google Play Store updating the Google Play Services APK

The Android Maps API is provided as a part of Google Play Services. Before a Xamarin.Android application can use the Maps API, the Google Play Services SDK must be installed using the Android SDK Manager. The following screenshot shows where in the Android SDK Manager the Google Play services client can be found:

Google Play Services appears under Extras in the Android SDK Manager

Install the Xamarin.GooglePlayServices.Maps package from NuGet

The Xamarin.GooglePlayServices.Maps package contains the Xamarin.Android bindings for the Google Play Services Maps API. To add the Google Play Services Map package, right-click the References folder of your project in the Solution Explorer and click Manage NuGet Packages...:

Solution Explorer showing Manage NuGet Packages context menu item under References

This opens the NuGet Package Manager. Click Browse and enter Xamarin Google Play Services Maps in the search field. Select Xamarin.GooglePlayServices.Maps and click Install. (If this package had been installed previously, click Update.):

NuGet Package Manager with Xamarin.GooglePlayServices.Maps package selected

Notice that the following dependency packages are also installed:

  • Xamarin.GooglePlayServices.Base
  • Xamarin.GooglePlayServices.Basement
  • Xamarin.GooglePlayServices.Tasks

Specify the required permissions

Apps must identify the hardware and permission requirements in order to use the Google Maps API. Some permissions are automatically granted by the Google Play Services SDK, and it is not necessary for a developer to explicitly add them to AndroidManfest.XML:

  • Access to the Network State – The Maps API must be able to check if it can download the map tiles.

  • Internet Access – Internet access is necessary to download the map tiles and communicate with the Google Play Servers for API access.

The following permissions and features must be specified in the AndroidManifest.XML for the Google Maps Android API:

GoogleMap
application
<application ...>
   ...
   <uses-library android:name="org.apache.http.legacy" android:required="false" />    
</application>

The following snippet is an example of the settings that must be added to AndroidManifest.XML:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="4.5" package="com.xamarin.docs.android.mapsandlocationdemo2" android:versionCode="6">
    <uses-sdk android:minSdkVersion="23" android:targetSdkVersion="28" />

    <!-- Google Maps for Android v2 requires OpenGL ES v2 -->
    <uses-feature android:glEsVersion="0x00020000" android:required="true" />

    <!-- Necessary for apps that target Android 9.0 or higher -->
    <uses-library android:name="org.apache.http.legacy" android:required="false" />

    <!-- Permission to receive remote notifications from Google Play Services -->
    <!-- Notice here that we have the package name of our application as a prefix on the permissions. -->
    <uses-permission android:name="<PACKAGE NAME>.permission.MAPS_RECEIVE" />
    <permission android:name="<PACKAGE NAME>.permission.MAPS_RECEIVE" android:protectionLevel="signature" />

    <!-- These are optional, but recommended. They will allow Maps to use the My Location provider. -->
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

    <application android:label="@string/app_name">
        <!-- Put your Google Maps V2 API Key here. -->
        <meta-data android:name="com.google.android.maps.v2.API_KEY" android:value="YOUR_API_KEY" />
        <meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version" />
        <!-- Necessary for apps that target Android 9.0 or higher -->
        <uses-library android:name="org.apache.http.legacy" android:required="false" />
    </application>
</manifest>
ACCESS_COARSE_LOCATIONACCESS_FINE_LOCATION

Create an Emulator with Google APIs

In the event that a physical Android device with Google Play services is not installed, it is possible to create an emulator image for development. For more information see the Device Manager.

The GoogleMap Class

Once the prerequisites are satisfied, it is time to start developing the application and use the Android Maps API. The GoogleMap class is the main API that a Xamarin.Android application will use to display and interact with a Google Maps for Android. This class has the following responsibilities:

  • Interacting with Google Play services to authorize the application with the Google web service.

  • Downloading, caching, and displaying the map tiles.

  • Displaying UI controls such as pan and zoom to the user.

  • Drawing markers and geometric shapes on maps.

GoogleMap
MapGoogleMap

Adding a MapFragment to an Activity

MapFragment

Screenshot of a device displaying a Google Map fragment

MapFragment
MapFragment.GetMapAsyncGoogleMapMapFragmentIOnMapReadyCallback
IMapReadyCallback.OnMapReady(MapFragment map)GoogleMapMapFragmentIOnMapReadyCallback
public class MapWithMarkersActivity : AppCompatActivity, IOnMapReadyCallback
{
    protected override void OnCreate(Bundle bundle)
    {
        base.OnCreate(bundle);
        SetContentView(Resource.Layout.MapLayout);

        var mapFragment = (MapFragment) FragmentManager.FindFragmentById(Resource.Id.map);
        mapFragment.GetMapAsync(this);

        // remainder of code omitted
    }

    public void OnMapReady(GoogleMap map)
    {
        // Do something with the map, i.e. add markers, move to a specific location, etc.
    }
}

Map types

There are five different types of maps available from the Google Maps API:

  • Normal - This is the default map type. It shows roads and important natural features along with some artificial points of interest (such as buildings and bridges).

  • Satellite - This map shows satellite photography.

  • Hybrid - This map shows satellite photography and road maps.

  • Terrain - This primarily shows topographical features with some roads.

  • None - This map does not load any tiles, it is rendered as an empty grid.

The image below shows three of the different types of maps, from left-to-right (normal, hybrid, terrain):

Three map example screenshots: Normal, Hybrid, and Terrain

GoogleMap.MapType
public void OnMapReady(GoogleMap map)
{
    map.MapType = GoogleMap.MapTypeHybrid;
}

GoogleMap properties

GoogleMapGoogleMapMapFragmentGoogleMapOptionsMapFragment
GoogleMapOptions mapOptions = new GoogleMapOptions()
    .InvokeMapType(GoogleMap.MapTypeSatellite)
    .InvokeZoomControlsEnabled(false)
    .InvokeCompassEnabled(true);

FragmentTransaction fragTx = FragmentManager.BeginTransaction();
mapFragment = MapFragment.NewInstance(mapOptions);
fragTx.Add(Resource.Id.map, mapFragment, "map");
fragTx.Commit();
GoogleMapGoogleMap
public void OnMapReady(GoogleMap map)
{
    map.UiSettings.ZoomControlsEnabled = true;
    map.UiSettings.CompassEnabled = true;
}

Interacting with the GoogleMap

The Android Maps API provides APIs that allow an Activity to change the viewpoint, add markers, place custom overlays, or draw geometric shapes. This section will discuss how to accomplish some of these tasks in Xamarin.Android.

Changing the Viewpoint

CameraUpdate
CameraUpdateMoveCameraAnimateCamera
CameraUpdateFactoryCameraUpdate
MapFragment mapFrag = (MapFragment) FragmentManager.FindFragmentById(Resource.Id.my_mapfragment_container);
mapFrag.GetMapAsync(this);
...

public void OnMapReady(GoogleMap map)
{   
    map.MoveCamera(CameraUpdateFactory.ZoomIn());
}
CameraUpdateCameraPositionCameraUpdateCameraPositionGoogleMap
public void OnMapReady(GoogleMap map)
{
    LatLng location = new LatLng(50.897778, 3.013333);

    CameraPosition.Builder builder = CameraPosition.InvokeBuilder();
    builder.Target(location);
    builder.Zoom(18);
    builder.Bearing(155);
    builder.Tilt(65);

    CameraPosition cameraPosition = builder.Build();

    CameraUpdate cameraUpdate = CameraUpdateFactory.NewCameraPosition(cameraPosition);

    map.MoveCamera(cameraUpdate);
}
GoogleMap

Example Google Map showing a specified location with a tilted viewing angle

Drawing on the Map

The Android Maps API provides API's for drawing the following items on a map:

  • Markers - These are special icons that are used to identify a single location on a map.

  • Overlays - This is an image that can be used to identify a collection of locations or area on the map.

  • Lines, Polygons, and Circles - These are APIs that allow Activities to add shapes to a map.

Markers

The Maps API provides a Marker class which encapsulates all of the data about a single location on a map. By default the Marker class uses a standard icon provided by Google Maps. It is possible to customize the appearance of a marker and to respond to user clicks.

Adding a Marker
GoogleMap
public void OnMapReady(GoogleMap map)
{
    MarkerOptions markerOpt1 = new MarkerOptions();
    markerOpt1.SetPosition(new LatLng(50.379444, 2.773611));
    markerOpt1.SetTitle("Vimy Ridge");

    map.AddMarker(markerOpt1);
}

The title of the marker will be displayed in an info window when the user taps on the marker. The following screenshot shows what this marker looks like:

Example Google Map with a marker and an info window for Vimy Ridge

Customizing A Marker
MarkerOptions.InvokeIconBitmapDescriptor
DefaultMarker(float colour)FromAsset(string assetName)FromBitmap(Bitmap image)FromFile(string fileName)FromResource(int resourceId)

The following code snippet shows an example of creating a cyan coloured default marker:

public void OnMapReady(GoogleMap map)
{
    MarkerOptions markerOpt1 = new MarkerOptions();
    markerOpt1.SetPosition(new LatLng(50.379444, 2.773611));
    markerOpt1.SetTitle("Vimy Ridge");

    var bmDescriptor = BitmapDescriptorFactory.DefaultMarker (BitmapDescriptorFactory.HueCyan);
    markerOpt1.InvokeIcon(bmDescriptor);

    map.AddMarker(markerOpt1);
}

Info windows

Info windows are special windows that popup to display information to the user when they tap a specific marker. By default the info window will display the contents of the marker's title. If the title has not been assigned, then no info window will appear. Only one info window may be shown at a time.

It is possible to customize the info window by implementing the GoogleMap.IInfoWindowAdapter interface. There are two important methods on this interface:

public View GetInfoWindow(Marker marker)nullpublic View GetInfoContents(Marker marker)nullnull

An info window is not a live view - instead Android will convert the View to a static bitmap and display that on the image. This means that an info window cannot respond to any touch events or gestures, nor will it automatically update itself. To update an info window, it is necessary to call the GoogleMap.ShowInfoWindow method.

The following image shows some examples of some customized info windows. The image on the left has its contents customized, while the image on the right has its window and contents customized with rounded corners:

Example marker windows for Melbourne, including icon and population. The right window has rounded corners.

GroundOverlays

Unlike markers, which identify a specific location on a map, a GroundOverlay is an image that is used to identify a collection of locations or an area on the map.

Adding a GroundOverlay
GoogleMap.AddGroundOverlayGroundOverlay
BitmapDescriptor image = BitmapDescriptorFactory.FromResource(Resource.Drawable.polarbear);
GroundOverlayOptions groundOverlayOptions = new GroundOverlayOptions()
    .Position(position, 150, 200)
    .InvokeImage(image);
GroundOverlay myOverlay = googleMap.AddGroundOverlay(groundOverlayOptions);

The following screenshot shows this overlay on a map:

Example map with an overlayed image of a polar bear

Lines, Circles, and Polygons

There are three simple types of geometric figures that can be added to a map:

  • Polyline - This is a series of connected line segments. It can mark a path on a map or create a geometric shape.

  • Circle - This will draw a circle on the map.

  • Polygon - This is a closed shape for marking areas on a map.

Polylines
LatLngPolylineOptionsPolylineOptionGoogleMapAddPolyline
PolylineOption rectOptions = new PolylineOption();
rectOptions.Add(new LatLng(37.35, -122.0));
rectOptions.Add(new LatLng(37.45, -122.0));
rectOptions.Add(new LatLng(37.45, -122.2));
rectOptions.Add(new LatLng(37.35, -122.2));
rectOptions.Add(new LatLng(37.35, -122.0)); // close the polyline - this makes a rectangle.

googleMap.AddPolyline(rectOptions);
Circles

Circles are created by first instantiating a CircleOption object which will specify the center and the radius of the circle in metres. The circle is drawn on the map by calling GoogleMap.AddCircle. The following code snippet shows how to draw a circle:

CircleOptions circleOptions = new CircleOptions ();
circleOptions.InvokeCenter (new LatLng(37.4, -122.1));
circleOptions.InvokeRadius (1000);

googleMap.AddCircle (circleOptions);
Polygons
PolygonPolylinePolygonPolygonPolyline
PolylinePolygonAddPolygonPolyline
PolygonOptions rectOptions = new PolygonOptions();
rectOptions.Add(new LatLng(37.35, -122.0));
rectOptions.Add(new LatLng(37.45, -122.0));
rectOptions.Add(new LatLng(37.45, -122.2));
rectOptions.Add(new LatLng(37.35, -122.2));
// notice we don't need to close off the polygon

googleMap.AddPolygon(rectOptions);

Responding to user events

There are three types of interactions a user may have with a map:

  • Marker Click - The user clicks on a marker.

  • Marker Drag - The user has long-clicked on a mparger

  • Info Window Click - The user has clicked on an info window.

Each of these events will be discussed in more detail below.

Marker click events

MarkerClickedGoogleMap.MarkerClickEventArgs
GoogleMap.MarkerClickEventArgs.HandledtruefalseMarkerMarkerClick
MarkerClick
void MapOnMarkerClick(object sender, GoogleMap.MarkerClickEventArgs markerClickEventArgs)
{
    markerClickEventArgs.Handled = true;

    var marker = markerClickEventArgs.Marker;
    if (marker.Id.Equals(gotMauiMarkerId))
    {
        LatLng InMaui = new LatLng(20.72110, -156.44776);

        // Move the camera to look at Maui.
        PositionPolarBearGroundOverlay(InMaui);
        googleMap.AnimateCamera(CameraUpdateFactory.NewLatLngZoom(InMaui, 13));
        gotMauiMarkerId = null;
        polarBearMarker.Remove();
        polarBearMarker = null;
    }
    else
    {
        Toast.MakeText(this, $"You clicked on Marker ID {marker.Id}", ToastLength.Short).Show();
    }
}

Marker Drag events

Marker.DraggabletrueMarkerOptions.Draggabletrue

To drag the marker, the user must first long-click on the marker and then their finger must remain on the map. When the user's finger is dragged around on the screen, the marker will move. When the user's finger lifts off the screen, the marker will remain in place.

The following list describes the various events that will be raised for a draggable marker:

GoogleMap.MarkerDragStart(object sender, GoogleMap.MarkerDragStartEventArgs e)GoogleMap.MarkerDrag(object sender, GoogleMap.MarkerDragEventArgs e)GoogleMap.MarkerDragEnd(object sender, GoogleMap.MarkerDragEndEventArgs e)
EventArgsP0Marker

Info Window Click events

InfoWindowClick
public void OnMapReady(GoogleMap map)
{
    map.InfoWindowClick += MapOnInfoWindowClick;
}

private void MapOnInfoWindowClick (object sender, GoogleMap.InfoWindowClickEventArgs e)
{
    Marker myMarker = e.Marker;
    // Do something with marker.
}
View

Related Links