Page updated Jan 16, 2024

Work with maps

Install Amplify-MapLibre adapter

Add the following dependency to your build.gradle (Module :app) file and click "Sync Now" when prompted:

1dependencies {
2 implementation 'com.amplifyframework:aws-auth-cognito:ANDROID_VERSION'
3 implementation 'com.amplifyframework:aws-geo-location:ANDROID_VERSION'
4
5 // Add this dependency to integrate MapLibre into your app
6 implementation 'com.amplifyframework:maplibre-adapter:ANDROID_VERSION'
7}

Note: the minimum API level required for the UI components is 21.

Display a map

First, ensure you've provisioned an Amazon Location Service Map resource and configured your app using the instructions in either Configure maps or Use existing resources guide.

Select your user interface

There are two UI components available to render maps on an Android app, the MapLibreView and the AmplifyMapView. The MapLibreView is an extension of the standard Android MapLibre MapView that is integrated with the Amplify.Geo APIs, while the AmplifyMapView is a wrapper with built-in location search, map controls, markers and a few standard UX interactions.

MapLibreView vs AmplifyMapView

If the goal is to customize the UI, the MapLibreView provides a plain map that allows you to build and integrate your own controls and flow. If the goal is to use the map to search and select places, with a standard UI, then AmplifyMapView is a good choice.

Note that even though the extensibility of AmplifyMapView is limited, you have access to the wrapped MapLibreView through the mapView property (getMapView() on Java). So any API available to MapLibreView is also available on AmplifyMapView.

MapLibreView

The MapLibreView is an extension of the standard MapView provided by the MapLibre library. The implementation adds the Amplify.Geo integration behind the scenes to enable developers to focus on their UI instead of the library integration. That also means all MapLibre APIs are available and will work as expected. Check the official MapLibre SDK for Android documentation for the API reference and guides.

Add a map to your app

  1. Navigate to your app's src/main/res/layout directory in Android Studio

  2. Create a new layout named activity_main.xml, or use an existing layout of your choice, and add the following:

1<?xml version="1.0" encoding="utf-8"?>
2<androidx.constraintlayout.widget.ConstraintLayout
3 xmlns:android="http://schemas.android.com/apk/res/android"
4 xmlns:tools="http://schemas.android.com/tools"
5 xmlns:mapbox="http://schemas.android.com/apk/res-auto"
6 android:layout_width="match_parent"
7 android:layout_height="match_parent"
8 tools:context=".MainActivity">
9
10 <com.amplifyframework.geo.maplibre.view.MapLibreView
11 android:id="@+id/mapView"
12 android:layout_width="match_parent"
13 android:layout_height="match_parent"
14 />
15
16</androidx.constraintlayout.widget.ConstraintLayout>

Initialize the MapLibreView

  1. Navigate to your app's activity (e.g. MainActivity)

  2. Add an import statement for MapLibreView at the top of your app's activity:

1import com.amplifyframework.geo.maplibre.view.MapLibreView;
1import com.amplifyframework.geo.maplibre.view.MapLibreView
  1. Declare the view instance variable at top-level of the activity:
1private MapLibreView mapView;
1private val mapView by lazy {
2 findViewById<MapLibreView>(R.id.mapView)
3}
  1. Interact with the map in the Activity's onCreate:
1@Override
2protected void onCreate(@Nullable Bundle savedInstanceState) {
3 super.onCreate(savedInstanceState);
4
5 // Note: make sure you configure Amplify before calling setContentView
6 // See the Getting Started instructions
7
8 setContentView(R.layout.activity_main);
9 mapView = findViewById(R.id.mapView);
10
11 // now you can interact with the mapView, see examples below
12}
1override fun onCreate(savedInstanceState: Bundle?) {
2 super.onCreate(savedInstanceState)
3
4 // Note: make sure you configure Amplify before calling setContentView
5 // See the Getting Started instructions
6
7 setContentView(R.layout.activity_main)
8
9 // now you can interact with the mapView, see examples below
10}

Interact with the map

The map needs to be loaded in order to interact with it. You can use either getMapAsync that is called when the map is ready or getStyle that is called when both the map and its style are ready. Some APIs, like the SymbolManager, require the style to also be loaded so you can draw markers and other symbols on the map, that's when getStyle comes in handy.

Update the map center

1import com.mapbox.mapboxsdk.camera.CameraPosition;
2import com.mapbox.mapboxsdk.geometry.LatLng;
1mapView.getMapAsync(map -> {
2 LatLng seattle = new LatLng(47.6160281982247, -122.32642111977668);
3 map.setCameraPosition(
4 new CameraPosition.Builder()
5 .target(seattle)
6 .zoom(13.0)
7 .build()
8 );
9});
1import com.mapbox.mapboxsdk.camera.CameraPosition
2import com.mapbox.mapboxsdk.geometry.LatLng
1mapView.getMapAsync { map ->
2 val seattle = LatLng(47.6160281982247, -122.32642111977668)
3 map.cameraPosition = CameraPosition.Builder()
4 .target(seattle)
5 .zoom(13.0)
6 .build()
7}

Updating cameraPosition moves the camera to the passed coordinates without any animation. If animation is needed, use map.animateCamera() instead. See the official reference for more details.

Add markers to your map

The MapLibre SDK for Android relies on the MapLibre Annotation Plugin in order to display markers on a map.

1import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
2import com.mapbox.mapboxsdk.plugins.annotation.SymbolOptions;
1mapView.getStyle((map, style) -> {
2 LatLng spaceNeedle = new LatLng(47.6205063, -122.3514661);
3 mapView.symbolManager.create(
4 new SymbolOptions()
5 .withIconImage("place")
6 .withLatLng(spaceNeedle)
7 );
8 map.animateCamera(CameraUpdateFactory.newLatLngZoom(spaceNeedle, 16.0));
9});
1import com.mapbox.mapboxsdk.camera.CameraUpdateFactory
2import com.mapbox.mapboxsdk.plugins.annotation.SymbolOptions
1mapView.getStyle { map, style ->
2 val spaceNeedle = LatLng(47.6205063, -122.3514661)
3 mapView.symbolManager.create(
4 SymbolOptions()
5 .withIconImage("place")
6 .withLatLng(spaceNeedle)
7 )
8 map.animateCamera(CameraUpdateFactory.newLatLngZoom(spaceNeedle, 16.0))
9}

Notes:

  • The mapView.symbolManager is a built-in reference of SymbolManager from the MapLibre Annotation Plugin with some standard configuration.
  • If customized icons or render other types of shapes and layers are needed, an instance of SymbolManager can be created and used to manage the different types of custom use-cases.

MapLibreView configuration parameters

The MapLibreView has several configuration parameters that are not present in the official guides yet. For a complete list, refer to the source xml file.

Also, check the official MapView API reference for the available public API documentation.

AmplifyMapView

The AmplifyMapView provides a default search field, place markers, visualization modes (map or list) and map controls. It can be used to easily embed a place picker into any app. To use the search functionality of AmplifyMapView, provision a search index resource using the instructions in either Configure Location Search or Use existing Amazon Location Service resources.

Add a map to your app

  1. Navigate to your app's src/main/res/layout directory in Android Studio

  2. Create a new layout named activity_main.xml, or use an existing layout of your choice, and add the following:

1<?xml version="1.0" encoding="utf-8"?>
2<androidx.constraintlayout.widget.ConstraintLayout
3 xmlns:android="http://schemas.android.com/apk/res/android"
4 xmlns:tools="http://schemas.android.com/tools"
5 xmlns:map="http://schemas.android.com/apk/res-auto"
6 android:layout_width="match_parent"
7 android:layout_height="match_parent"
8 tools:context=".MainActivity">
9
10 <com.amplifyframework.geo.maplibre.view.AmplifyMapView
11 android:id="@+id/mapView"
12 android:layout_width="match_parent"
13 android:layout_height="match_parent"
14 />
15
16</androidx.constraintlayout.widget.ConstraintLayout>

Initialize the AmplifyMapView

  1. Navigate to your app's activity (e.g. MainActivity)

  2. Add an import statement for AmplifyMapView at the top of your app's activity:

1import com.amplifyframework.geo.maplibre.view.AmplifyMapView;
1import com.amplifyframework.geo.maplibre.view.AmplifyMapView
  1. Declare the view instance variable at top-level of the activity:
1private AmplifyMapView amplifyMapView;
1private val amplifyMapView by lazy {
2 findViewById<AmplifyMapView>(R.id.mapView)
3}
  1. Interact with the map in the Activity's onCreate:
1@Override
2protected void onCreate(@Nullable Bundle savedInstanceState) {
3 super.onCreate(savedInstanceState);
4
5 // Note: make sure you configure Amplify before calling setContentView
6 // See the Getting Started instructions
7
8 setContentView(R.layout.activity_main);
9 amplifyMapView = findViewById(R.id.mapView);
10
11 // now you can interact with the mapView, see examples below
12}
1override fun onCreate(savedInstanceState: Bundle?) {
2 super.onCreate(savedInstanceState)
3
4 // Note: make sure you configure Amplify before calling setContentView
5 // See the Getting Started instructions
6
7 setContentView(R.layout.activity_main)
8
9 // now you can interact with the mapView, see examples below
10}

Place select

The main API provided by AmplifyMapView is an event listener that is called when a place is selected on the map, either by clicking on the mark or the item on the list.

1import android.util.Log;
1amplifyMapView.setOnPlaceSelectListener((place, symbol) -> {
2 // place is an instance of AmazonLocationPlace
3 // symbol is an instance of Symbol from MapLibre
4 Log.i("MyAmplifyApp", "The selected place is " + place.getLabel());
5 Log.i("MyAmplifyApp", "It is located at " + place.getCoordinates());
6});
1import android.util.Log
1amplifyMapView.onPlaceSelect { place, symbol ->
2 // place is an instance of AmazonLocationPlace
3 // symbol is an instance of Symbol from MapLibre
4 Log.i("MyAmplifyApp", "The selected place is ${place.label}")
5 Log.i("MyAmplifyApp", "It is located at ${place.coordinates}")
6}

AmplifyMapView configuration parameters

The view can be initialized with the following configuration parameters:

PropertyTypeDescriptionDefault
map:map_centerLatitudeFloatThe initial center latitude0.0
map:map_centerLongitudeFloatThe initial center longitude0.0
map:map_minZoomLevelIntegerThe minimum zoom level (min is 0)3
map:map_maxZoomLevelIntegerThe maximum zoom level (max is 22)18
map:map_showCompassIndicatorBooleanWhether the compass should be displayed or nottrue
map:map_showZoomControlsBooleanWhether the zoom controls should be displayed or notfalse
map:map_zoomLevelIntegerThe initial zoom level (between 0 and 22)14

Example:

1<?xml version="1.0" encoding="utf-8"?>
2<androidx.constraintlayout.widget.ConstraintLayout
3 xmlns:android="http://schemas.android.com/apk/res/android"
4 xmlns:tools="http://schemas.android.com/tools"
5 xmlns:map="http://schemas.android.com/apk/res-auto"
6 android:layout_width="match_parent"
7 android:layout_height="match_parent"
8 tools:context=".MainActivity">
9
10 <com.amplifyframework.geo.maplibre.view.AmplifyMapView
11 android:id="@+id/mapView"
12 android:layout_width="match_parent"
13 android:layout_height="match_parent"
14 map:map_zoomLevel="12"
15 map:map_centerLatitude="47.6160281982247"
16 map:map_centerLongitude="-122.32642111977668"
17 map:map_showCompassIndicator="true"
18 map:map_showZoomControls="true"
19 />
20
21</androidx.constraintlayout.widget.ConstraintLayout>

Display different map styles

The getAvailableMaps API fetches information for all maps that are available to be displayed.

This is useful if you would like to give your users a variety of map styles to choose from.

1Amplify.Geo.getAvailableMaps(
2 result -> {
3 for (final MapStyle style : result) {
4 Log.i("MyAmplifyApp", style.toString());
5 }
6 },
7 error -> Log.e("MyAmplifyApp", "Failed to get available maps.", error)
8);
1Amplify.Geo.getAvailableMaps(
2 {
3 for (mapStyle in it) {
4 Log.i("MyAmplifyApp", mapStyle.toString())
5 }
6 },
7 { Log.e("MyAmplifyApp", "Failed to get available maps.", it) }
8)
1try {
2 val result = Amplify.Geo.getAvailableMaps()
3 for (mapStyle in result) {
4 Log.i("MyAmplifyApp", mapStyle.toString())
5 }
6} catch (error: GeoException) {
7 Log.e("MyAmplifyApp", "Failed to get available maps.", error)
8}
1RxAmplify.Geo.getAvailableMaps().subscribe(
2 result -> {
3 for (final MapStyle style : result) {
4 Log.i("MyAmplifyApp", style.toString());
5 }
6 },
7 error -> Log.e("MyAmplifyApp", "Failed to get available maps.", error)
8);

You can set a different style to your map using setStyle method from the adapter:

With MapLibreView:

1// where mapStyle is a reference to the selected style from Amplify.Geo.getAvailableMaps
2mapView.setStyle(mapStyle, style -> {
3 Log.i("MyAmplifyApp", "Finished loading " + mapStyle.getStyle());
4});

With AmplifyMapView:

1// where mapStyle is a reference to the selected style from Amplify.Geo.getAvailableMaps
2amplifyMapView.getMapView().setStyle(mapStyle, style -> {
3 Log.i("MyAmplifyApp", "Finished loading " + mapStyle.getStyle());
4});

With MapLibreView:

1// where mapStyle is a reference to the selected style from Amplify.Geo.getAvailableMaps
2mapView.setStyle(mapStyle) { style ->
3 Log.i("MyAmplifyApp", "Finished loading ${mapStyle.style}.")
4}

With AmplifyMapView:

1// where mapStyle is a reference to the selected style from Amplify.Geo.getAvailableMaps
2amplifyMapView.mapView.setStyle(mapStyle) { style ->
3 Log.i("MyAmplifyApp", "Finished loading ${mapStyle.style}.")
4}