

# Get started with Amazon Location Service
<a name="getting-started"></a>

This topic helps you get started with Amazon Location Service. Follow these steps to create your first application and understand how to choose the appropriate Amazon Location API based on common use cases. 

1. **Set up your AWS account and access.**

   If you don’t already have an account, you'll be prompted to create one. With the AWS free tier, you can get three months of free tier for Amazon Location Service.

   If you already have an account, you need to provide access to Amazon Location Service.

   Continue with the [Set up your account](set-up.md) topic.

1. **Understand and set up authentication.**

   To use Amazon Location, a user must be granted access to the resources and APIs that make up Amazon Location. API Key, Amazon Cognito, and AWS Identity and Access Management (IAM) are three options to grant access to your resources and actions (APIs). 

   Continue with the [Authenticate with Amazon Location Service](access.md) topic.

1. **Create your first location application.**

   See [Create your first Amazon Location Maps and Places application](first-app.md) to build your first "Hello World" application.

1. **Choose the right API.**

   Amazon Location offers a rich set of APIs across Places, Routes, Maps, and Geofences and Trackers to solve a variety of business use cases. 

   To learn more about how to choose an Amazon Location API, see [Choose the right API](choose-an-api.md) for more information.

# Set up your account
<a name="set-up"></a>

This section describes what you need to do to use Amazon Location Service. You must have an AWS account and have set up access to Amazon Location for users that want to use it.

## I'm new to AWS
<a name="new-user"></a>

### Sign up for an AWS account
<a name="sign-up-for-aws"></a>

If you do not have an AWS account, complete the following steps to create one.

**To sign up for an AWS account**

1. Open [https://portal.aws.amazon.com/billing/signup](https://portal.aws.amazon.com/billing/signup).

1. Follow the online instructions.

   Part of the sign-up procedure involves receiving a phone call or text message and entering a verification code on the phone keypad.

   When you sign up for an AWS account, an *AWS account root user* is created. The root user has access to all AWS services and resources in the account. As a security best practice, assign administrative access to a user, and use only the root user to perform [tasks that require root user access](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_root-user.html#root-user-tasks).

AWS sends you a confirmation email after the sign-up process is complete. At any time, you can view your current account activity and manage your account by going to [https://aws.amazon.com/](https://aws.amazon.com/) and choosing **My Account**.

### Create a user with administrative access
<a name="create-an-admin"></a>

After you sign up for an AWS account, secure your AWS account root user, enable AWS IAM Identity Center, and create an administrative user so that you don't use the root user for everyday tasks.

**Secure your AWS account root user**

1.  Sign in to the [AWS Management Console](https://console.aws.amazon.com/) as the account owner by choosing **Root user** and entering your AWS account email address. On the next page, enter your password.

   For help signing in by using root user, see [Signing in as the root user](https://docs.aws.amazon.com/signin/latest/userguide/console-sign-in-tutorials.html#introduction-to-root-user-sign-in-tutorial) in the *AWS Sign-In User Guide*.

1. Turn on multi-factor authentication (MFA) for your root user.

   For instructions, see [Enable a virtual MFA device for your AWS account root user (console)](https://docs.aws.amazon.com/IAM/latest/UserGuide/enable-virt-mfa-for-root.html) in the *IAM User Guide*.

**Create a user with administrative access**

1. Enable IAM Identity Center.

   For instructions, see [Enabling AWS IAM Identity Center](https://docs.aws.amazon.com//singlesignon/latest/userguide/get-set-up-for-idc.html) in the *AWS IAM Identity Center User Guide*.

1. In IAM Identity Center, grant administrative access to a user.

   For a tutorial about using the IAM Identity Center directory as your identity source, see [ Configure user access with the default IAM Identity Center directory](https://docs.aws.amazon.com//singlesignon/latest/userguide/quick-start-default-idc.html) in the *AWS IAM Identity Center User Guide*.

**Sign in as the user with administrative access**
+ To sign in with your IAM Identity Center user, use the sign-in URL that was sent to your email address when you created the IAM Identity Center user.

  For help signing in using an IAM Identity Center user, see [Signing in to the AWS access portal](https://docs.aws.amazon.com/signin/latest/userguide/iam-id-center-sign-in-tutorial.html) in the *AWS Sign-In User Guide*.

**Assign access to additional users**

1. In IAM Identity Center, create a permission set that follows the best practice of applying least-privilege permissions.

   For instructions, see [ Create a permission set](https://docs.aws.amazon.com//singlesignon/latest/userguide/get-started-create-a-permission-set.html) in the *AWS IAM Identity Center User Guide*.

1. Assign users to a group, and then assign single sign-on access to the group.

   For instructions, see [ Add groups](https://docs.aws.amazon.com//singlesignon/latest/userguide/addgroups.html) in the *AWS IAM Identity Center User Guide*.

## I already have an AWS account
<a name="existing-user"></a>

**Grant access to Amazon Location Service**

Your non-admin users have no permissions by default. Before they can access Amazon Location, you must grant permission by attaching an IAM policy with specific permissions. Make sure to follow the principle of least privilege when granting access to resources. 

**Note**  
For information about giving unauthenticated users access to Amazon Location Service functionality (for example, in a web-based application), see [Authenticate with Amazon Location Service](access.md).

The following example policy gives a user permission to access all Amazon Location operations. For more examples, see [Identity-based policy examples for Amazon Location Service](security-iam.md#security_iam_id-based-policy-examples).

```
{
  "Version": "2012-10-17",		 	 	 
  "Statement": [
    {
      "Action": [
        "geo:*",
        "geo-maps:*",
        "geo-places:*",
        "geo-routes:*"
      ],
      "Resource": "*",
      "Effect": "Allow"
    }
  ]
}
```

To provide access, add permissions to your users, groups, or roles:
+ Users and groups in AWS IAM Identity Center:

  Create a permission set. Follow the instructions in [Create a permission set](https://docs.aws.amazon.com//singlesignon/latest/userguide/howtocreatepermissionset.html) in the *AWS IAM Identity Center User Guide*.
+ Users managed in IAM through an identity provider:

  Create a role for identity federation. Follow the instructions in [Create a role for a third-party identity provider (federation)](https://docs.aws.amazon.com//IAM/latest/UserGuide/id_roles_create_for-idp.html) in the *IAM User Guide*.
+ IAM users:
  + Create a role that your user can assume. Follow the instructions in [Create a role for an IAM user](https://docs.aws.amazon.com//IAM/latest/UserGuide/id_roles_create_for-user.html) in the *IAM User Guide*.
  + (Not recommended) Attach a policy directly to a user or add a user to a user group. Follow the instructions in [Adding permissions to a user (console)](https://docs.aws.amazon.com//IAM/latest/UserGuide/id_users_change-permissions.html#users_change_permissions-add-console) in the *IAM User Guide*.

When creating applications that use Amazon Location Service, you may need some users to have unauthenticated access. For these use cases, see [Enabling unauthenticated access using Amazon Cognito](authenticating-using-cognito.md).

# Use the Amazon Location Service console to authenticate
<a name="set-up-auth"></a>

**Note**  
To learn more about authentication, see [Authenticate with Amazon Location Service](access.md).

To use Amazon Location Service, a user must be granted access to the resources and APIs that make up Amazon Location. By default, the Amazon Location APIs require authentication to use. You can use either Amazon Cognito or API keys to provide authentication and authorization for anonymous users. 

In the [Create your first Amazon Location Maps and Places application](first-app.md) tutorial, the application has anonymous usage, which means your users aren't required to sign in. In the tutorial, you create API keys for use in the sample application.

Follow the procedures below to create your first API key.

1. In the [https://console.aws.amazon.com/location](https://console.aws.amazon.com/location) and choose **API keys** from the left menu.

1. On the **API keys** page, choose **Create API key**.

1. On the **Create API key **page, fill in the following information:
   + **Name** – A name for your API key, such as `MyHelloWorldApp`.
   + **Description** – An optional description for your API key.
   + **Actions** – Specify the actions you want to authorize with this API key. You must select at least **geo-maps:Get\$1** and **geo-places:Search\$1**.
   + **Expiration time** – Optionally, add an expiration date and time for your API key. For more information, see [API key best practices](using-apikeys.md#api-keys-best-practices).
   + **Client restrictions** – Optionally, add one or more web domains or one or more Android or Apple apps where you can use the API key. For example, if the API key is to allow an application running on the website `example.com`, then you could put `*.example.com/` as an allowed referrer.
   + **Tags** – Optionally, add tags to the API key.
**Important**  
We recommend that you protect your API key usage by setting either an expiration time or a referrer, if not both.

1. Choose **Create API key** to create the API key.

1. On the detail page for the API key, you can see information about the API key that you have created. 

   Choose **Show API key** and copy the key value to use later in the [Create your first Amazon Location Maps and Places application](first-app.md) tutorial. The key value will have the format `v1.public.a1b2c3d4...`. 

# Choose the right API
<a name="choose-an-api"></a>

This topic helps you choose an Amazon Location Service API based on common use cases that you may want to solve with location-based data and services. 

Maps  
Maps provide access to both dynamic and static map types for a variety of applications. For more information, See [Amazon Location Service Maps](maps.md).  
+ **Dynamic Maps**: Interactive maps that can be customized in real time, allowing users to pan, zoom, and overlay data. For more information, See [Dynamic maps](dynamic-maps.md).
+ **Static Maps**: Static images of maps that display specific locations or routes without interactive elements, suitable for applications with limited interactivity. For more information, See [Static maps](static-maps.md).

Routes  
Routes provide capabilities for calculating optimized paths between locations. These features support applications requiring logistics planning, distance calculations, and route optimization. Users can also snap location points to roads for improved accuracy. For more information, See [Amazon Location Service Routes](routes.md).  
+ **CalculateIsolines**: Generates isolines based on travel time or distance, useful for defining service areas or reachability zones. For more information, See [Calculate isolines](calculate-isolines.md).
+ **CalculateRouteMatrix**: Provides a matrix of distances and travel times between multiple origins and destinations, supporting logistics and trip planning. For more information, See [Calculate route matrix](calculate-route-matrix.md).
+ **CalculateRoutes**: Calculates optimized routes for point-to-point or multi-stop navigation, including customizable routing preferences. For more information, See [Calculate routes](calculate-routes.md).
+ **OptimizeWaypoints**: Optimizes the order of waypoints for the most efficient travel route, minimizing distance or time. For more information, See [Optimize waypoints](actions-optimize-waypoints.md).
+ **SnapToRoads**: Aligns coordinates to the nearest road paths, enhancing GPS accuracy by snapping points to known roads. For more information, See [Snap to Roads](snap-to-roads.md).

Places  
Places enable applications to search, find, and retrieve details about points of interest, addresses, and specific locations. These capabilities enhance location-based services by providing context and improving user experience in search functions. For more information, See [Amazon Location Service Places](places.md).   
+ **Geocode**: Converts addresses or place names into geographic coordinates (longitude, latitude), supporting applications that require address-to-location transformation for mapping and spatial analysis. For more information, see [Geocode](geocode.md).
+ **Reverse Geocode**: Converts geographic coordinates to the nearest address or place name, providing context for a location. For more information, See [Reverse Geocode](reverse-geocode.md).
+ **Autocomplete**: Suggests potential completions for user-entered text, improving efficiency in search input. For more information, See [Autocomplete](autocomplete.md).
+ **GetPlace**: Retrieves detailed information about a specified place, including attributes like address, contact details, and opening hours. For more information, See [GetPlace](get-place.md).
+ **SearchNearby**: Finds places within a specified radius of a given geographic point, suitable for "near me" searches. For more information, See [Search Nearby](search-nearby.md).
+ **SearchText**: Allows text-based searching for places or points of interest based on a keyword or phrase, ideal for finding locations by name or description. For more information, See [Search Text](search-text.md).
+ **Suggest**: Provides search term suggestions as users type, enhancing search relevance and user experience. For more information, See [Suggest](suggest.md).

Geofences  
Geofencing allows applications to define geographical boundaries and monitor entry or exit events within these regions. Features include creating, updating, and deleting geofences, as well as configuring notifications or triggers for location-based actions when tracked devices cross geofence boundaries. Ideal for proximity-based notifications, security monitoring, and asset tracking within predefined areas. For more information, See [Amazon Location Service Geofences](geofences.md).

Trackers  
Tracking enables real-time monitoring of device or asset locations over time. Features include adding tracked devices, updating their location data, and retrieving historical position data. Trackers are useful for managing fleets, monitoring personnel, and ensuring the security of valuable assets by providing up-to-date location data and movement patterns. For more information, See [Amazon Location Service trackers](trackers.md).

# Create your first Amazon Location Maps and Places application
<a name="first-app"></a>

In this section, you will create your first application with Maps and Places.

**Prerequisite:**

If you already created an API key in the [Use the Amazon Location Service console to authenticate](set-up-auth.md) steps, let's get started. 

If you haven't created an API key yet, follow [Use the Amazon Location Service console to authenticate](set-up-auth.md) before continuing to build the application. If you have any questions, see [Use API keys to authenticate](using-apikeys.md) and [Amazon Location supported regions](location-regions.md) for more information.

## Web
<a name="qs-web"></a>

Here’s a step-by-step tutorial for creating an Amazon Location Service map application with MapLibre GL JS. This guide will walk you through setting up the map, adding styling options, and enabling place search functionality.

### Set up the initial page
<a name="qs-initial-page"></a>

In this section, we will set up the initial page and folder structure.

#### Add required libraries and stylesheets
<a name="qs-initial-add-library"></a>

Create an `index.html` file. To render the map, you need MapLibre GL JS and MapLibre GL Geocoder. You will add the MapLibre and Geocoder stylesheets and JavaScript scripts. 

Copy and paste the following code into your `index.html` file.

```
<!DOCTYPE html>
<html lang="en">
<head>

    <title>Amazon Location Service - Getting Started with First Map App</title>
    <meta charset='utf-8'>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="description" content="Interactive map application using Amazon Location Service">

    <!--Link to MapLibre CSS and JavaScript library for map rendering and visualization -->
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/maplibre-gl@5.x/dist/maplibre-gl.css" />
    <script src="https://cdn.jsdelivr.net/npm/maplibre-gl@5.x/dist/maplibre-gl.js"></script>
    
    <!--Link to MapLibre Geocoder CSS and JavaScript library for place search and geocoding -->
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@maplibre/maplibre-gl-geocoder@1.7.0/dist/maplibre-gl-geocoder.css" />
    <script src="https://cdn.jsdelivr.net/npm/@maplibre/maplibre-gl-geocoder@1.7.0/dist/maplibre-gl-geocoder.js"></script>
    
    <!--Link to amazon-location JavaScript librarie -->
    <script src="https://cdn.jsdelivr.net/npm/@aws/amazon-location-utilities-auth-helper@1"></script>
    <script src="https://cdn.jsdelivr.net/npm/@aws/amazon-location-client@1.2"></script>
    
    <!-- Link to the first Amazon Location Map App's CSS and JavaScript -->
    <script src="utils.js"></script>
    <link rel="stylesheet" href="style.css"/>
   

</head>
<body>
    <main> 
        
    </main>
    <script> 
        // Step 1: Setup API Key and AWS Region 
        // Step 2.1 Add maps to application
        // Step 2.2 initialize the map
        // Step 3: Add places features to application
        // Step 3.1: Get GeoPlaces instance. It will be used for addion search box and map click functionality
        // Step 3.2: Add search box to the map
        // Step 3.3.: Setup map click functionality
        // Add functions
    </script>
</body>
</html>
```

#### Create the Map container
<a name="qs-create-map-container"></a>

 Under the `<body>` element of the HTML file, create a `<div>` element in your HTML to hold the map. You can style this `<div>` in your CSS to set dimensions as needed for your application. You must download the CSS file, `style.css`, from our GitHub repository. This will help you focus on business logic. 

 Save the `style.css` and `index.html` files in the same folder. 

 Download the `style.css` file from [GitHub](https://github.com/aws-geospatial/amazon-location-samples-js/blob/quick_start_sample_js/quick-start/style.css). 

```
<main role="main" aria-label="Map Container">
    <div id="map"></div>
</main>
```

#### Add API key and AWS Region details
<a name="qs-create-add-key"></a>

Add the API key you created in [Use API keys to authenticate](using-apikeys.md) to this file, along with the AWS Region where the key was created. 

```
<!DOCTYPE html>
<html lang="en">
.....
.....
<body>
    <main role="main" aria-label="Map Container">
        <div id="map"></div>
    </main>
    <script>
        // Step 1: Setup API Key and AWS Region 
        const API_KEY = "Your_API_Key";
        const AWS_REGION = "Region_where_you_created_API_Key";
        // Step 2: Add maps to application
            // Step 2.1 initialize the map
            // Step 2.2 Add navigation controls to the map
        // Step 3: Add places feature to application        
            // Step 3.1: Get GeoPlaces instance. It will be used for addion search box and map click functionality
            // Step 3.2: Add search box to the map
            // Step 3.3.: Setup map click functionality
    </script>
</body>
</html>
```

### Add Map to your application
<a name="qs-add-map"></a>

In this section, we will add Map capabilities to the application. Before you start, your files should be in this folder structure. 

 If have not already done so, please download the `style.css` file from [GitHub](https://github.com/aws-geospatial/amazon-location-samples-js/blob/quick_start_sample_js/quick-start/style.css). 

```
|---FirstApp [Folder]
|-------------- index.html [File]
|-------------- style.css [File]
```

#### Create a Function to Initialize the Map
<a name="qs-initialize-map-function"></a>

To set up your map, create the following function, `initializeMap(...)`, after the line `//Add functions`.

Choose an initial center location and zoom level. In this example, we set the map center to Vancouver, Canada, with a zoom level of 10. Add navigation controls for easy zooming.

```
/**
 * Initializes the map with the specified style and color scheme.
 */
function initializeMap(mapStyle = "Standard", colorScheme = "Dark") {
     const styleUrl = `https://maps.geo.${AWS_REGION}.amazonaws.com/v2/styles/${mapStyle}/descriptor?key=${API_KEY}&color-scheme=${colorScheme}`;
     const map = new maplibregl.Map({
         container: 'map',                 // The ID of the map container
         style: styleUrl,                  // The style URL for the map
         center: [-123.116226, 49.246292], // Starting center coordinates
         zoom: 10,                         // Initial zoom level
         validateStyle: false              // Disable style validation
     });
     return map;                           // Return the initialized map
}
```

#### Initialize the Map
<a name="qs-initialize-map"></a>

Call `initializeMap(...)` to initialize the map. Optionally, you can initialize it with your preferred style and color scheme after the `initializeMap` function. For more style options, see [AWS map styles and features](map-styles.md).

```
// Step 1: Setup API Key and AWS Region 
const API_KEY = "Your_API_Key";
const AWS_REGION = "Region_where_you_created_API_Key";

// Step 2.1 Add maps to application
// Step 2.2 initialize the map
const map = initializeMap("Standard","Light");

// Step 3: Add places features to application
```

Open `index.html` in a browser to see the map in action.

#### Add Navigation Control
<a name="qs-add-navigation"></a>

Optionally, you can add navigation controls (zoom and rotation) to the map. This should be done after calling `initializeMap(...)`.

```
// Step 2.1 initialize the map
const map = initializeMap("Standard","Light");

// Step 2.2 Add navigation controls to the map
map.addControl(new maplibregl.NavigationControl());

// Step 3: Add places features to application
```

#### Review the Map Code
<a name="qs-add-final"></a>

Congratulations\$1 Your first app is ready to use a map. Open `index.html` in a browser. Make sure `style.css` is in the same folder as `index.html`.

Your final HTML should look like this:

```
<!DOCTYPE html>
<html lang="en">
<head>

   <title>Amazon Location Service - Getting Started with First Map App</title>
   <meta charset='utf-8'>
   <meta name="viewport" content="width=device-width, initial-scale=1">
   <meta name="description" content="Interactive map application using Amazon Location Service">

   <!-- Link to MapLibre CSS and JavaScript library for map rendering and visualization -->
   <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/maplibre-gl@5.x/dist/maplibre-gl.css" />
   <script src="https://cdn.jsdelivr.net/npm/maplibre-gl@5.x/dist/maplibre-gl.js"></script>
   
   <!-- Link to MapLibre Geocoder CSS and JavaScript library for place search and geocoding -->
   <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@maplibre/maplibre-gl-geocoder@1.7.0/dist/maplibre-gl-geocoder.css" />
   <script src="https://cdn.jsdelivr.net/npm/@maplibre/maplibre-gl-geocoder@1.7.0/dist/maplibre-gl-geocoder.js"></script>
   
   <!-- Link to amazon-location JavaScript library -->
   <script src="https://cdn.jsdelivr.net/npm/@aws/amazon-location-utilities-auth-helper@1"></script>
   <script src="https://cdn.jsdelivr.net/npm/@aws/amazon-location-client@1.2"></script>
   
   <!-- Link to the first Amazon Location Map App's CSS and JavaScript -->
   <script src="utils.js"></script>
   <link rel="stylesheet" href="style.css"/>
</head>

<body>
    <main role="main" aria-label="Map Container">
        <div id="map"></div>
    </main>
    <script>
        const API_KEY = "Your_API_Key";
        const AWS_REGION = "Region_where_you_created_API_Key";
        
        function initializeMap(mapStyle, colorScheme) {
            const styleUrl = `https://maps.geo.${AWS_REGION}.amazonaws.com/v2/styles/${mapStyle}/descriptor?key=${API_KEY}&color-scheme=${colorScheme}`;
        
            const map = new maplibregl.Map({
                container: 'map',                 // ID of the HTML element for the map
                style: styleUrl,                  // URL for the map style
                center: [-123.116226, 49.246292], // Initial map center [longitude, latitude]
                zoom: 10                          // Initial zoom level
            });
            map.addControl(new maplibregl.NavigationControl());    
            return map;
        }
        
        const map = initializeMap("Standard", "Light");
        
    </script>
</body>
</html>
```

### Add Places to your application
<a name="qs-add-places"></a>

In this section, we will set up add places capabilities to the application. Download the JavaScript file from GitHub, [https://github.com/aws-geospatial/amazon-location-samples-js/blob/quick_start_sample_js/quick-start/utils.js](https://github.com/aws-geospatial/amazon-location-samples-js/blob/quick_start_sample_js/quick-start/utils.js).

Before you start, your files should be in this folder structure:

```
|---FirstApp [Folder]
|-------------- index.html [File]
|-------------- style.css [File]
|-------------- utils.js [File]
```

#### Create Function to Create GeoPlaces
<a name="qs-create-geoplaces"></a>

To add search functionality, initialize the `GeoPlaces` class using `AuthHelper` and `AmazonLocationClient`. Add the following `getGeoPlaces(map)` function before the `</script>` tag in `index.html`.

```
/**
 * Gets a GeoPlaces instance for Places operations.
 */
function getGeoPlaces(map) {
    const authHelper = amazonLocationClient.withAPIKey(API_KEY, AWS_REGION);                      // Authenticate using the API key and AWS region
    const locationClient = new amazonLocationClient.GeoPlacesClient(authHelper.getClientConfig()); // Create a GeoPlaces client
    const geoPlaces = new GeoPlaces(locationClient, map);                                          // Create GeoPlaces instance
    return geoPlaces;                                                                              // Return the GeoPlaces instance
}
```

#### Create Function to Add Search Box to the Application
<a name="qs-add-searchbox"></a>

Add the following `addSearchBox(map, geoPlaces)`, `renderPopup(feature)`, and `createPopup(feature)` functions before the `</script>` tag in `index.html` to complete the search functionality setup.

```
/**
 * Adds search box to the map.
 */
function addSearchBox(map, geoPlaces) {
    const searchBox = new MaplibreGeocoder(geoPlaces, {
        maplibregl,
        showResultsWhileTyping: true,                    // Show results while typing
        debounceSearch: 300,                             // Debounce search requests
        limit: 30,                                       // Limit number of results
        popuprender: renderPopup,                        // Function to render popup
        reverseGeocode: true,                            // Enable reverse geocoding
        zoom: 14,                                        // Zoom level on result selection
        placeholder: "Search text or nearby (lat,long)"  // Placeholder text for search box.
    });
    
    // Add the search box to the map
    map.addControl(searchBox, 'top-left'); 

    // Event listener for when a search result is selected
    searchBox.on('result', async (event) => {
        const { id, result_type } = event.result;                     // Get result ID and type
        if (result_type === "Place") {                                // Check if the result is a place
            const placeResults = await geoPlaces.searchByPlaceId(id); // Fetch details for the selected place
            if (placeResults.features.length) {
                createPopup(placeResults.features[0]).addTo(map);     // Create and add popup for the place
            }
        }
    });
}

/**
 * Renders the popup content for a given feature.
 */
function renderPopup(feature) {
    return `
        <div class="popup-content">
            <span class="${feature.place_type.toLowerCase()} badge">${feature.place_type}</span><br>
            ${feature.place_name}
        </div>`;
}

/**
 * Creates a popup for a given feature and sets its position.
 */
function createPopup(feature) {
    return new maplibregl.Popup({ offset: 30 })      // Create a new popup
        .setLngLat(feature.geometry.coordinates)     // Set the popup position
        .setHTML(renderPopup(feature));              // Set the popup content
}
```

#### Add Search Box to the Application
<a name="qs-add-searchbox-to-application"></a>

Create a `GeoPlaces` object by calling `getGeoPlaces(map)` as defined in Section 3.1 and then call `addSearchBox(map, geoPlaces)` to add the search box to the application.

```
// Step 2: Add maps to application
// Step 2.1 initialize the map
const map = initializeMap("Standard","Light");
// Step 2.2 Add navigation controls to the map
map.addControl(new maplibregl.NavigationControl()); 

// Step 3: Add places feature to application        
// Step 3.1: Get GeoPlaces instance. It will be used for adding search box and map click functionality
const geoPlaces = getGeoPlaces(map);
// Step 3.2: Add search box to the map
addSearchBox(map, geoPlaces);
```

Your place search is ready to use. Open `index.html` in a browser to see it in action.

#### Add Function to Show Popup on User Click on the Map
<a name="qs-add-map-click-feature"></a>

Create a function `addMapClick(map, geoPlaces)` to display a popup when the user clicks on the map. Add this function just before the `</script>` tag.

```
/**
 * Sets up reverse geocoding on map click events.
 */
function addMapClick(map, geoPlaces) {
    map.on('click', async ({ lngLat }) => {                     // Listen for click events on the map
        const response = await geoPlaces.reverseGeocode({ query: [lngLat.lng, lngLat.lat], limit: 1, click: true }); // Perform reverse geocoding

        if (response.features.length) {                         // If there are results
            const clickMarker = new maplibregl.Marker({ color: "orange" }); // Create a marker
            const feature = response.features[0];               // Get the clicked feature
            const clickedPopup = createPopup(feature);          // Create popup for the clicked feature
            clickMarker.setLngLat(feature.geometry.coordinates) // Set marker position
                .setPopup(clickedPopup)                         // Attach popup to marker
                .addTo(map);                                    // Add marker to the map

            clickedPopup.on('close', () => clickMarker.remove()).addTo(map); // Remove marker when popup is closed
        }
    });
}
```

#### Call Function to Add Map Click Feature
<a name="qs-call-map-click-feature"></a>

To enable the map click action, call `addMapClick(map, geoPlaces)` after the line containing `addSearchBox(map, geoPlaces)`.

```
// Step 3: Add places feature to application        
// Step 3.1: Get GeoPlaces instance. It will be used for adding search box and map click functionality
const geoPlaces = getGeoPlaces(map);
// Step 3.2: Add search box to the map
addSearchBox(map, geoPlaces);
// Step 3.3: Setup map click functionality
addMapClick(map, geoPlaces);
```

#### Review Maps and Places application
<a name="qs-review-places"></a>

Congratulations\$1 Your first application is ready to use Maps and Places. Open `index.html` in a browser. Make sure `style.css` and `utils.js` are in the same folder with `index.html`. 

Your final HTML should look like this:

```
<!DOCTYPE html>
<html lang="en">
<head>

   <title>Amazon Location Service - Getting Started with First Map App</title>
    <meta charset='utf-8'>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="description" content="Interactive map application using Amazon Location Service">

    <!--Link to MapLibre CSS and JavaScript library for map rendering and visualization -->
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/maplibre-gl@5.x/dist/maplibre-gl.css" />
    <script src="https://cdn.jsdelivr.net/npm/maplibre-gl@5.x/dist/maplibre-gl.js"></script>
    
    <!--Link to MapLibre Geocoder CSS and JavaScript library for place search and geocoding -->
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@maplibre/maplibre-gl-geocoder@1.7.0/dist/maplibre-gl-geocoder.css" />
    <script src="https://cdn.jsdelivr.net/npm/@maplibre/maplibre-gl-geocoder@1.7.0/dist/maplibre-gl-geocoder.js"></script>
    
    <!--Link to amazon-location JavaScript librarie -->
    <script src="https://cdn.jsdelivr.net/npm/@aws/amazon-location-utilities-auth-helper@1"></script>
    <script src="https://cdn.jsdelivr.net/npm/@aws/amazon-location-client@1.2"></script>
    
    <!-- Link to the first Amazon Location Map App's CSS and JavaScript -->
    <script src="utils.js"></script>
    <link rel="stylesheet" href="style.css"/>
   

</head>
<body>
    <main role="main" aria-label="Map Container">
        <div id="map"></div>
    </main>
    <script>
        // Step 1: Setup API Key and AWS Region
        const API_KEY = "Your_API_Key";
        const AWS_REGION = "Region_where_you_created_API_Key";
        
        
        // Step 2: Add maps to application
        // Step 2.1 initialize the map
        const map = initializeMap("Standard","Light");
        // Step 2.2 Add navigation controls to the map
        map.addControl(new maplibregl.NavigationControl()); 

        // Step 3: Add places feature to application        
        // Step 3.1: Get GeoPlaces instance. It will be used for addion search box and map click functionality
        const geoPlaces =  getGeoPlaces(map);
        // Step 3.2: Add search box to the map
        addSearchBox(map, geoPlaces);
        // Step 3.3.: Setup map click functionality
        addMapClick(map, geoPlaces); 
                
 

        /**
         * Functions to add maps and places feature.
         */
         
         /**
         * Initializes the map with the specified style and color scheme.
         */ 
        function initializeMap(mapStyle = "Standard", colorScheme = "Dark") {
            const styleUrl = `https://maps.geo.${AWS_REGION}.amazonaws.com/v2/styles/${mapStyle}/descriptor?key=${API_KEY}&color-scheme=${colorScheme}`;
            const map = new maplibregl.Map({
                container: 'map',                   // The ID of the map container
                style: styleUrl,                    // The style URL for the map
                center: [-123.116226, 49.246292],   // Starting center coordinates
                zoom: 10,                           // Initial zoom level
                validateStyle: false                // Disable style validation
            });
            return map;                             // Return the initialized map
        }
        
        /**
         * Gets a GeoPlaces instance for Places operations.
         */
        function getGeoPlaces(map) {
            const authHelper =  amazonLocationClient.withAPIKey(API_KEY, AWS_REGION);                      // Authenticate using the API key and AWS region
            const locationClient = new amazonLocationClient.GeoPlacesClient(authHelper.getClientConfig()); // Create a GeoPlaces client
            const geoPlaces = new GeoPlaces(locationClient, map);                                          // Create GeoPlaces instance
                return geoPlaces;                                                                          // Return the GeoPlaces instance
        }
        
         /**
         * Adds search box to the map.
         */
        
        function addSearchBox(map, geoPlaces) {
            const searchBox = new MaplibreGeocoder(geoPlaces, {
                maplibregl,
                showResultsWhileTyping: true,                    // Show results while typing
                debounceSearch: 300,                             // Debounce search requests
                limit: 30,                                       // Limit number of results
                popuprender: renderPopup,                        // Function to render popup
                reverseGeocode: true,                            // Enable reverse geocoding
                zoom: 14,                                        // Zoom level on result selection
                placeholder: "Search text or nearby (lat,long)"  // Place holder text for search box.  
            });
            
            // Add the search box to the map
            map.addControl(searchBox, 'top-left'); 

            // Event listener for when a search result is selected
            searchBox.on('result', async (event) => {
                const { id, result_type } = event.result;                     // Get result ID and type
                if (result_type === "Place") {                                // Check if the result is a place
                    const placeResults = await geoPlaces.searchByPlaceId(id); // Fetch details for the selected place
                    if (placeResults.features.length) {
                        createPopup(placeResults.features[0]).addTo(map);     // Create and add popup for the place
                    }
                }
            });
        }

        /**
         * Renders the popup content for a given feature.
         */
        function renderPopup(feature) {
            return `
                <div class="popup-content">
                    <span class="${feature.place_type.toLowerCase()} badge">${feature.place_type}</span><br>
                    ${feature.place_name}
                </div>`;
        }

        /**
         * Creates a popup for a given feature and sets its position.
         */
        function createPopup(feature) {
            return new maplibregl.Popup({ offset: 30 })      // Create a new popup
                .setLngLat(feature.geometry.coordinates)     // Set the popup position
                .setHTML(renderPopup(feature));              // Set the popup content
        }
        
        /**
         * Sets up reverse geocoding on map click events.
         */
        function addMapClick(map, geoPlaces) {
            map.on('click', async ({ lngLat }) => {                     // Listen for click events on the map
                const response = await geoPlaces.reverseGeocode({ query: [lngLat.lng, lngLat.lat], limit: 1, click:true }); // Perform reverse geocoding

                if (response.features.length) {                         // If there are results
                    const clickMarker = new maplibregl.Marker({ color: "orange" }); // Create a marker
                    const feature = response.features[0];               // Get the clicked feature
                    const clickedPopup = createPopup(feature);          // Create popup for the clicked feature
                    clickMarker.setLngLat(feature.geometry.coordinates) // Set marker position
                        .setPopup(clickedPopup)                         // Attach popup to marker
                        .addTo(map);                                    // Add marker to the map

                    clickedPopup.on('close', () => clickMarker.remove()).addTo(map); // Remove marker when popup is closed
                }
            });
        }
        
    </script>
</body>
</html>
```

### Explore more
<a name="qs-whats-next"></a>

You have completed the quick start tutorial, and should have an idea of how Amazon Location Service is used to build applications. To get more out of Amazon Location, you can check out the following resources:
+ **Query suggestion details** - Consider extending the `GeoPlaces` class or using a similar approach to `ReverseGeocode` to get more details about results returned by the `Suggestion` API. 
+ **Choose the right API for your business needs** - To determine the best Amazon Location API for your requirements, check out this resource: [Choose the right API](choose-an-api.md). 
+ **Check out Amazon Location "how-to" guides** - Visit the [Amazon Location Service Developer Guide](https://docs.aws.amazon.com/location/) for tutorials and further resources. 
+ **Documentation and product information** - For complete documentation, visit the [Amazon Location Service Developer Guide](https://docs.aws.amazon.com/location/) . To learn more about the product, go to the [Amazon Location Service Product](https://aws.amazon.com/location) page. 

# Create your first Geofences and Trackers application
<a name="first-geofence-app"></a>

In this section, you'll create an application that demonstrates the key features of using the Amazon Location Geofences and Trackers. The applications demonstrate how a tracker and geofence interact using a combination of Lambda, AWS IoT, and Amazon Location features. Choose iOS or Android platform to get started. 

Before you start to build your application, follow the procedures in [Use the Amazon Location Service console to authenticate](set-up-auth.md) to grant appropriate access.

**Topics**
+ [Create an iOS application](ios-geofence-app.md)
+ [Create an Android application](android-geofence-app.md)

# Create an iOS application
<a name="ios-geofence-app"></a>

Follow these procedures to build an iOS application using Amazon Location Service.

Clone the project files from [GitHub](https://github.com/aws-geospatial/amazon-location-samples-ios/tree/main/tracking-with-geofence-notifications).

## Create Amazon Location resources for your app
<a name="qs-ios-tracking-resources"></a>

You can generate Amazon Location Service resources once your AWS account is ready. These resources will be essential for executing the provided code snippets.

**Note**  
If you haven't created an AWS account yet, please [create an AWS account](https://portal.aws.amazon.com/billing/signup#/start/email).

To begin you will need to create a Amazon Cognito Identity Pool Id, use the following procedure:

1. In the AWS console, navigate to the Amazon Cognito service and then select **Identity pools** from the left side menu and select **Create Identity pool**. 

1. Make sure **Guest Access** is checked, and press **Next** to continue.

1. Next create a new IAM role or Use an existing IAM role.

1. Enter an Identity pool name, and make sure Identity Pool has access to Amazon Location `(geo)` resources for the map and tracker you will be creating in the next procedure.

1. 

Now you need to create and style a map in the AWS Amazon Location console, use the following procedure:

1. Navigate to the [Maps section](https://console.aws.amazon.com/location/maps/home) in the Amazon Location console and select **Create Map** to preview available map styles.

1. Give the new map resource a **Name** and **Description**. Record the name you assign to the map resource, as it is used later in the tutorial.

1. When choosing a map style, consider the map data provider. Refer to section 82 of the [AWS service terms](http://aws.amazon.com/service-terms) for more details.

1.  Accept the [Amazon Location Terms and Conditions](https://aws.amazon.com/service-terms/#:~:text=82.%20Amazon%20Location%20Service), then select **Create Map**. After map has been created, you can interact with the map by zooming in, out, or panning in any direction.

To create a tracker using the Amazon Location console

1.  Open the [Amazon Location Service console](https://console.aws.amazon.com/location/).

1.  In the left navigation pane, choose **Trackers**.

1.  Choose **Create tracker**.

1.  Fill in the all the required fields.

1.  Under **Position filtering**, choose the option that best fits how you intend to use your tracker resource. If you do not set Position filtering, the default setting is TimeBased. For more information, see Trackers in this guide, and PositionFiltering in the Amazon Location Service Trackers API Reference.

1.  Choose **Create tracker** to finish.

## Create a Geofence Collection
<a name="qs-ios-tracking-geofence"></a>

When creating a geofence collection you can use either the console, API or CLI. The following procedures walk you through each option.

Create a geofence collection using the Amazon Location console:

1.  Open the Amazon Location Service console at https://console.aws.amazon.com/location/.

1.  In the left navigation pane, choose Geofence Collections.

1.  Choose Create geofence collection.

1.  Provide a name and description for the collection.

1.  Under EventBridge rule with CloudWatch as a target, you can create an optional EventBridge rule to get started reacting to geofence events. This enables Amazon Location to publish events to Amazon CloudWatch Logs.

1.  Choose Create geofence collection.

Create a geofence collection using the Amazon Location APIs:

Use the CreateGeofenceCollection operation from the Amazon Location Geofences APIs. The following example uses an API request to create a geofence collection called `GOECOLLECTION_NAME`.

```
POST /geofencing/v0/collections
Content-type: application/json
    {
        "CollectionName": "GOECOLLECTION_NAME",
        "Description": "Geofence collection 1 for shopping center",
        "Tags": { 
            "Tag1" : "Value1"
                }
    }
```

Create a geofence collection using AWS CLI commands:

Use the create-geofence-collection command. The following example uses an AWS CLI to create a geofence collection called `GOECOLLECTION_NAME`.

```
aws location \ create-geofence-collection \
    --collection-name "GOECOLLECTION_NAME" \
    --description "Shopping center geofence collection" \
    --tags Tag1=Value1                 
```

## Link a tracker to a geofence collection
<a name="qs-ios-tracking-link-geofence"></a>

To link a tracker to a geofence collection you can use either the console, API, or CLI. The following procedures walk you through each option.

Link a tracker resource to a geofence collection using the Amazon Location Service console:

1. Open the Amazon Location console.

1. In the left navigation pane, choose **Trackers**.

1. Under **Device Trackers**, select the name link of the target tracker.

1. Under **Linked Geofence Collections**, choose **Link Geofence Collection**.

1. In the **Linked Geofence Collection window**, select a geofence collection from the dropdown menu.

1. Choose **Link**.

1. After you link the tracker resource, it will be assigned an Active status.

Link a tracker resource to a geofence collection using the Amazon Location APIs:

Use the ``AsssociateTrackerConsumer operation from the Amazon Location Trackers APIs. The following example uses an API request that associates ExampleTracker with a geofence collection using its Amazon Resource Name (ARN).

```
POST /tracking/v0/trackers/ExampleTracker/consumers
Content-type: application/json
        {
           "ConsumerArn": "arn:aws:geo:us-west-2:123456789012:geofence-collection/GOECOLLECTION_NAME"
        }
```

Link a tracker resource to a geofence collection using AWS CLI commands:

Use the `associate-tracker-consumer ` command. The following example uses an AWS CLI to create a geofence collection called `GOECOLLECTION_NAME`.

```
aws location \
associate-tracker-consumer \
    --consumer-arn "arn:aws:geo:us-west-2:123456789012:geofence-collection/GOECOLLECTION_NAME" \
    --tracker-name "ExampleTracker"
```

## Use AWS Lambda with MQTT
<a name="qs-ios-tracking-lambda"></a>

Create a Lambda function:

To create a connection between AWS IoT Core and Amazon Location Service, you need an AWS Lambda function to process messages forwarded by EventBridge CloudWatch events. This function will extract any positional data, format it for Amazon Location Service, and submit it through the Amazon Location Tracker API. You can create this function through the AWS Lambda console, or you can use the AWS Command Line Interface (AWS CLI) or the AWS Lambda APIs. To create a Lambda function that publishes position updates to Amazon Location using the console:

1.  Open the AWS Lambda console at https://console.aws.amazon.com/lambda/.

1. From the left navigation, choose Functions.

1. Choose Create Function, and make sure that Author from scratch is selected.

1. Fill out the following boxes:
   + a Function name
   + for the **Runtime** option, choose Node.js 16.x.

1. Choose Create function.

1. Choose the Code tab to open the editor.

1. Overwrite the placeholder code in index.js with the following:

   ```
   const AWS = require('aws-sdk')
   const iot = new AWS.Iot();
   exports.handler =  function(event) {
                 console.log("event===>>>", JSON.stringify(event));
                 var param = {
                   endpointType: "iot:Data-ATS"
                 };
                 iot.describeEndpoint(param, function(err, data) {
                   if (err) {
                     console.log("error===>>>", err, err.stack); // an error occurred
                   } else {
                     var endp = data['endpointAddress'];
                     const iotdata = new AWS.IotData({endpoint: endp});    
                     const trackerEvent = event["detail"]["EventType"];
                     const src = event["source"];
                     const time = event["time"];
                     const gfId = event["detail"]["GeofenceId"];
                     const resources = event["resources"][0];  
                     const splitResources = resources.split(".");  
                     const geofenceCollection = splitResources[splitResources.length - 1];
                     const coordinates = event["detail"]["Position"];                               
                     const deviceId = event["detail"]["DeviceId"]; 
                     console.log("deviceId===>>>", deviceId);
                     const msg =  {
                         "trackerEventType" : trackerEvent,
                         "source" : src,
                         "eventTime" : time,
                         "geofenceId" : gfId,
                         "coordinates": coordinates, 
                         "geofenceCollection": geofenceCollection
                       };
                     const params = {
                       topic: `${deviceId}/tracker`,
                       payload: JSON.stringify(msg),
                       qos: 0
                     };
                     iotdata.publish(params, function(err, data) {
                         if (err) {
                           console.log("error===>>>", err, err.stack); // an error occurred
                         } else {
                           console.log("Ladmbda triggered===>>>", trackerEvent);  // successful response 
                         }
                     }); 
                   }
                 });
               }
   ```

1. Choose Deploy to save the updated function.

1. Choose the Configuration tab.

1. In the Triggers section, click on Add trigger.

1. Select EventBridge (CloudWatch Events) in Source field.

1. Select `Existing Rules` radio option.

1. Enter the rule name like this `AmazonLocationMonitor-GEOFENCECOLLECTION\$1NAME`.

1. Click on the Add button.

1. This will also attach `Resource-based policy statements` in permissions tab

MQTT Test Client

1. Open the [https://console.aws.amazon.com/iot/](https://console.aws.amazon.com/iot/).

1. In the left navigation pane, choose MQTT test client.

1. You'll see a section titled **MQTT test client** where you can configure your MQTT connection.

1. After configuring the necessary settings, click on the **Connect** button to establish a connection to the MQTT broker using the provided parameters.

1. Make note of the Endpoint value.

Once connected, you can subscribe to MQTT topics or publish messages to topics using the respective input fields provided in the MQTT test client interface. Next you will attach the MQTT Policy:

1.  On the left side menu, under **Manage** expand **Security** option and click on **Policies**.

1. Click on **Create Policy** button.

1. Enter a policy name.

1. On **Policy Document** select **JSON** tab.

1. Copy paste the policy shown below, but make sure to update all elements with your `REGION` and `ACCOUNT_ID`:

   ```
   {
       "Version": "2012-10-17",		 	 	 
       "Statement": [
                   {
                     "Action": [
                       "iot:Connect",
                       "iot:Publish",
                       "iot:Subscribe",
                       "iot:Receive"
                     ],
                     "Resource": [
                       "arn:aws:iot:REGION:ACCOUNT_ID:client/${cognito-identity.amazonaws.com:sub}",
                       "arn:aws:iot:REGION:ACCOUNT_ID:topic/${cognito-identity.amazonaws.com:sub}",
                       "arn:aws:iot:REGION:ACCOUNT_ID:topicfilter/${cognito-identity.amazonaws.com:sub}/",
                       "arn:aws:iot:REGION:ACCOUNT_ID:topic/${cognito-identity.amazonaws.com:sub}/tracker"
                      ],
                      "Effect": "Allow"
                    }
                  ]
   }
   ```

1. Select the **Create** button to finish.

## Set up sample app code
<a name="qs-ios-tracking-setup-sample"></a>

In order to setup the sample code you must have the following tools installed:
+ Git
+ XCode 15.3 or Later
+ iOS Simulator 16 or later

Use this procedure to set up the sample app code:

1. Clone the git repository from this URL: [https://github.com/aws-geospatial/amazon-location-samples-ios/tree/main/tracking-with-geofence-notifications](https://github.com/aws-geospatial/amazon-location-samples-ios/tree/main/tracking-with-geofence-notifications).

1. Open the `AWSLocationSampleApp.xcodeproj` project file.

1. Wait for the package resolution process.

1. **Optional**: On the project navigation menu rename `ConfigTemplate.xcconfig` to `Config.xcconfig` and fill in the following values:

   ```
   IDENTITY_POOL_ID = `YOUR_IDENTITY_POOL_ID`
   MAP_NAME = `YOUR_MAP_NAME`
   TRACKER_NAME = `YOUR_TRACKER_NAME`
   WEBSOCKET_URL = `YOUR_MQTT_TEST_CLIENT_ENDPOINT`
   GEOFENCE_ARN = `YOUR_GEOFENCE_COLLECTION_NAME`
   ```

## Use the sample app
<a name="qs-ios-tracking-usage"></a>

After setting up the sample code you can now run the app on an iOS simulator or a physical device.

1. Build and run the app.

1. The app will ask you for location and notification permissions. You need to allow them.

1. Tap on `Cognito Configuration` button.

1. If you have not filled the values in `Config.xcconfig` file you need to fill out the field with the resources values you have created previously in the configuration screen.

   ```
   IDENTITY_POOL_ID = `YOUR_IDENTITY_POOL_ID`
   MAP_NAME = `YOUR_MAP_NAME`
   TRACKER_NAME = `YOUR_TRACKER_NAME`
   WEBSOCKET_URL = `YOUR_MQTT_TEST_CLIENT_ENDPOINT`
   GEOFENCE_ARN = `YOUR_GEOFENCE_COLLECTION_NAME`
   ```

1. Save the configuration

1. You can now see the Filter options for time, distance and accuracy. Use them as per your need.

1. Go to `Tracking` tab in the app and you will see the map and `Start Tracking` button.

1. If you have installed the app on a simulator you may want to simulate location changes. This can be done in Features -> Location menu option. For example select Features -> Location -> Freeway Drive.

1. Tap on `Start Tracking` button. You should see the tracking points on the map.

1. The app is also tracking the locations in the background. So, when you move the app in the background it will ask for your permission to continue tracking in background mode.

1. You can stop the tracking by tapping on `Stop Tracking` button.

# Create an Android application
<a name="android-geofence-app"></a>

Follow these procedures to build an iOS application using Amazon Location Service.

Clone the project files from [GitHub](https://github.com/aws-geospatial/amazon-location-samples-android/tree/main/tracking-with-geofence-notifications).

## Create Amazon Location resources for your app
<a name="qs-android-tracking-resources"></a>

You can generate Amazon Location Service resources once your AWS account is ready. These resources will be essential for executing the provided code snippets.

**Note**  
If you haven't created an AWS account yet, please [create an AWS account](https://portal.aws.amazon.com/billing/signup#/start/email).

To begin you will need to create a Amazon Cognito Identity Pool Id, use the following procedure:

1. In the AWS console, navigate to the Amazon Cognito service and then select **Identity pools** from the left side menu and select **Create Identity pool**. 

1. Make sure **Guest Access** is checked, and press **Next** to continue.

1. Next create a new IAM role or Use an existing IAM role.

1. Enter an Identity pool name, and make sure Identity Pool has access to Amazon Location `(geo)`resources for the map and tracker you will be creating in the next procedure.

1. 

Now you need to create and style a map in the AWS Amazon Location console, use the following procedure:

1. Navigate to the [Maps section](https://console.aws.amazon.com/location/maps/home) in the Amazon Location console and select **Create Map** to preview available map styles.

1. Give the new map resource a **Name** and **Description**. Record the name you assign to the map resource, as it is used later in the tutorial.

1. When choosing a map style, consider the map data provider. Refer to section 82 of the [AWS service terms](http://aws.amazon.com/service-terms) for more details.

1. Accept the [Amazon Location Terms and Conditions](https://aws.amazon.com/service-terms/#:~:text=82.%20Amazon%20Location%20Service), then select **Create Map**. After map has been created, you can interact with the map by zooming in, out, or panning in any direction.

To create a tracker using the Amazon Location console

1.  Open the [Amazon Location Service console](https://console.aws.amazon.com/location/).

1. In the left navigation pane, choose **Trackers**.

1. Choose **Create tracker**.

1. Fill in the all the required fields.

1. Under **Position filtering**, choose the option that best fits how you intend to use your tracker resource. If you do not set Position filtering, the default setting is TimeBased. For more information, see Trackers in this guide, and PositionFiltering in the Amazon Location Service Trackers API Reference.

1. Choose **Create tracker** to finish.

## Create a Geofence Collection
<a name="qs-android-tracking-geofence"></a>

When creating a geofence collection you can use either the console, API or CLI. The following procedures walk you through each option.

Create a geofence collection using the Amazon Location console:

1. Open the Amazon Location Service console at https://console.aws.amazon.com/location/.

1. In the left navigation pane, choose Geofence Collections.

1. Choose Create geofence collection.

1. Provide a name and description for the collection.

1. Under EventBridge rule with CloudWatch as a target, you can create an optional EventBridge rule to get started reacting to geofence events. This enables Amazon Location to publish events to Amazon CloudWatch Logs.

1. Choose Create geofence collection.

Create a geofence collection using the Amazon Location APIs:

Use the CreateGeofenceCollection operation from the Amazon Location Geofences APIs. The following example uses an API request to create a geofence collection called `GOECOLLECTION_NAME`.

```
POST /geofencing/v0/collections
Content-type: application/json
    {
    "CollectionName": "GOECOLLECTION_NAME",
    "Description": "Geofence collection 1 for shopping center",
    "Tags": { 
        "Tag1" : "Value1"
            }
    }
```

Create a geofence collection using AWS CLI commands:

Use the create-geofence-collection command. The following example uses an AWS CLI to create a geofence collection called `GOECOLLECTION_NAME`.

```
aws location \ create-geofence-collection \
    --collection-name "GOECOLLECTION_NAME" \
    --description "Shopping center geofence collection" \
    --tags Tag1=Value1               
```

## Link a tracker to a geofence collection
<a name="qs-android-tracking-link-geofence"></a>

To link a tracker to a geofence collection you can use either the console, API, or CLI. The following procedures walk you through each option.

Link a tracker resource to a geofence collection using the Amazon Location Service console:

1. Open the Amazon Location console.

1. In the left navigation pane, choose **Trackers**.

1. Under **Device Trackers**, select the name link of the target tracker.

1. Under **Linked Geofence Collections**, choose **Link Geofence Collection**.

1. In the **Linked Geofence Collection window**, select a geofence collection from the dropdown menu.

1. Choose **Link**.

1. After you link the tracker resource, it will be assigned an Active status.

Link a tracker resource to a geofence collection using the Amazon Location APIs:

Use the ``AsssociateTrackerConsumer operation from the Amazon Location Trackers APIs. The following example uses an API request that associates ExampleTracker with a geofence collection using its Amazon Resource Name (ARN).

```
POST /tracking/v0/trackers/ExampleTracker/consumers
Content-type: application/json
    {
    "ConsumerArn": "arn:aws:geo:us-west-2:123456789012:geofence-collection/GOECOLLECTION_NAME"
    }
```

Link a tracker resource to a geofence collection using AWS CLI commands:

Use the `associate-tracker-consumer ` command. The following example uses an AWS CLI to create a geofence collection called `GOECOLLECTION_NAME`.

```
aws location \
associate-tracker-consumer \
    --consumer-arn "arn:aws:geo:us-west-2:123456789012:geofence-collection/GOECOLLECTION_NAME" \
    --tracker-name "ExampleTracker"
```

## Use AWS Lambda with MQTT
<a name="qs-android-tracking-lambda"></a>

Create a Lambda function:

To create a connection between AWS IoT Core and Amazon Location Service, you need an AWS Lambda function to process messages forwarded by EventBridge CloudWatch events. This function will extract any positional data, format it for Amazon Location Service, and submit it through the Amazon Location Tracker API. You can create this function through the AWS Lambda console, or you can use the AWS Command Line Interface (AWS CLI) or the AWS Lambda APIs. To create a Lambda function that publishes position updates to Amazon Location using the console:

1.  Open the AWS Lambda console at https://console.aws.amazon.com/lambda/.

1. From the left navigation, choose Functions.

1. Choose Create Function, and make sure that Author from scratch is selected.

1. Fill out the following boxes:
   + a Function name
   + for the **Runtime** option, choose Node.js 16.x.

1. Choose Create function.

1. Choose the Code tab to open the editor.

1. Overwrite the placeholder code in index.js with the following:

   ```
   const AWS = require('aws-sdk')
   const iot = new AWS.Iot();
   exports.handler =  function(event) {
       console.log("event===>>>", JSON.stringify(event));
       var param = {
           endpointType: "iot:Data-ATS"
           };
       iot.describeEndpoint(param, function(err, data) {
           if (err) {
               console.log("error===>>>", err, err.stack); // an error occurred
            } else {
                     var endp = data['endpointAddress'];
                     const iotdata = new AWS.IotData({endpoint: endp});    
                     const trackerEvent = event["detail"]["EventType"];
                     const src = event["source"];
                     const time = event["time"];
                     const gfId = event["detail"]["GeofenceId"];
                     const resources = event["resources"][0];  
                     const splitResources = resources.split(".");  
                     const geofenceCollection = splitResources[splitResources.length - 1];
                     const coordinates = event["detail"]["Position"];                               
                     const deviceId = event["detail"]["DeviceId"]; 
                     console.log("deviceId===>>>", deviceId);
                     const msg =  {
                         "trackerEventType" : trackerEvent,
                         "source" : src,
                         "eventTime" : time,
                         "geofenceId" : gfId,
                         "coordinates": coordinates, 
                         "geofenceCollection": geofenceCollection
                     };
       const params = {
           topic: `${deviceId}/tracker`,
           payload: JSON.stringify(msg),
           qos: 0
                };
       iotdata.publish(params, function(err, data) {
           if (err) {
               console.log("error===>>>", err, err.stack); // an error occurred
           } else {
               console.log("Ladmbda triggered===>>>", trackerEvent);  // successful response 
                  }
           }); 
          }
         });
        }
   ```

1. Choose Deploy to save the updated function.

1. Choose the Configuration tab.

1. In the Triggers section, click on Add trigger.

1. Select EventBridge (CloudWatch Events) in Source field.

1. Select `Existing Rules` radio option.

1. Enter the rule name like this `AmazonLocationMonitor-GEOFENCECOLLECTION\$1NAME`.

1. Click on the Add button.

1. This will also attach `Resource-based policy statements` in permissions tab

MQTT Test Client

1. Open the [https://console.aws.amazon.com/iot/](https://console.aws.amazon.com/iot/).

1. In the left navigation pane, choose MQTT test client.

1. You'll see a section titled **MQTT test client** where you can configure your MQTT connection.

1. After configuring the necessary settings, click on the **Connect** button to establish a connection to the MQTT broker using the provided parameters.

1. Note down Endpoint value.

Once connected, you can subscribe to MQTT topics or publish messages to topics using the respective input fields provided in the MQTT test client interface. Next you will attach the MQTT Policy:

1.  On the left side menu, under **Manage** expand **Security** option and click on **Policies**.

1. Click on **Create Policy** button.

1. Enter a policy name.

1. On **Policy Document** select **JSON** tab.

1. Copy paste the policy shown below, but make sure to update all elements with your `REGION` and `ACCOUNT_ID`:

   ```
   {
    "Version": "2012-10-17",		 	 	 
    "Statement": [
                   {
                     "Action": [
                       "iot:Connect",
                       "iot:Publish",
                       "iot:Subscribe",
                       "iot:Receive"
                        ],
                     "Resource": [
                       "arn:aws:iot:REGION:ACCOUNT_ID:client/${cognito-identity.amazonaws.com:sub}",
                       "arn:aws:iot:REGION:ACCOUNT_ID:topic/${cognito-identity.amazonaws.com:sub}",
                       "arn:aws:iot:REGION:ACCOUNT_ID:topicfilter/${cognito-identity.amazonaws.com:sub}/",
                       "arn:aws:iot:REGION:ACCOUNT_ID:topic/${cognito-identity.amazonaws.com:sub}/tracker"
                       ],
                     "Effect": "Allow"
                   }
                 ]
   }
   ```
**Note**  
Record the policy name and topic name for use in the next procedure.

1. Select the **Create** button to finish.

After completing the previous procedure, you will now update the permissions for the guest role as follows:

1. Navigate to Amazon Cognito and open your identity pool. Then, proceed to user access and select the guest role.

1. Click on permission policies to enable editing.

   ```
   {
       'Version': '2012-10-17		 	 	 ',
       'Statement': [
           {
               'Action': [
                   'geo:GetMap*',
                   'geo:BatchUpdateDevicePosition',
                   'geo:BatchEvaluateGeofences',
                   'iot:Subscribe',
                   'iot:Publish',
                   'iot:Connect',
                   'iot:Receive',
                   'iot:AttachPrincipalPolicy',
                   'iot:AttachPolicy',
                   'iot:DetachPrincipalPolicy',
                   'iot:DetachPolicy'
               ],
               'Resource': [
                   'arn:aws:geo:us-east-1:{USER_ID}:map/{MAP_NAME}',
                   'arn:aws:geo:us-east-1:{USER_ID}:tracker/{TRACKER_NAME}',
                   'arn:aws:geo:us-east-1:{USER_ID}:geofence-collection/{GEOFENCE_COLLECTION_NAME}',
                   'arn:aws:iot:us-east-1:{USER_ID}:client/${cognito-identity.amazonaws.com:sub}',
                   'arn:aws:iot:us-east-1:{USER_ID}:topic/${cognito-identity.amazonaws.com:sub}',
                   'arn:aws:iot:us-east-1:{USER_ID}:topicfilter/${cognito-identity.amazonaws.com:sub}/*',
                   'arn:aws:iot:us-east-1:{USER_ID}:topic/${cognito-identity.amazonaws.com:sub}/tracker'
               ],
               'Effect': 'Allow'
           },
           {
               'Condition': {
                   'StringEquals': {
                       'cognito-identity.amazonaws.com:sub': '${cognito-identity.amazonaws.com:sub}'
                   }
               },
               'Action': [
                   'iot:AttachPolicy',
                   'iot:DetachPolicy',
                   'iot:AttachPrincipalPolicy',
                   'iot:DetachPrincipalPolicy'
               ],
               'Resource': [
                   '*'
               ],
               'Effect': 'Allow'
           }
       ]
   }
   ```

1. With the above policy changes, all necessary AWS resources are now configured appropriately for the application.

## Set up the sample app code
<a name="qs-android-tracking-sample-app-code"></a>



1. Open Android Studio and select **New** and then **Project from Version Control**.

1. Navigate to the **File** menu in Android Studio’s top left corner.

1. Select “New” from the dropdown menu.

1. Choose “Project from Version Control”.

1. Enter Repository URL In the dialogue box that appears, find the field marked “URL”.

1. Copy and paste the following URL for the sample app into this field:[https://github.com/aws-geospatial/amazon-location-samples-android.git](https://github.com/aws-geospatial/amazon-location-samples-android.git)

1. Decide on the directory where you want to clone the repository. Use either the default directory or opt for a custom location.

1. After setting the repository URL and directory preferences, hit the “Clone” button. Android Studio will proceed to clone the repository to your specified location.

1. You have now cloned the application to your machine and can begin using it.

## Use the sample app
<a name="qs-android-tracking-use"></a>

To use the sample follow these procedures:
+ **Create a `custom.properties`**:

  To configure your `custom.properties` file, follow these steps:

  1. Open your preferred text editor or IDE.

  1. Create a new file.

  1. Save the file with the name `custom.properties`.

  1. Update the `custom.properties` with the following code sample, and replace the `MQTT_END_POINT`, `POLICY_NAME`, `GEOFENCE_COLLECTION_NAME`, and `TOPIC_TRACKER` with actual values:

     ```
     MQTT_END_POINT=xxxxxxxxxxxxx-xxx.xxx.us-east-1.amazonaws.com
     POLICY_NAME=xxxxxxxxx
     GEOFENCE_COLLECTION_NAME=xxxxxxxxxxxxxxxxx
     TOPIC_TRACKER=xxxxxxxxxx
     ```

  1. Clean and Rebuild the project. After this, you can run the project.
+ **Sign In**:

  To sign in to the application, follow the below steps:

  1. Press the **Sign In** button.

  1. Provide an **Identity Pool Id**, **Tracker name**, and a **Map name**.

  1. Press **Sign In** again to finish.
+ **Manage Filters**:

  Open the configuration screen, and perform the following:

  1. Toggle filters on/off using the switch UI.

  1. Update Time and Distance filters when needed.
+ **Tracking Operations:**

  Open the tracking screen and perform the following:
  + You can start and stop tracking in foreground, background, or in battery-saver mode by pressing respective buttons.