

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

The most efficient way to get started with Amazon Location Service is to use the [Amazon Location console](https://console.aws.amazon.com/location/home). You can create and manage your resources and try the Amazon Location functionality using [the Explore page](https://console.aws.amazon.com/location/explore/home).

**Note**  
To use the Amazon Location Service console, or following the rest of this tutorial, requires that you first complete the [Prerequisites for using Amazon Location Service](gs-prereqs.md), including creating an AWS account, and allowing access to Amazon Location.

To begin learning about the Amazon Location APIs, use the following tutorial to create a simple application that displays an interactive map and uses search functionality. There are three versions of the tutorial: one shows you how to create a simple webpage using JavaScript, the second shows the same for an Android application using Kotlin, and the third shows the same for an iOS application using Swift.

**Topics**
+ [Create a web app to use Amazon Location Service](qs-web.md)
+ [Create an Android app to use Amazon Location Service](qs-android.md)
+ [Create an iOS app for Amazon Location Service](qs-ios.md)

# Create a web app to use Amazon Location Service
<a name="qs-web"></a>

 In this section, you will create a static webpage with a map and the ability to search at a location. First you will create your Amazon Location resources and create an API key for your application.

**Topics**
+ [Create Amazon Location resources for your app](qs-create-resources-web.md)
+ [Set up authentication for your Amazon Location application](qs-setup-authentication-web.md)
+ [Create the HTML for your Amazon Location application](qs-create-html.md)
+ [Add an Amazon Location interactive map to your application](qs-add-map.md)
+ [Add Amazon Location search to your application](qs-add-search.md)
+ [Review the final Amazon Location application](qs-final-review.md)

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

If you do not already have them, you must create the Amazon Location resources that your application will use. Here, you create a map resource to display maps in your application, and a place index to search for locations on the map.

**To add location resources to your application**

1. Choose the map style that you want to use.

   1. In the Amazon Location console, on the [Maps](https://console.aws.amazon.com/location/maps/home) page, choose **Create map** to preview map styles.

   1. Add a **Name** and **Description** for the new map resource. Make a note of the name that you use for the map resource. You will need it when creating your script file later in the tutorial.

   1. Choose a map.
**Note**  
Choosing a map style also chooses which map data provider that you will use. If your application is tracking or routing assets that you use in your business, such as delivery vehicles or employees, you may only use HERE as your geolocation provider. For more information, see section 82 of the [AWS service terms](https://aws.amazon.com/service-terms). 

   1. Agree to the **Amazon Location Terms and Conditions**, then choose **Create map**. You can interact with the map that you've chosen: zoom in, zoom out, or pan in any direction.

   1. Make a note of the Amazon Resource Name (ARN) that is shown for your new map resource. You'll use it to create the correct authentication later in this tutorial.

1. Choose the place index that you want to use.

   1. In the Amazon Location console on the [https://console.aws.amazon.com/location/places/home](https://console.aws.amazon.com/location/places/home) page, choose **Create place index**.

   1. Add a **Name** and **Description** for the new place index resource. Make a note of the name that you use for the place index resource. You will need it when creating your script file later in the tutorial.

   1. Choose a data provider.
**Note**  
In most cases, choose the data provider that matches the map provider that you already chose. This helps to ensure that the searches will match the maps.  
If your application is tracking or routing assets that you use in your business, such as delivery vehicles or employees, you may only use HERE as your geolocation provider. For more information, see section 82 of the [AWS service terms](https://aws.amazon.com/service-terms). 

   1. Choose the **Data storage option**. For this tutorial, the results are not stored, so you can choose ** No, single use only**.

   1. Agree to the **Amazon Location Terms and Conditions**, then choose **Create place index**.

   1. Make a note of the ARN that is shown for your new place index resource. You'll use it to create the correct authentication in the next section of this tutorial.

# Set up authentication for your Amazon Location application
<a name="qs-setup-authentication-web"></a>

The application that you create in this tutorial has anonymous usage, meaning that your users are not required to sign into AWS to use the application. However, by default, the Amazon Location Service APIs require authentication to use. You can use either Amazon Cognito or API keys to provide authentication and authorization for anonymous users. In this tutorial, you will create API keys for use in the sample application.

**Note**  
For more information about using API keys or Amazon Cognito with Amazon Location Service, see [Grant access to Amazon Location Service](how-to-access.md).



**To set up authentication for your application**

1. Go to the [Amazon Location console](https://console.aws.amazon.com/location), and choose **API keys** from the left menu.

1. Choose **Create API key**.
**Important**  
The API key that you create must be in the same AWS account and AWS Region as the Amazon Location Service resources that you created in the previous section.

1. One the **Create API key** page, fill in the following information.
   + **Name** – A name for your API key, such as `MyWebAppKey`.
   + **Resources** – Choose the Amazon Location Map and Place index resources that you created in the previous section. You can add more than one resource by choosing **Add resource**. This will allow the API key to be used with those resources.
   + **Actions** – Specify the actions you want to authorize with this API key. You must select at least **geo:GetMap\$1** and **geo:SearchPlaceIndexfForPosition** so that the tutorial will work as expected.
   + You can optionally add a **Description**, **Expiration time**, or **Tags** to your API key. You can also add a referrer (such as `*.example.com`), to limit the key to only being used from a particular domain. This will mean that the tutorial will only work from that domain.
**Note**  
It is recommended 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. Choose **Show API key**, and copy the key value for use later in the tutorial. It will be in the form `v1.public.a1b2c3d4...`.
**Important**  
You will need this key when writing the code for your application later in this tutorial.

# Create the HTML for your Amazon Location application
<a name="qs-create-html"></a>

In this tutorial, you will create a static HTML page that embeds a map, and allows the user to find what's at a location on the map. The app will consist of three files: an HTML file and CSS file for the webpage, and a JavaScript (.js) file for the code that creates the map and responds to the user's interactions and map events.

First, let's create the HTML and CSS framework that will be used for the application. This will be a simple page with a `<div>` element to hold the map container and a <pre> element to show the JSON responses to your queries.

**To create the HTML for your quick start application**

1. Create a new file called `quickstart.html`.

1. Edit the file in the text editor or environment of your choice. Add the following HTML to the file.

   ```
   <!DOCTYPE html>
   <html>
     <head>
       <meta charset="utf-8">
       <title>Quick start tutorial</title>
   
       <!-- Styles -->
       <link href="main.css" rel="stylesheet" />
     </head>
     
     <body>
       <header>
         <h1>Quick start tutorial</h1>
       </header>
       <main>
         <div id="map"></div>
         <aside>
           <h2>JSON Response</h2>
           <pre id="response"></pre>
         </aside>
       </main>
       <footer>This is a simple Amazon Location Service app. Pan and zoom. Click to see details about entities close to a point.</footer>
       
     </body>
   </html>
   ```

   This HTML has a pointer to the CSS file that you will create in the next step, some placeholder elements for the application, and some explanatory text.

   There are two placeholder elements that you will use later in this tutorial. The first is the `<div id="map>` element, which will hold the map control. The second is the `<pre id="response">` element, which will show the results of searching on the map.

1. Save your file.

Now add the CSS for the webpage. This will set the style of the text and placeholder elements for the application.

**To create the CSS for your quick start application**

1. Create a new file called `main.css`, in the same folder as the quickstart.html file created in the previous procedure.

1. Edit the file in whatever editor that you want to use. Add the following text to the file.

   ```
   * {
     box-sizing: border-box;
     font-family: Arial, Helvetica, sans-serif;
   }
   
   body {
     margin: 0;
   }
   
   header {
     background: #000000;
     padding: 0.5rem;
   }
   
   h1 {
     margin: 0;
     text-align: center;
     font-size: 1.5rem;
     color: #ffffff;
   }
   
   main {
     display: flex;
     min-height: calc(100vh - 94px);
   }
   
   #map {
     flex: 1;
   }
   
   aside {
     overflow-y: auto;
     flex: 0 0 30%;
     max-height: calc(100vh - 94px);
     box-shadow: 0 1px 1px 0 #001c244d, 1px 1px 1px 0 #001c2426, -1px 1px 1px 0 #001c2426;
     background: #f9f9f9;
     padding: 1rem;
   }
   
   h2 {
     margin: 0;
   }
   
   pre {
     white-space: pre-wrap;
     font-family: monospace;
     color: #16191f;
   }
   
   footer {
     background: #000000;
     padding: 1rem;
     color: #ffffff;
   }
   ```

   This sets the map to fill the space not used by anything else, sets the area for our responses to take up 30% of the width of the app, and sets color and styles for the title and explanatory text.

1. Save the file.

1. You can now view the `quickstart.html` file in a browser to see the layout of the application.  
![\[alt text not found\]](http://docs.aws.amazon.com/location/previous/developerguide/images/quickstart-blank.png)

Next, you will add the map control to the application.

# Add an Amazon Location interactive map to your application
<a name="qs-add-map"></a>

Now that you have a framework and a div placeholder, you can add the map control to your application. This tutorial uses [MapLibre GL JS](https://maplibre.org/maplibre-gl-js-docs/api/) as a map control, getting data from Amazon Location Service. You will also use the [JavaScript Authentication helper](loc-sdk-auth.md) to facilitate signing of calls to the Amazon Location APIs with your API key.

**To add an interactive map to your application**

1. Open the `quickstart.html` file that you created in the previous section.

1. Add references to the needed libraries, and the script file that you will create. The changes you need to make are shown in **green**.

   ```
   <!DOCTYPE html>
   <html>
     <head>
       <meta charset="utf-8">
       <title>Quick start tutorial</title>
   
       <!-- Styles -->
       <link href="https://unpkg.com/maplibre-gl@3.x/dist/maplibre-gl.css" rel="stylesheet" />
       <link href="main.css" rel="stylesheet" />
     </head>
     
     <body>
       ...
       <footer>This is a simple Amazon Location Service app. Pan and zoom. Click to see details about entities close to a point.</footer>
       
       <!-- JavaScript dependencies -->
       <script src="https://unpkg.com/maplibre-gl@3.x/dist/maplibre-gl.js"></script>
       <script src="https://unpkg.com/@aws/amazon-location-client@1.x/dist/amazonLocationClient.js"></script>
       <script src="https://unpkg.com/@aws/amazon-location-utilities-auth-helper@1.x/dist/amazonLocationAuthHelper.js"></script>
       
       <!-- JavaScript for the app -->
       <script src="main.js"></script>
     </body>
   </html>
   ```

   This adds the following dependencies to your app:
   + **MapLibre GL JS**. This library and stylesheet include a map control that displays map tiles and includes interactivity, such as pan and zoom. The control also allows extensions, such as drawing your own features on the map.
   + **Amazon Location client**. This provides interfaces for the Amazon Location functionality needed to get map data, and to search for places on the map. The Amazon Location client is based on the AWS SDK for JavaScript v3.
   + **Amazon Location Authentication Helper**. This provides helpful functions for authenticating Amazon Location Service with API keys or Amazon Cognito.

   This step also adds a reference to `main.js`, which you will create next.

1. Save the `quickstart.html` file.

1. Create a new file called `main.js` in the same folder as your HTML and CSS files, and open it for editing.

1. Add the following script to your file. The text in *red* should be replaced with the API key value, map resource name, and place resource name that you created earlier, as well as the region identifier for your region (such as `us-east-1`).

   ```
   // Amazon Location Service resource names:
   const mapName = "explore.map";
   const placesName = "explore.place";
   const region = "your_region";
   const apiKey = "v1.public.a1b2c3d4...
   
   // Initialize a map
   async function initializeMap() {
     const mlglMap = new maplibregl.Map({
       container: "map", // HTML element ID of map element
       center: [-77.03674, 38.891602], // Initial map centerpoint
       zoom: 16, // Initial map zoom
       style: `https://maps.geo.${region}.amazonaws.com/maps/v0/maps/${mapName}/style-descriptor?key=${apiKey}`, // Defines the appearance of the map and authenticates using an API key
     });
   
     // Add navigation control to the top left of the map
     mlglMap.addControl(new maplibregl.NavigationControl(), "top-left");
     
     return mlglMap;
   }
   
   async function main() {
     // Initialize map and Amazon Location SDK client:
     const map = await initializeMap();
   }
   
   main();
   ```

   This code sets up Amazon Location resources, then configures and initializes a MapLibre GL JS map control and places it in your `<div>` element with the id `map`.

   The `initializeMap()` function is important to understand. It creates a new MapLibre map control (called `mlglMap` locally, but called `map` in the rest of the code) that is used to render the map in your application.

   ```
     // Initialize the map
     const mlglMap = new maplibregl.Map({
       container: "map", // HTML element ID of map element
       center: [-77.03674, 38.891602], // Initial map centerpoint
       zoom: 16, // Initial map zoom
       style: `https://maps.geo.${region}.amazonaws.com/maps/v0/maps/${mapName}/style-descriptor?key=${apiKey}`, // Defines the appearance of the map and authenticates using an API key
     });
   ```

   When you create a new MapLibre map control, the parameters that you pass indicate the initial state of the map control. Here, we set the following parameters.
   + HTML container, which uses the map div element in our HTML.
   + The initial center of the map to a point in Washington, DC.
   + The zoom level to 16 (zoomed into a neighborhood or block level).
   + The style to use for the map, which gives MapLibre a URL to use to get the map tiles and other information to render the map. Notice that this URL includes your API key for authentication.

1. Save your JavaScript file, and open it with a browser. You now have a map on your page, where you can use pan and zoom actions. 
**Note**  
You can use this app to see how the MapLibre map control behaves. You can try using Ctrl or Shift while using a dragging operation, to see other ways to interact with the map. All of this functionality is customizable.  
![\[alt text not found\]](http://docs.aws.amazon.com/location/previous/developerguide/images/quickstart-map.png)

Your app is nearly complete. In the next section, you will handle choosing a location on the map, and show the address of the location chosen. You will also show the resulting JSON on the page, to see the full results.

# Add Amazon Location search to your application
<a name="qs-add-search"></a>

The last step for your application is to add searching on the map. In this case, you will add a reverse geocoding search, where you find the items at a location.

**Note**  
Amazon Location Service also provides the ability to search by name or address to find the locations of places on the map.

**To add search functionality to your application**

1. Open the `main.js` file that you created in the previous section.

1. Modify the `main` function, as shown. The changes you need to make are shown in **green**.

   ```
   async function main() {
     // Create an authentication helper instance using an API key
     const authHelper = await amazonLocationAuthHelper.withAPIKey(apiKey);
   
   
     // Initialize map and Amazon Location SDK client:
     const map = await initializeMap();
   
     const client = new amazonLocationClient.LocationClient({
       region,
       ...authHelper.getLocationClientConfig(), // Provides configuration required to make requests to Amazon Location
     });
   
   
     // On mouse click, display marker and get results:
     map.on("click", async function (e) {
       // Set up parameters for search call
       let params = {
         IndexName: placesName,
         Position: [e.lngLat.lng, e.lngLat.lat],
         Language: "en",
         MaxResults: "5",
       };
   
       // Set up command to search for results around clicked point
       const searchCommand = new amazonLocationClient.SearchPlaceIndexForPositionCommand(params);
   
       try {
         // Make request to search for results around clicked point
         const data = await client.send(searchCommand);
   
         // Write JSON response data to HTML
         document.querySelector("#response").textContent = JSON.stringify(data, undefined, 2);
   
         // Display place label in an alert box
         alert(data.Results[0].Place.Label);
       } catch (error) {
         // Write JSON response error to HTML
         document.querySelector("#response").textContent = JSON.stringify(error, undefined, 2);
   
         // Display error in an alert box
         alert("There was an error searching.");
       }
     });
   }
   ```

   This code starts by setting up the Amazon Location authentication helper to use your API key.

   ```
   const authHelper = await amazonLocationAuthHelper.withAPIKey(apiKey);
   ```

   Then it uses that authentication helper, and the region you are using to create a new Amazon Location client.

   ```
   const client = new amazonLocationClient.LocationClient({
       region,
       ...authHelper.getLocationClientConfig(),
     });
   ```

   Next, the code responds to the user choosing a spot on the map control. It does this by catching a MapLibre provided event for `click`.

   ```
   map.on("click", async function(e) {
       ...
     });
   ```

   The MapLibre `click` event provides parameters that include the latitude and longitude that the user chose (`e.lngLat`). Within the `click` event, the code creates the `searchPlaceIndexForPositionCommand` to find the entities at the given latitude and longitude.

   ```
       // Set up parameters for search call
       let params = {
         IndexName: placesName,
         Position: [e.lngLat.lng, e.lngLat.lat],
         Language: "en",
         MaxResults: "5"
       };
   
       // Set up command to search for results around clicked point
       const searchCommand = new amazonLocationClient.SearchPlaceIndexForPositionCommand(params);
   
       try {
         // Make request to search for results around clicked point
         const data = await client.send(searchCommand);
         ...
       });
   ```

   Here, the `IndexName` is the name of the Place Index resource that you created earlier, the `Position` is the latitude and longitude to search for, `Language` is the preferred language for results, and `MaxResults` tells Amazon Location to return only a maximum of five results.

   The remaining code checks for an error, and then displays the results of the search in the `<pre>` element called `response`, and shows the top result in an alert box.

1. (Optional) If you save and open the `quickstart.html` file in a browser now, choosing a location on the map will show you the name or address of the place that you chose.

1. The final step in the application is to use the MapLibre functionality to add a marker on the spot that the user selected. Modify the `main` function as follows. The changes you need to make are shown in **green**.

   ```
   async function main() {
     // Create an authentication helper instance using an API key
     const authHelper = await amazonLocationAuthHelper.withAPIKey(apiKey);
   
     // Initialize map and Amazon Location SDK client
     const map = await initializeMap();
     const client = new amazonLocationClient.LocationClient({
       region,
       ...authHelper.getLocationClientConfig(), // Provides configuration required to make requests to Amazon Location
     });
   
     // Variable to hold marker that will be rendered on click
     let marker;
   
     // On mouse click, display marker and get results:
     map.on("click", async function (e) {
       // Remove any existing marker
       if (marker) {
         marker.remove();
       }
   
       // Render a marker on clicked point
       marker = new maplibregl.Marker().setLngLat([e.lngLat.lng, e.lngLat.lat]).addTo(map);
   
       // Set up parameters for search call
       let params = {
         IndexName: placesName,
         Position: [e.lngLat.lng, e.lngLat.lat],
         Language: "en",
         MaxResults: "5",
       };
   
       // Set up command to search for results around clicked point
       const searchCommand = new amazonLocationClient.SearchPlaceIndexForPositionCommand(params);
   
   ...
   ```

   This code declares a `marker` variable, that is populated each time the user selects a location, showing where they selected. The marker is automatically rendered by the map control, once it's added to the map with `.addTo(map);`. The code also checks for a previous marker, and removes it, so that there is only 1 marker on the screen at a time.

1. Save the `main.js` file, and open the `quickstart.html` file in a browser. You can pan and zoom on the map, as before, but now if you choose a location, you will see details about the location that you chose.  
![\[alt text not found\]](http://docs.aws.amazon.com/location/previous/developerguide/images/quickstart-search.png)

Your quick start application is complete. This tutorial has shown you how to create a static HTML application that:
+ Creates a map that users can interact with.
+ Handles a map event (`click`).
+ Calls an Amazon Location Service API, specifically to search the map at a location, using `searchPlaceIndexForPosition`.
+ Uses the MapLibre map control to add a marker.

# Review the final Amazon Location application
<a name="qs-final-review"></a>

The final source code for this application is included in this section. You can also find the final project [on GitHub](https://github.com/aws-geospatial/amazon-location-samples-js/tree/main/quick-start-using-api-keys).

You can also find a version of the application that uses Amazon Cognito instead of API keys [on GitHub](https://github.com/aws-geospatial/amazon-location-samples-js/tree/main/quick-start-using-cognito).

------
#### [ Overview ]

Select each tab to view the final source code of the files in this quick start tutorial.

The files are:
+ **quickstart.html** — the framework for your application, including the HTML element holders for the map and search results.
+ **main.css** — the stylesheet for the application.
+ **main.js** — the script for your application that authenticates the user, creates the map, and searches on a `click` event. 

------
#### [ quickstart.html ]

The HTML framework for the quick start application.

```
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Quick start tutorial</title>

    <!-- Styles -->
    <link href="https://unpkg.com/maplibre-gl@3.x/dist/maplibre-gl.css" rel="stylesheet" />
    <link href="main.css" rel="stylesheet" />
  </head>
  
  <body>
    ...
    <footer>This is a simple Amazon Location Service app. Pan and zoom. Click to see details about entities close to a point.</footer>
    
    <!-- JavaScript dependencies -->
    <script src="https://unpkg.com/maplibre-gl@3.x/dist/maplibre-gl.js"></script>
    <script src="https://unpkg.com/@aws/amazon-location-client@1.x/dist/amazonLocationClient.js"></script>
    <script src="https://unpkg.com/@aws/amazon-location-utilities-auth-helper@1.x/dist/amazonLocationAuthHelper.js"></script>
    
    <!-- JavaScript for the app -->
    <script src="main.js"></script>
  </body>
</html>
```

------
#### [ main.css ]

The stylesheet for the quick start application.

```
* {
  box-sizing: border-box;
  font-family: Arial, Helvetica, sans-serif;
}

body {
  margin: 0;
}

header {
  background: #000000;
  padding: 0.5rem;
}

h1 {
  margin: 0;
  text-align: center;
  font-size: 1.5rem;
  color: #ffffff;
}

main {
  display: flex;
  min-height: calc(100vh - 94px);
}

#map {
  flex: 1;
}

aside {
  overflow-y: auto;
  flex: 0 0 30%;
  max-height: calc(100vh - 94px);
  box-shadow: 0 1px 1px 0 #001c244d, 1px 1px 1px 0 #001c2426, -1px 1px 1px 0 #001c2426;
  background: #f9f9f9;
  padding: 1rem;
}

h2 {
  margin: 0;
}

pre {
  white-space: pre-wrap;
  font-family: monospace;
  color: #16191f;
}

footer {
  background: #000000;
  padding: 1rem;
  color: #ffffff;
}
```

------
#### [ main.js ]

The code for the quick start application. The text in *red* should be replaced with the appropriate Amazon Location object names.

```
// Amazon Location Service resource names:
const mapName = "explore.map";
const placesName = "explore.place";
const region = "your_region";
const apiKey = "v1.public.a1b2c3d4...

// Initialize a map
async function initializeMap() {
  // Initialize the map
  const mlglMap = new maplibregl.Map({
    container: "map", // HTML element ID of map element
    center: [-77.03674, 38.891602], // Initial map centerpoint
    zoom: 16, // Initial map zoom
    style: `https://maps.geo.${region}.amazonaws.com/maps/v0/maps/${mapName}/style-descriptor?key=${apiKey}`, // Defines the appearance of the map and authenticates using an API key
  });

  // Add navigation control to the top left of the map
  mlglMap.addControl(new maplibregl.NavigationControl(), "top-left");

  return mlglMap;
}

async function main() {
  // Create an authentication helper instance using an API key
  const authHelper = await amazonLocationAuthHelper.withAPIKey(apiKey);

  // Initialize map and Amazon Location SDK client
  const map = await initializeMap();
  const client = new amazonLocationClient.LocationClient({
    region,
    ...authHelper.getLocationClientConfig(), // Provides configuration required to make requests to Amazon Location
  });

  // Variable to hold marker that will be rendered on click
  let marker;

  // On mouse click, display marker and get results:
  map.on("click", async function (e) {
    // Remove any existing marker
    if (marker) {
      marker.remove();
    }

    // Render a marker on clicked point
    marker = new maplibregl.Marker().setLngLat([e.lngLat.lng, e.lngLat.lat]).addTo(map);

    // Set up parameters for search call
    let params = {
      IndexName: placesName,
      Position: [e.lngLat.lng, e.lngLat.lat],
      Language: "en",
      MaxResults: "5",
    };

    // Set up command to search for results around clicked point
    const searchCommand = new amazonLocationClient.SearchPlaceIndexForPositionCommand(params);

    try {
      // Make request to search for results around clicked point
      const data = await client.send(searchCommand);

      // Write JSON response data to HTML
      document.querySelector("#response").textContent = JSON.stringify(data, undefined, 2);

      // Display place label in an alert box
      alert(data.Results[0].Place.Label);
    } catch (error) {
      // Write JSON response error to HTML
      document.querySelector("#response").textContent = JSON.stringify(error, undefined, 2);

      // Display error in an alert box
      alert("There was an error searching.");
    }
  });
}

main();
```

------

## What's next
<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:
+ Dive deeper into the [concepts of Amazon Location Service](how-it-works.md)
+ Get more information about [how to use Amazon Location features and functionality](using-amazon-location.md)
+ See how to expand on this sample and build more complex applications by looking at [code examples using Amazon Location](samples.md)

# Create an Android app to use Amazon Location Service
<a name="qs-android"></a>

In this section, you will create an Android application with a map, the ability to search at a location and tracking in the foreground. First, you will create your Amazon Location resources, an Amazon Cognito identity and an API key for your application.

**Topics**
+ [Create Amazon Location resources for your app](qs-create-resources-android.md)
+ [Set up authentication for your Amazon Location application](qs-setup-authentication-android.md)
+ [Create the base Android application to use Amazon Location](qs-create-app-android.md)
+ [Add an Amazon Location interactive map to your application](qs-add-map-android.md)
+ [Add Amazon Location reverse geocoding search to your application](qs-add-search-android.md)
+ [Add Amazon Location tracking to your application](qs-add-tracking-android.md)

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

If you do not already have them, you must create the Amazon Location resources that your application will use. Here, you create a map resource to display maps in your application, a place index to search for locations on the map, and a tracker to track an object across the map.

**To add location resources to your application**

1. Choose the map style that you want to use.

   1. In the Amazon Location console, on the [Maps](https://console.aws.amazon.com/location/maps/home) page, choose **Create map** to preview map styles.

   1. Add a **Name** and **Description** for the new map resource. Make a note of the name that you use for the map resource. You will need it when creating your script file later in the tutorial.

   1. We recommend you choose the HERE map style for your map.
**Note**  
Choosing a map style also chooses which map data provider that you will use. If your application is tracking or routing assets that you use in your business, such as delivery vehicles or employees, you may only use HERE as your geolocation provider. For more information, see section 82 of the [AWS service terms](https://aws.amazon.com/service-terms). 

   1. Agree to the **Amazon Location Terms and Conditions**, then choose **Create map**. You can interact with the map that you've chosen: zoom in, zoom out, or pan in any direction.

   1. Make a note of the Amazon Resource Name (ARN) that is shown for your new map resource. You'll use it to create the correct authentication later in this tutorial.

1. Choose the place index that you want to use.

   1. In the Amazon Location console on the [https://console.aws.amazon.com/location/places/home](https://console.aws.amazon.com/location/places/home) page, choose **Create place index**.

   1. Add a **Name** and **Description** for the new place index resource. Make a note of the name that you use for the place index resource. You will need it when creating your script file later in the tutorial.

   1. Choose a data provider.
**Note**  
In most cases, choose the data provider that matches the map provider that you already chose. This helps to ensure that the searches will match the maps.  
If your application is tracking or routing assets that you use in your business, such as delivery vehicles or employees, you may only use HERE as your geolocation provider. For more information, see section 82 of the [AWS service terms](https://aws.amazon.com/service-terms). 

   1. Choose the **Data storage option**. For this tutorial, the results are not stored, so you can choose ** No, single use only**.

   1. Agree to the **Amazon Location Terms and Conditions**, then choose **Create place index**.

   1. Make a note of the ARN that is shown for your new place index resource. You'll use it to create the correct authentication in the next section of this tutorial.

1. 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**, we recommend you use the default setting: **TimeBased**.

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

# Set up authentication for your Amazon Location application
<a name="qs-setup-authentication-android"></a>

The application that you create in this tutorial has anonymous usage, meaning that your users are not required to sign into AWS to use the application. However, the Amazon Location Service APIs require authentication to use. You can use either API keys or Amazon Cognito to provide authentication and authorization for anonymous users. This tutorial will use Amazon Cognito and API keys to authenticate your application.

**Note**  
For more information about using Amazon Cognito or API keys with Amazon Location Service, see [Grant access to Amazon Location Service](how-to-access.md).

The following tutorials show you how to set up authentication for the map, the place index, and tracker you created in as well setting up permissions for Amazon Location.

**Set up authentication**

1. Navigate to the [Amazon Location console](https://console.aws.amazon.com/location/home/) and select **API keys** from the left-hand menu.

1. Click on 'Create API key'. Remember that the API key must be in the same AWS account and region as the previously created Amazon Location Service resources.

1. Fill in the required details on the 'Create API key' page:
   + Name: Provide a name for your API key, like `MyAppKey`.
   + Resources: Choose the Amazon Location Service Map and Place index resources created earlier. You can add multiple resources by selecting 'Add Resource'. This allows the API key to be used with specified resources.
   +  Actions: Specify authorized actions for this API key. At a minimum, select `geo:GetMap` and `geo:SearchPlaceIndexForPosition` to ensure the tutorial functions as intended.
   + Optional you can add a Description, Expiration time, Tags, or a referrer for example `https://www.example.com` to limit the key's usage to a specific domain, enabling the tutorial to function only within that domain.

1. Click **Create API Key** to generate the API key.

1. Select **Show API Key** and copy the key value for example `v1.public.a1b2c3d4` for later use in the tutorial.



**Create an IAM policy for tracking**

1. Sign in to the IAM console at https://console.aws.amazon.com/iam/ with your user that has administrator permissions. 

1. In the navigation pane, choose Policies. 

1. In the content pane, choose Create policy. 

1. Choose the **JSON** option, then copy and paste this JSON policy into the JSON text box.

   ```
   {
           "Version": "2012-10-17",		 	 	 
           "Statement": [
               {
                   "Effect": "Allow",
                   "Action": [
                       "geo:GetMapTile",
                       "geo:GetMapStyleDescriptor",
                       "geo:GetMapSprites",
                       "geo:GetMapGlyphs",
                       "geo:SearchPlaceIndexForPosition",
                       "geo:GetDevicePositionHistory",
                       "geo:BatchUpdateDevicePosition"
                   ],
                   "Resource": [
                       "arn:aws:geo:{Region}:{Account}:map/{MapName}",
                       "arn:aws:geo:{Region}:{Account}:place-index/{IndexName}",
                       "arn:aws:geo:{Region}:{Account}:tracker/{TrackerName}"
                   ]
               }
           ]
       }
   ```

   This is a policy example for Tracking. To use the example for your own policy, replace the `Region`, `Account`, and **TrackerName** placeholders.
**Note**  
While unauthenticated identity pools are intended for exposure on unsecured internet sites, note that they will be exchanged for standard, time-limited AWS credentials.  
It's important to scope the IAM roles associated with unauthenticated identity pools appropriately. For more information about using and appropriately scoping policies in Amazon Cognito with Amazon Location Service, see [Granting access to Amazon Location Service](location/previous/developerguide/how-to-access.html).

1. On the Review and Create page, provide a name for the policy name field. Review the permissions granted by your policy, and then choose Create Policy to save your work.

The new policy appears in the list of managed policies and is ready to attach.

**Set up authentication for your tracking**

1. Set up authentication for your map application in the [Amazon Cognito console](https://console.aws.amazon.com/cognito/home/).

1. Open the **Identity pools** page.
**Note**  
The pool that you create must be in the same AWS account and AWS Region as the Amazon Location Service resources that you created in the previous section.

1. Choose **Create Identity pool**.

1. Starting with the **Configure identity pool trust** step. For user access authentication, select **Guest access**, and press next.

1. On the **Configure permissions** page select the **Use an existing IAM role** and enter the name of the IAM role you created in the previous step. When ready press next to move on to the next step.

1. On the **Configure properties** page, provide a name for your identity pool. Then press **Next**.

1. On the **Review and create** page, review all the information present then press **Create identity pool**.

1. Open the **Identity pools** page, and select the identity pool you just created. Then copy or write down the IdentityPoolId that you will use later in your browser script.

# Create the base Android application to use Amazon Location
<a name="qs-create-app-android"></a>

In this tutorial, you will create an Android application that embeds a map and allows the user to find what's at a location on the map.

First, create an empty Kotlin application using Android Studio's new project wizard.

**To create an empty application (AndroidStudio)**

1. Start AndroidStudio. Open the menu, and choose **File**, **New**, **New Project**.

1. From the **Phone and Tablet** tab, select **Empty Activity**, and then choose **Next**.

1. Choose a **Name**, **Package name**, and **Save location** for your application.

1. In the menu for **Language**, select **Kotlin**.

1. Choose **Finish** to create your blank application.

# Add an Amazon Location interactive map to your application
<a name="qs-add-map-android"></a>

Now that you have created a basic application, you can add map control to your application. This tutorial uses API keys for managing the map view. The map control itself is part of the [MapLibre Native library](https://github.com/maplibre/maplibre-native), with the API key and MapLibre, and the map data comes from Amazon Location.

To add a map to your application you will have to perform the following actions:
+ Add the MapLibre dependency to your project.
+ Set up the map view code with compose.
+ Write code to show the map.

Use the following procedure to add the map to your app:

1. Add the MapLibre dependency to your project

   1. In AndroidStudio, select the **View** menu, and choose **Tool Windows**, **Project**. This will open the Project window, which gives you access to all the files in your project.

   1. In the **Project** window, open **gradle** then open the `libs.versions.toml` file in the tree view. This will open the `libs.versions.toml` file for editing. Now add the below version and libraries data in the `libs.versions.toml` file.

      ```
      [versions]
       ...
       auth = "0.2.4"
       tracking = "0.2.4"
       
       [libraries]
       ...
       auth = { group = "software.amazon.location", name = "auth", version.ref = "auth" }
       tracking = { module = "software.amazon.location:tracking", version.ref = "tracking" }
      
       [plugins]
       ...
      ```

   1. After you finish editing the `libs.versions.toml` file, AndroidStudio must re-sync the project. At the top of the `libs.versions.toml` editing window, AndroidStudio prompts you to sync. Select 'Sync Now' to sync your project before continuing.

   1. In the Project window, open Gradle Scripts in the tree view and select the `build.gradle` file for your application module. This will open the `build.gradle` file for editing.

   1. At the bottom of the file, in the dependencies section, add the following dependency.

      ```
      dependencies {
          ...
          implementation(libs.org.maplibre.gl)
       }
      ```

   1. After you finish adding the Gradle dependencies, Android Studio must re-sync the project. At the top of the **build.gradle** editing window, Android Studio, select **Sync Now** to sync your project before continuing.

1. Now you will set up the map view code with compose. Use the following steps:

   1. From the Project window, open App, Java, *your package name* in the tree view, and go to the **ui** folder, inside the **ui** folder create a **view** directory.

   1. Inside **view** directory create a `MapLoadScreen.kt` file.

   1. Add the following code to your `MapLoadScreen.kt` file.

      ```
      import androidx.compose.foundation.layout.Box
      import androidx.compose.foundation.layout.fillMaxHeight
      import androidx.compose.foundation.layout.fillMaxWidth
      import androidx.compose.runtime.Composable
      import androidx.compose.ui.Modifier
      import androidx.compose.ui.viewinterop.AndroidView
      import org.maplibre.android.maps.OnMapReadyCallback
       
       @Composable
       fun MapLoadScreen(
           mapReadyCallback: OnMapReadyCallback,
       ) {
           Box(
               modifier = Modifier
                   .fillMaxWidth()
                   .fillMaxHeight(),
           ) {
               MapView(mapReadyCallback)
           }
       }
       
       @Composable
       fun MapView(mapReadyCallback: OnMapReadyCallback) {
           AndroidView(
               factory = { context ->
                   val mapView = org.maplibre.android.maps.MapView(context)
                   mapView.onCreate(null)
                   mapView.getMapAsync(mapReadyCallback)
                   mapView
               },
           )
       }
      ```

1. Write code to show the map.

   1. Add the following code to your `MainActivity.kt` file.

      ```
      // ...other imports
      import org.maplibre.android.MapLibre
      import org.maplibre.android.camera.CameraPosition
      import org.maplibre.android.geometry.LatLng
      import org.maplibre.android.maps.MapLibreMap
      import org.maplibre.android.maps.OnMapReadyCallback
      import org.maplibre.android.maps.Style
       
       class MainActivity : ComponentActivity(), OnMapReadyCallback {
           private val region = "YOUR_AWS_REGION"
           private val mapName = "YOUR_AWS_MAP_NAME"
           private val apiKey = "YOUR_AWS_API_KEY"
           override fun onCreate(savedInstanceState: Bundle?) {
               MapLibre.getInstance(this)
               super.onCreate(savedInstanceState)
               setContent {
                   TestMapAppTheme {
                       Surface(
                           modifier = Modifier.fillMaxSize(),
                           color = MaterialTheme.colorScheme.background
                       ) {
                           MapLoadScreen(this)
                       }
                   }
               }
           }
       
           override fun onMapReady(map: MapLibreMap) {
               map.setStyle(
                   Style.Builder()
                       .fromUri(
                           "https://maps.geo.$region.amazonaws.com/maps/v0/maps/$mapName/style-descriptor?key=$apiKey"
                       ),
               ) {
                   map.uiSettings.isAttributionEnabled = true
                   map.uiSettings.isLogoEnabled = false
                   map.uiSettings.attributionGravity = Gravity.BOTTOM or Gravity.END
                   val initialPosition = LatLng(47.6160281982247, -122.32642111977668)
                   map.cameraPosition = CameraPosition.Builder()
                       .target(initialPosition)
                       .zoom(14.0)
                       .build()
               }
           }
       }
      ```

   1. Save the `MainActivity.kt` file. You can now build the application. To run it, you may have to set up a device to emulate it in AndroidStudio, or use the app on your device. Use this app to see how the map control behaves. You can pan by dragging it on the map and pinching it to zoom.

      In the next section, you will add a marker on the map and show the address of the location where the marker is as you move the map.

# Add Amazon Location reverse geocoding search to your application
<a name="qs-add-search-android"></a>

You will now add reverse geocoding search to your application, where you find the items at a location. To simplify using an Android app, we will search the center of the screen. To find a new location, move the map to where you want to search. We will place a marker at the centre of the map to show where we are searching.

Adding a reverse geocoding search will consist of two parts.
+ Add a marker at the centre of the screen to show the user where we are searching.
+ Add a text box for results, then search for what is at the marker's location and show it in the text box.

**To add a marker to your application**

1. Save this image to your project in the `app/res/drawable` folder as `red_marker.png` (you can also access the image from [GitHub](https://github.com/makeen-project/amazon-location-mobile-quickstart-android/tree/main/app/src/main/res/drawable). Alternatively, you can create your image. You can also use a .png file with transparency for the parts you don't want shown.

1. Add the following code to your **MapLoadScreen.kt** file.

   ```
   // ...other imports
   import androidx.compose.foundation.Image
   import androidx.compose.foundation.layout.size
   import androidx.compose.ui.Alignment
   import androidx.compose.ui.res.painterResource
   import androidx.compose.ui.unit.dp
   import com.amazon.testmapapp.R
   
   @Composable
   fun MapLoadScreen(
       mapReadyCallback: OnMapReadyCallback,
   ) {
       Box(
           modifier = Modifier
               .fillMaxWidth()
               .fillMaxHeight(),
       ) {
           MapView(mapReadyCallback)
           Box(
               modifier = Modifier
                   .align(Alignment.Center),
           ) {
               Image(
                   painter = painterResource(id = R.drawable.red_marker),
                   contentDescription = "marker",
                   modifier = Modifier
                       .size(40.dp)
                       .align(Alignment.Center),
               )
           }
       }
   }
   
   @Composable
   fun MapView(mapReadyCallback: OnMapReadyCallback) {
       AndroidView(
           factory = { context ->
               val mapView = org.maplibre.android.maps.MapView(context)
               mapView.onCreate(null)
               mapView.getMapAsync(mapReadyCallback)
               mapView
           },
       )
   }
   ```

1. Build and run your app to preview the functionality.

Your app now has a marker on the screen. In this case, it is a static image that doesn't move. It is used to show the centre of the map view, which is where we will search. In the following procedure, we will add the search at that location.

**To add reverse geocoding search at a location to your app**

1. In the **Project** window, open **gradle** to `libs.versions.toml` file in the tree view. This will open the `libs.versions.toml` file for editing. Now add the below version and libraries data in the `libs.versions.toml` file.

   ```
   [versions]
    ...
    okhttp = "4.12.0"
    
    [libraries]
    ...
    com-squareup-okhttp3 = { group = "com.squareup.okhttp3", name = "okhttp", version.ref = "okhttp" }
    
    [plugins]
    ...
   ```

1. After you finish editing the `libs.versions.toml` file, AndroidStudio must re-sync the project. At the top of the `libs.versions.toml` editing window, AndroidStudio prompts you to sync. Select 'Sync Now' to sync your project before continuing.

1. In the Project window, open Gradle Scripts in the tree view and select the `build.gradle` file for your application module. This will open the `build.gradle` file for editing.

1. At the bottom of the file, in the dependencies section, add the following dependency.

   ```
   dependencies {
       ...
       implementation(libs.com.squareup.okhttp3)
    }
   ```

1. After you finish editing the Gradle dependencies, AndroidStudio must re-sync the project. At the top of the `build.gradle` editing window, AndroidStudio prompts you to sync. Select **SyncNow** to sync your project before continuing.

1. Now in the tree view add the **data**, to the **request** directory, and create the `ReverseGeocodeRequest.kt` data class. Add the following code to the class.

   ```
   import com.google.gson.annotations.SerializedName
   
   data class ReverseGeocodeRequest(
       @SerializedName("Language")
       val language: String,
       @SerializedName("MaxResults")
       val maxResults: Int,
       @SerializedName("Position")
       val position: ListDouble
   )
   ```

1. Now in the tree view add the **data** to **response** directory, and create the `ReverseGeocodeResponse.kt` data class. Add the following code inside it.

   ```
   import com.google.gson.annotations.SerializedName
   
   data class ReverseGeocodeResponse(
       @SerializedName("Results")
       val results: ListResult
   )
   
   data class Result(
       @SerializedName("Place")
       val place: Place
   )
   
   data class Place(
       @SerializedName("Label")
       val label: String
   )
   ```

1. Now, From the Project window, open App, Java, *your package name* in the tree view, and go to the **ui** folder, inside **ui** folder create **viewModel** directory.

1. Inside **viewModel** directory create `MainViewModel.kt` file.

1. Add the following code to your `MainViewModel.kt` file.

   ```
   import androidx.compose.runtime.getValue
   import androidx.compose.runtime.mutableStateOf
   import androidx.compose.runtime.setValue
   import androidx.lifecycle.ViewModel
   import com.amazon.testmapapp.data.request.ReverseGeocodeRequest
   import com.amazon.testmapapp.data.response.ReverseGeocodeResponse
   import com.google.gson.Gson
   import java.io.IOException
   import okhttp3.Call
   import okhttp3.Callback
   import okhttp3.MediaType.Companion.toMediaTypeOrNull
   import okhttp3.OkHttpClient
   import okhttp3.Request
   import okhttp3.RequestBody.Companion.toRequestBody
   import okhttp3.Response
   import org.maplibre.android.geometry.LatLng
   import org.maplibre.android.maps.MapLibreMap
   
   class MainViewModel : ViewModel() {
       var label by mutableStateOf("")
       var isLabelAdded: Boolean by mutableStateOf(false)
       var client = OkHttpClient()
       var mapLibreMap: MapLibreMap? = null
   
       fun reverseGeocode(latLng: LatLng, apiKey: String) {
           val region = "YOUR_AWS_REGION"
           val indexName = "YOUR_AWS_PLACE_INDEX"
           val url =
               "https://places.geo.${region}.amazonaws.com/places/v0/indexes/${indexName}/search/position?key=${apiKey}"
   
           val requestBody = ReverseGeocodeRequest(
               language = "en",
               maxResults = 1,
               position = listOf(latLng.longitude, latLng.latitude)
           )
           val json = Gson().toJson(requestBody)
   
           val mediaType = "application/json".toMediaTypeOrNull()
           val request = Request.Builder()
               .url(url)
               .post(json.toRequestBody(mediaType))
               .build()
   
           client.newCall(request).enqueue(object : Callback {
               override fun onFailure(call: Call, e: IOException) {
                   e.printStackTrace()
               }
   
               override fun onResponse(call: Call, response: Response) {
                   if (response.isSuccessful) {
                       val jsonResponse = response.body?.string()
   
                       val reverseGeocodeResponse =
                           Gson().fromJson(jsonResponse, ReverseGeocodeResponse::class.java)
   
                       val responseLabel = reverseGeocodeResponse.results.firstOrNull()?.place?.label
   
                       if (responseLabel != null) {
                           label = responseLabel
                           isLabelAdded = true
                       }
                   }
               }
           })
       }
   }
   ```

1. If it's not open already, open the `MapLoadScreen.kt` file, as in the previous procedure. Add the following code. This will create a compose Text view where you will see reverse geocoding search results at the location.

   ```
   // ...other imports
   import androidx.compose.foundation.background
   import androidx.compose.foundation.layout.Arrangement
   import androidx.compose.foundation.layout.Column
   import androidx.compose.foundation.layout.Spacer
   import androidx.compose.foundation.layout.fillMaxSize
   import androidx.compose.foundation.layout.height
   import androidx.compose.foundation.layout.padding
   import androidx.compose.material3.Text
   import androidx.compose.ui.graphics.Color
   import androidx.compose.ui.platform.testTag
   import androidx.compose.ui.semantics.contentDescription
   import androidx.compose.ui.semantics.semantics
   import androidx.compose.ui.unit.sp
   import com.amazon.testmapapp.ui.viewModel.MainViewModel
   
   @Composable
   fun MapLoadScreen(
       mapReadyCallback: OnMapReadyCallback,
       mainViewModel: MainViewModel,
   ) {
       Box(
           modifier = Modifier
               .fillMaxWidth()
               .fillMaxHeight(),
       ) {
           MapView(mapReadyCallback)
           Box(
               modifier = Modifier
                   .align(Alignment.Center),
           ) {
               Image(
                   painter = painterResource(id = R.drawable.red_marker),
                   contentDescription = "marker",
                   modifier = Modifier
                       .size(40.dp)
                       .align(Alignment.Center),
               )
           }
           if (mainViewModel.isLabelAdded) {
               Column(
                   modifier = Modifier.fillMaxSize(),
                   verticalArrangement = Arrangement.Bottom
               ) {
                   Box(
                       modifier = Modifier
                           .fillMaxWidth()
                           .background(Color.White),
                   ) {
                       Text(
                           text = mainViewModel.label,
                           modifier = Modifier
                               .padding(16.dp)
                               .align(Alignment.Center)
                               .testTag("label")
                               .semantics {
                                   contentDescription = "label"
                               },
                           fontSize = 14.sp,
                       )
                   }
                   Spacer(modifier = Modifier.height(80.dp))
               }
           }
       }
   }
   
   @Composable
   fun MapView(mapReadyCallback: OnMapReadyCallback) {
       AndroidView(
           factory = { context ->
               val mapView = org.maplibre.android.maps.MapView(context)
               mapView.onCreate(null)
               mapView.getMapAsync(mapReadyCallback)
               mapView
           },
       )
   }
   ```

1. In the app, under java, in the **package name** folder in AndroidStudio, open the `MainActivity.kt` file. Modify the code as shown.

   ```
   // ...other imports
   import androidx.activity.viewModels
   import com.amazon.testmapapp.ui.viewModel.MainViewModel
   
    class MainActivity : ComponentActivity(), OnMapReadyCallback, MapLibreMap.OnCameraMoveStartedListener, MapLibreMap.OnCameraIdleListener {
    
        private val mainViewModel: MainViewModel by viewModels()
        private val region = "YOUR_AWS_REGION"
        private val mapName = "YOUR_AWS_MAP_NAME"
        private val apiKey = "YOUR_AWS_API_KEY"
        override fun onCreate(savedInstanceState: Bundle?) {
            MapLibre.getInstance(this)
            super.onCreate(savedInstanceState)
            setContent {
                TestMapAppTheme {
                    Surface(
                        modifier = Modifier.fillMaxSize(),
                        color = MaterialTheme.colorScheme.background
                    ) {
                        MapLoadScreen(this, mainViewModel)
                    }
                }
            }
        }
    
        override fun onMapReady(map: MapLibreMap) {
            map.setStyle(
                Style.Builder()
                    .fromUri(
                        "https://maps.geo.$region.amazonaws.com/maps/v0/maps/$mapName/style-descriptor?key=$apiKey"
                    ),
            ) {
                map.uiSettings.isAttributionEnabled = true
                map.uiSettings.isLogoEnabled = false
                map.uiSettings.attributionGravity = Gravity.BOTTOM or Gravity.END
                val initialPosition = LatLng(47.6160281982247, -122.32642111977668)
                map.cameraPosition = CameraPosition.Builder()
                    .target(initialPosition)
                    .zoom(14.0)
                    .build()
                    
                map.addOnCameraMoveStartedListener(this)
                map.addOnCameraIdleListener(this)
                map.cameraPosition.target?.let { latLng ->
                    mainViewModel.reverseGeocode(
                        LatLng(
                            latLng.latitude,
                            latLng.longitude
                        ), apiKey
                    )
                }
            }
        }
       override fun onCameraMoveStarted(p0: Int) {
           mainViewModel.label = ""
           mainViewModel.isLabelAdded = false
       }
   
       override fun onCameraIdle() {
           if (!mainViewModel.isLabelAdded) {
               mainViewModel.mapLibreMap?.cameraPosition?.target?.let { latLng ->
                   mainViewModel.reverseGeocode(
                       LatLng(
                           latLng.latitude,
                           latLng.longitude
                       ), apiKey
                   )
               }
           }
       }
    }
   ```

   This code works with the map view. A virtual camera position defines the map view in MapLibre. Moving the map can be thought of as moving that virtual camera.
   + ViewModel has a label variable: This variable sets data in compose text view.
   + **onMapReady**:This function is updated to register two new events.
   + The **onCameraMove** event happens whenever the user is moving the map. In general, when moving the map, we want to hide the search until the user is done moving the map.
   + The **onCameraIdle** event occurs when the user pauses moving the map. This event calls our reverse geocode function to search at the centre of the map.
   + `reverseGeocode(latLng: LatLng, apiKey: String)`: This function, called in the event onCameraIdle, searches at the centre of the map for a location and updates the label to show the results. It uses the camera target, which defines the centre of the map (where the camera is looking).

1. Save your files, and build and run your app to see if it works.

Your quick-start application with search functionality is complete.

# Add Amazon Location tracking to your application
<a name="qs-add-tracking-android"></a>

To add tracking to your sample application, follow these steps:

1. Add tracking and auth SDK dependencies to your project.

1. Include permission and service entries in your AndroidManifest.xml file.

1. Set up the start/stop tracking button code with compose.

1. Add code for creating a LocationTracker object and start and stop tracking.

1. Create a test route with Android Emulator.

1. **Add tracking and auth SDK dependencies to your project.**

   1. In the **Project** window, open **gradle** then open the `libs.versions.toml` file in the tree view. This will open the `libs.versions.toml` file for editing. Now add the below version and libraries data in the `libs.versions.toml` file.

      ```
      [versions]
       ...
       auth = "0.0.1"
       tracking = "0.0.1"
       
       [libraries]
       ...
       auth = { group = "software.amazon.location", name = "auth", version.ref = "auth" }
       tracking = { module = "software.amazon.location:tracking", version.ref = "tracking" }
      
       [plugins]
       ...
      ```

   1. After you finish editing the `libs.versions.toml` file, AndroidStudio must re-sync the project. At the top of the `libs.versions.toml` editing window, AndroidStudio prompts you to sync. Select 'Sync Now' to sync your project before continuing.

   1. In the Project window, open Gradle Scripts in the tree view and select the `build.gradle` file for your application module. This will open the `build.gradle` file for editing.

   1. At the bottom of the file, in the **dependencies** section, add the following dependency.

      ```
      dependencies {
          ...
          implementation(libs.auth)
          implementation(libs.tracking)
       }
      ```

   1. After you finish editing the Gradle dependencies, AndroidStudio must re-sync the project. At the top of the **build.gradle** editing window, AndroidStudio prompts you to sync. Select **SyncNow** to sync your project before continuing.

1. **Include permission and service entries in your AndroidManifest.xml file.**

   1. To include the correct permission and service entries in your `AndroidManifest.xml file`, update the file with the following code:

     ```
     <?xml version="1.0" encoding="utf-8"?>
     <manifest xmlns:android="http://schemas.android.com/apk/res/android"
         xmlns:tools="http://schemas.android.com/tools">
     
         <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
         <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
         <uses-permission android:name="android.permission.INTERNET"/>
         <application
             android:allowBackup="true"
             android:dataExtractionRules="@xml/data_extraction_rules"
             android:fullBackupContent="@xml/backup_rules"
             android:icon="@mipmap/ic_launcher"
             android:label="@string/app_name"
             android:roundIcon="@mipmap/ic_launcher_round"
             android:supportsRtl="true"
             android:theme="@style/Theme.AndroidQuickStartApp"
             tools:targetApi="31">
             <activity
                 android:name=".MainActivity"
                 android:exported="true"
                 android:label="@string/app_name"
                 android:theme="@style/Theme.AndroidQuickStartApp">
                 <intent-filter>
                     <action android:name="android.intent.action.MAIN" />
     
                     <category android:name="android.intent.category.LAUNCHER" />
                 </intent-filter>
             </activity>
         </application>
     
     </manifest>
     ```

1. **Set up the start/stop tracking button code with compose.** 

   1. Add two images of Play and Pause in **res** under **drawable** named as **ic\$1pause** and **ic\$1play**. You can also access the image from [GitHub](https://github.com/aws-geospatial/amazon-location-samples-android/tree/main/quick-start/res/drawable).

   1. If it's not open already, open the `MapLoadScreen.kt` file, as in the previous procedure. Add the following code. This will create a compose Button view where we can click on it to **start** and **stop** tracking.

      ```
      // ...other imports
      import androidx.compose.material3.Button
      import androidx.compose.material3.ButtonDefaults
      
      @Composable
      fun MapLoadScreen(
          mapReadyCallback: OnMapReadyCallback,
          mainViewModel: MainViewModel,
          onStartStopTrackingClick: () -> Unit
      ) {
          Box(
              modifier = Modifier
                  .fillMaxWidth()
                  .fillMaxHeight(),
          ) {
              MapView(mapReadyCallback)
              Box(
                  modifier = Modifier
                      .align(Alignment.Center),
              ) {
                  Image(
                      painter = painterResource(id = R.drawable.red_marker),
                      contentDescription = "marker",
                      modifier = Modifier
                          .size(40.dp)
                          .align(Alignment.Center),
                  )
              }
              if (mainViewModel.isLabelAdded) {
                  Column(
                      modifier = Modifier.fillMaxSize(),
                      verticalArrangement = Arrangement.Bottom
                  ) {
                      Box(
                          modifier = Modifier
                              .fillMaxWidth()
                              .background(Color.White),
                      ) {
                          Text(
                              text = mainViewModel.label,
                              modifier = Modifier
                                  .padding(16.dp)
                                  .align(Alignment.Center)
                                  .testTag("label")
                                  .semantics {
                                      contentDescription = "label"
                                  },
                              fontSize = 14.sp,
                          )
                      }
                      Spacer(modifier = Modifier.height(80.dp))
                  }
              }
              Column(
                  modifier = Modifier
                      .fillMaxSize()
                      .padding(bottom = 16.dp),
                  horizontalAlignment = Alignment.CenterHorizontally,
                  verticalArrangement = Arrangement.Bottom,
              ) {
                  Button(
                      onClick = onStartStopTrackingClick,
                      modifier = Modifier
                          .padding(horizontal = 16.dp)
                  ) {
                      Text(
                          text = if (mainViewModel.isLocationTrackingForegroundActive) "Stop tracking" else "Start tracking",
                          color = Color.Black
                      )
                      Spacer(modifier = Modifier.size(ButtonDefaults.IconSpacing))
                      Image(
                          painter = painterResource(id = if (mainViewModel.isLocationTrackingForegroundActive) R.drawable.ic_pause else R.drawable.ic_play),
                          contentDescription = if (mainViewModel.isLocationTrackingForegroundActive) "stop_tracking" else "start_tracking"
                      )
                  }
              }
          }
      }
      
      @Composable
      fun MapView(mapReadyCallback: OnMapReadyCallback) {
          AndroidView(
              factory = { context ->
                  val mapView = org.maplibre.android.maps.MapView(context)
                  mapView.onCreate(null)
                  mapView.getMapAsync(mapReadyCallback)
                  mapView
              },
          )
      }
      ```

1. **Add code for creating a LocationTracker object and start and stop tracking.** 

   1. Add the following code inside the `MainViewModel.kt` file.

      ```
      ...
      var isLocationTrackingForegroundActive: Boolean by mutableStateOf(false)
      var locationTracker: LocationTracker? = null
      ```

   1. Add the following code to your `MainActivity.kt` file.

      ```
      // ...other imports
      import software.amazon.location.auth.AuthHelper
      import software.amazon.location.auth.LocationCredentialsProvider
      import software.amazon.location.tracking.LocationTracker
      import software.amazon.location.tracking.aws.LocationTrackingCallback
      import software.amazon.location.tracking.config.LocationTrackerConfig
      import software.amazon.location.tracking.database.LocationEntry
      import software.amazon.location.tracking.filters.DistanceLocationFilter
      import software.amazon.location.tracking.filters.TimeLocationFilter
      import software.amazon.location.tracking.util.TrackingSdkLogLevel
      
      class MainActivity : ComponentActivity(), OnMapReadyCallback,
          MapLibreMap.OnCameraMoveStartedListener, MapLibreMap.OnCameraIdleListener {
      
          private val mainViewModel: MainViewModel by viewModels()
          private val poolId = "YOUR_AWS_IDENTITY_POOL_ID"
          private val trackerName = "YOUR_AWS_TRACKER_NAME"
          private val region = "YOUR_AWS_REGION"
          private val mapName = "YOUR_AWS_MAP_NAME"
          private val apiKey = "YOUR_AWS_API_KEY"
          private val coroutineScope = MainScope()
          private lateinit var locationCredentialsProvider: LocationCredentialsProvider
          private lateinit var authHelper: AuthHelper
      
          override fun onCreate(savedInstanceState: Bundle?) {
              MapLibre.getInstance(this)
              super.onCreate(savedInstanceState)
              setContent {
                  TestMapAppTheme {
                      Surface(
                          modifier = Modifier.fillMaxSize(),
                          color = MaterialTheme.colorScheme.background
                      ) {
                          MapLoadScreen(this, mainViewModel, onStartStopTrackingClick = {
                              if (mainViewModel.isLocationTrackingForegroundActive) {
                                  mainViewModel.isLocationTrackingForegroundActive = false
                                  mainViewModel.locationTracker?.stop()
                              } else {
                                  if (checkLocationPermission(this)) return@MapLoadScreen
                                  mainViewModel.isLocationTrackingForegroundActive = true
                                  mainViewModel.locationTracker?.start(locationTrackingCallback = object :
                                      LocationTrackingCallback {
                                      override fun onLocationAvailabilityChanged(locationAvailable: Boolean) {
                                      }
      
                                      override fun onLocationReceived(location: LocationEntry) {
                                      }
      
                                      override fun onUploadSkipped(entries: LocationEntry) {
                                      }
      
                                      override fun onUploadStarted(entries: ListLocationEntry) {
                                      }
      
                                      override fun onUploaded(entries: ListLocationEntry) {
                                      }
      
                                  })
                              }
                          })
                      }
                  }
              }
              authenticateUser()
          }
      
          private fun authenticateUser() {
              coroutineScope.launch {
                  authHelper = AuthHelper(applicationContext)
                  locationCredentialsProvider = authHelper.authenticateWithCognitoIdentityPool(
                      poolId,
                  )
                  locationCredentialsProvider.let {
                      val config = LocationTrackerConfig(
                          trackerName = trackerName,
                          logLevel = TrackingSdkLogLevel.DEBUG,
                          latency = 1000,
                          frequency = 5000,
                          waitForAccurateLocation = false,
                          minUpdateIntervalMillis = 5000,
                      )
                      mainViewModel.locationTracker = LocationTracker(
                          applicationContext,
                          it,
                          config,
                      )
                      mainViewModel.locationTracker?.enableFilter(TimeLocationFilter())
                      mainViewModel.locationTracker?.enableFilter(DistanceLocationFilter())
                  }
              }
          }
      
          private fun checkLocationPermission(context: Context) = ActivityCompat.checkSelfPermission(
              context,
              Manifest.permission.ACCESS_FINE_LOCATION,
          ) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(
              context,
              Manifest.permission.ACCESS_COARSE_LOCATION,
          ) != PackageManager.PERMISSION_GRANTED
      
          override fun onMapReady(map: MapLibreMap) {
              map.setStyle(
                  Style.Builder()
                      .fromUri(
                          "https://maps.geo.$region.amazonaws.com/maps/v0/maps/$mapName/style-descriptor?key=$apiKey"
                      ),
              ) {
                  mainViewModel.mapLibreMap = map
                  map.uiSettings.isAttributionEnabled = true
                  map.uiSettings.isLogoEnabled = false
                  map.uiSettings.attributionGravity = Gravity.BOTTOM or Gravity.END
                  val initialPosition = LatLng(47.6160281982247, -122.32642111977668)
                  map.cameraPosition = CameraPosition.Builder()
                      .target(initialPosition)
                      .zoom(14.0)
                      .build()
      
                  map.addOnCameraMoveStartedListener(this)
                  map.addOnCameraIdleListener(this)
                  map.cameraPosition.target?.let { latLng ->
                      mainViewModel.reverseGeocode(
                          LatLng(
                              latLng.latitude,
                              latLng.longitude
                          ), apiKey
                      )
                  }
              }
          }
      
          override fun onCameraMoveStarted(p0: Int) {
              mainViewModel.label = ""
              mainViewModel.isLabelAdded = false
          }
      
          override fun onCameraIdle() {
              if (!mainViewModel.isLabelAdded) {
                  mainViewModel.mapLibreMap?.cameraPosition?.target?.let { latLng ->
                      mainViewModel.reverseGeocode(
                          LatLng(
                              latLng.latitude,
                              latLng.longitude
                          ), apiKey
                      )
                  }
              }
          }
      }
      ```

      The above code shows how to create a `LocationTracker` object with `AuthHelper` and how to start and stop tracking with LocationTracker.
      + `authenticateUser()`: This method creates AuthHelper and LocationTracker objects.
      + `onStartStopTrackingClick`: This callback is triggered when the user clicks on the start/stop tracking button, which will start/stop tracking with Tracking SDK.

1. **Create a test route with Android Emulator.**

   1. **Open Emulator** by launching the AVD using Android Studio.

   1. **Open Extended Controls** by clicking on the **More** (three dots) icon in the emulator toolbar.

   1. **Open Location** by selecting **Location** from the sidebar.

   1. **Create route** with GPX data or by clicking on the map and choosing source and destination data.

   1. **Start Simulation** by clicking on **PLAY ROUTE** to begin simulating the GPS route.

   1. **Test Application** by running your application and observing how it handles the simulated route.

This is the full demo of the Android Quick Start application.

## What's next
<a name="qs-android-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.

The source code for this application is available on [GitHub](https://github.com/aws-geospatial/amazon-location-samples-android/tree/main/quick-start).

To get more out of Amazon Location, you can check out the following resources:
+ Dive deeper into the [concepts of Amazon Location Service](how-it-works.md)
+ Get more information about [how to use Amazon Location features and functionality](using-amazon-location.md)
+ See how to expand on this sample and build more complex applications by looking at [code examples using Amazon Location](samples.md)

# Create an iOS app for Amazon Location Service
<a name="qs-ios"></a>

In this section, you will create an iOS application with the ability to search at a location and tracking in the foreground. First, you will create your Amazon Location resources, and an Amazon Cognito identity for your application.

**Topics**
+ [Create Amazon Location resources for your app](qs-create-resources-ios.md)
+ [Set up authentication for your Amazon Location application](qs-setup-authentication-ios.md)
+ [Create the base iOS application to use Amazon Location](qs-ios-create-app.md)
+ [Set up the initial code for Amazon Location](qs-ios-create-app-initial-code.md)
+ [Add an Amazon Location interactive map to your application](qs-ios-add-map.md)
+ [Add Amazon Location search to your application](qs-ios-add-search.md)
+ [Add Amazon Location tracking to your application](qs-ios-add-tracking.md)

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

If you do not already have them, you must create the Amazon Location resources that your application will use. You will create a map resource to display maps in your application, a place index to search for locations on the map, and a tracker to track an object across the map.

**To add location resources to your application**

1. Choose the map style that you want to use.

   1. In the Amazon Location console, on the [Maps](https://console.aws.amazon.com/location/maps/home) page, choose **Create map** to preview map styles.

   1. Add a **Name** and **Description** for the new map resource. Make a note of the name that you use for the map resource. You will need it when creating your script file later in the tutorial.

   1. Choose a map.
**Note**  
Choosing a map style also chooses which map data provider that you will use. If your application is tracking or routing assets that you use in your business, such as delivery vehicles or employees, you may only use HERE as your geolocation provider. For more information, see section 82 of the [AWS service terms](https://aws.amazon.com/service-terms). 

   1. Agree to the **Amazon Location Terms and Conditions**, then choose **Create map**. You can interact with the map that you've chosen: zoom in, zoom out, or pan in any direction.

   1. Make a note of the Amazon Resource Name (ARN) that is shown for your new map resource. You'll use it to create the correct authentication later in this tutorial.

1. Choose the place index that you want to use.

   1. In the Amazon Location console on the [https://console.aws.amazon.com/location/places/home](https://console.aws.amazon.com/location/places/home) page, choose **Create place index**.

   1. Add a **Name** and **Description** for the new place index resource. Make a note of the name that you use for the place index resource. You will need it when creating your script file later in the tutorial.

   1. Choose a data provider.
**Note**  
In most cases, choose the data provider that matches the map provider that you already chose. This helps to ensure that the searches will match the maps.  
If your application is tracking or routing assets that you use in your business, such as delivery vehicles or employees, you may only use HERE as your geolocation provider. For more information, see section 82 of the [AWS service terms](https://aws.amazon.com/service-terms). 

   1. Choose the **Data storage option**. For this tutorial, the results are not stored, so you can choose ** No, single use only**.

   1. Agree to the **Amazon Location Terms and Conditions**, then choose **Create place index**.

   1. Make a note of the ARN that is shown for your new place index resource. You'll use it to create the correct authentication in the next section of this tutorial.

1. 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**, we recommend you use the default setting: **TimeBased**.

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

# Set up authentication for your Amazon Location application
<a name="qs-setup-authentication-ios"></a>

The application that you create in this tutorial has anonymous usage, meaning that your users are not required to sign into AWS to use the application. However, the Amazon Location Service APIs require authentication to use. You will use Amazon Cognito to provide authentication and authorization for anonymous users. This tutorial will use Amazon Cognito to authenticate your application.

**Note**  
For more information about using Amazon Cognito with Amazon Location Service, see [Grant access to Amazon Location Service](how-to-access.md).

The following tutorials show you how to set up authentication for the map, the place index, and tracker you created in as well setting up permissions for Amazon Location.

**Create an IAM policy for tracking**

1. Sign in to the IAM console at https://console.aws.amazon.com/iam/ with your user that has administrator permissions. 

1. In the navigation pane, choose Policies. 

1. In the content pane, choose Create policy. 

1. Choose the **JSON** option, then copy and paste this JSON policy into the JSON text box.

   ```
   {
           "Version": "2012-10-17",		 	 	 
           "Statement": [
               {
                   "Effect": "Allow",
                   "Action": [
                       "geo:GetMapTile",
                       "geo:GetMapStyleDescriptor",
                       "geo:GetMapSprites",
                       "geo:GetMapGlyphs",
                       "geo:SearchPlaceIndexForPosition",
                       "geo:GetDevicePositionHistory",
                       "geo:BatchUpdateDevicePosition"
                   ],
                   "Resource": [
                       "arn:aws:geo:{Region}:{Account}:map/{MapName}",
                       "arn:aws:geo:{Region}:{Account}:place-index/{IndexName}",
                       "arn:aws:geo:{Region}:{Account}:tracker/{TrackerName}"
                   ]
               }
           ]
       }
   ```

   This is a policy example for Tracking. To use the example for your own policy, replace the `Region`, `Account`, `IndexName`, `MapName` and **TrackerName** placeholders.
**Note**  
While unauthenticated identity pools are intended for exposure on unsecured internet sites, note that they will be exchanged for standard, time-limited AWS credentials.  
It's important to scope the IAM roles associated with unauthenticated identity pools appropriately. For more information about using and appropriately scoping policies in Amazon Cognito with Amazon Location Service, see [Granting access to Amazon Location Service](location/previous/developerguide/how-to-access.html).

1. On the Review and Create page, provide a name for the policy name field. Review the permissions granted by your policy, and then choose Create Policy to save your work.

The new policy appears in the list of managed policies and is ready to attach.

**Set up authentication for your tracking**

1. Set up authentication for your map application in the [Amazon Cognito console](https://console.aws.amazon.com/cognito/home/).

1. Open the **Identity pools** page.
**Note**  
The pool that you create must be in the same AWS account and AWS Region as the Amazon Location Service resources that you created in the previous section.

1. Choose **Create Identity pool**.

1. Starting with the **Configure identity pool trust** step. For user access authentication, select **Guest access**, and press next.

1. On the **Configure permissions** page select the **Use an existing IAM role** and enter the name of the IAM role you created in the previous step. When ready press next to move on to the next step.

1. On the **Configure properties** page, provide a name for your identity pool. Then press **Next**.

1. On the **Review and create** page, review all the information present then press **Create identity pool**.

1. Open the **Identity pools** page, and select the identity pool you just created. Then copy or write down the IdentityPoolId that you will use later in your browser script.

# Create the base iOS application to use Amazon Location
<a name="qs-ios-create-app"></a>

In this tutorial, you will create an iOS application that embeds a map, and allows the user to find what's at a location on the map. 

First, let's create a Swift application using Xcode's project wizard.

**To create an empty application (Xcode)**

1. Open Xcode, and from the menu, choose **File**, **New**, **New Project**.

1. From the **iOS** tab, select **App**, and then choose **Next**.

1. Provide a **Product Name**, an **Organization Identifier**, and in the **Interface** field input `SwiftUI`. Choose **Next** to finalize the selection.

1. Select a location where you will save your project and press **create** button to create the empty application.

Once you have creating the base application, you will need to install the required packages for the sample app.

**Installing required dependencies**

1. In Xcode, right-click on the **project** and choose **Add Packages...**. This will open the Packages window, where you can add packages to your project.

1. In the Packages window, add the following packages:
   + For the Maplibre native package, use this URL: [https://github.com/maplibre/maplibre-gl-native-distribution](https://github.com/maplibre/maplibre-gl-native-distribution). From the URL, add these packages: `maplibre-gl-native-distribution`, and `Mapbox`.
   + For the Amazon Location authentication iOS SDK, use this URL: [https://github.com/aws-geospatial/amazon-location-mobile-auth-sdk-ios](https://github.com/aws-geospatial/amazon-location-mobile-auth-sdk-ios). From the URL, add these packages: `amazon-location-mobile-auth-sdk-ios`, and `AmazonLocationiOSAuthSDK`.
   + For the Amazon Location tracking iOS SDK, use this URL: [https://github.com/aws-geospatial/amazon-location-mobile-tracking-sdk-ios](https://github.com/aws-geospatial/amazon-location-mobile-tracking-sdk-ios). From the URL, add these packages: `amazon-location-mobile-tracking-sdk-ios`, and `AmazonLocationiOSTrackingSDK`.

# Set up the initial code for Amazon Location
<a name="qs-ios-create-app-initial-code"></a>

This page provides the initial code for a sample iOS application that integrates with the Amazon Location Service. With this code as a starting point, you can build location-aware iOS apps leveraging features like maps, geocoding, geofencing, tracking, and routing.

**Enable Location permissions in your app**

1. Open your Xcode project.

1. Locate the project's `Info.plist` file.

1. Add the necessary keys for location permissions based on your app's requirements. Here are the keys:
   + `NSLocationWhenInUseUsageDescription`: Description of why your app needs location access when it's in use.
   + `NSLocationAlwaysAndWhenInUseUsageDescription`: Description of why your app needs continuous location access.

Now you will need to configure resource values in your app. Add a new file named `Config.xcconfig` and fill out the values that you had created previously in the Amazon console.

```
REGION =
INDEX_NAME =
MAP_NAME =
IDENTITY_POOL_ID =
TRACKER_NAME =
```

1. From the left side navigator section, select the project.

1. Under the targets section, select your app and click on the info tab.

1. Add info properties with values like the below:

1. Add the `Config.swift` file with the contents below, which will read config values from the Bundle info file.

   ```
   import Foundation
   
   enum Config {
       static let region = Bundle.main.object(forInfoDictionaryKey: "Region") as! String
       static let mapName = Bundle.main.object(forInfoDictionaryKey: "MapName") as! String
       static let indexName = Bundle.main.object(forInfoDictionaryKey: "IndexName") as! String
       static let identityPoolId = Bundle.main.object(forInfoDictionaryKey: "IdentityPoolId") as! String
       static let trackerName = Bundle.main.object(forInfoDictionaryKey: "TrackerName") as! String
   }
   ```

1. Create a new folder with the name `ViewModel` and add a `TrackingViewModel.swift` file inside it.

   ```
   import SwiftUI
   import AmazonLocationiOSAuthSDK
   import MapLibre
   
   final class TrackingViewModel : ObservableObject {
       @Published var trackingButtonText = NSLocalizedString("StartTrackingLabel", comment: "")
       @Published var trackingButtonColor = Color.blue
       @Published var trackingButtonIcon = "play.circle"
       @Published var region : String
       @Published var mapName : String
       @Published var indexName : String
       @Published var identityPoolId : String
       @Published var trackerName : String
       @Published var showAlert = false
       @Published var alertTitle = ""
       @Published var alertMessage = ""
       @Published var centerLabel = ""
   
       var clientIntialised: Bool
       var client: LocationTracker!
       var authHelper: AuthHelper
       var credentialsProvider: LocationCredentialsProvider?
       var mlnMapView: MLNMapView?
       var mapViewDelegate: MapViewDelegate?
       var lastGetTrackingTime: Date?
       var trackingActive: Bool
       
       init(region: String, mapName: String, indexName: String, identityPoolId: String, trackerName: String) {
           self.region = region
           self.mapName = mapName
           self.indexName = indexName
           self.identityPoolId = identityPoolId
           self.trackerName = trackerName
           self.authHelper = AuthHelper()
           self.trackingActive = false
           self.clientIntialised = false
       }
       
       func authWithCognito(identityPoolId: String?) {
           guard let identityPoolId = identityPoolId?.trimmingCharacters(in: .whitespacesAndNewlines)
           else {
               alertTitle = NSLocalizedString("Error", comment: "")
               alertMessage = NSLocalizedString("NotAllFieldsAreConfigured", comment: "")
               showAlert = true
               return
           }
           credentialsProvider = authHelper.authenticateWithCognitoUserPool(identityPoolId: identityPoolId)
           initializeClient()
       }
       
       func initializeClient() {
           client = LocationTracker(provider: credentialsProvider!, trackerName: trackerName)
           clientIntialised = true
       }
   }
   ```

# Add an Amazon Location interactive map to your application
<a name="qs-ios-add-map"></a>

You will now add the map control to your application. This tutorial uses MapLibre and the AWS API for managing the map view in the application. The map control itself is part of the [MapLibre GL Native iOS](https://docs.maptiler.com/maplibre-gl-native-ios/) library.

1. Add `MapView.swift` file under the **Views** folder with the following code:

   ```
   import SwiftUI
   import MapLibre
   
   struct MapView: UIViewRepresentable {
       var onMapViewAvailable: ((MLNMapView) -> Void)?
       var mlnMapView: MLNMapView?
       var trackingViewModel: TrackingViewModel
       
       func makeCoordinator() -> MapView.Coordinator {
           return Coordinator(self, trackingViewModel: trackingViewModel)
       }
       
       func makeUIView(context: Context) -> MLNMapView {
           let styleURL = URL(string: "https://maps.geo.\(trackingViewModel.region).amazonaws.com/maps/v0/maps/\(trackingViewModel.mapName)/style-descriptor")
           let mapView = MLNMapView(frame: .zero, styleURL: styleURL)
           mapView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
           mapView.setZoomLevel(15, animated: true)
           mapView.showsUserLocation = true
           mapView.userTrackingMode = .follow
           context.coordinator.mlnMapView = mapView
           mapView.delegate = context.coordinator
   
           mapView.logoView.isHidden = true
           context.coordinator.addCenterMarker()
           
           onMapViewAvailable?(mapView)
           trackingViewModel.mlnMapView = mapView
           return mapView
       }
       
       func updateUIView(_ uiView: MLNMapView, context: Context) {
       }
       
       class Coordinator: NSObject, MLNMapViewDelegate, MapViewDelegate {
           var control: MapView
           var mlnMapView: MLNMapView?
           var trackingViewModel: TrackingViewModel
           var centerMarker: MLNPointAnnotation?
           
           public init(_ control: MapView, trackingViewModel: TrackingViewModel) {
               self.control = control
               self.trackingViewModel = trackingViewModel
               super.init()
               self.trackingViewModel.mapViewDelegate = self
           }
   
           func mapViewDidFinishRenderingMap(_ mapView: MLNMapView, fullyRendered: Bool) {
               if(fullyRendered) {
                   mapView.accessibilityIdentifier = "MapView"
                   mapView.isAccessibilityElement = false
               }
           }
           
           func addCenterMarker() {
               guard let mlnMapView = mlnMapView else {
                   return
               }
   
               let centerCoordinate = mlnMapView.centerCoordinate
               let marker = MLNPointAnnotation()
               marker.coordinate = centerCoordinate
               marker.accessibilityLabel = "CenterMarker"
               mlnMapView.addAnnotation(marker)
               centerMarker = marker
   
               trackingViewModel.reverseGeocodeCenter(centerCoordinate: centerCoordinate, marker: marker)
           }
           
           func mapView(_ mapView: MLNMapView, regionDidChangeAnimated animated: Bool) {
               if let marker = centerMarker {
                                 DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
                       mapView.deselectAnnotation(marker, animated: false)
                       marker.coordinate = mapView.centerCoordinate
                       let centerCoordinate = mapView.centerCoordinate
                       self.trackingViewModel.reverseGeocodeCenter(centerCoordinate: centerCoordinate, marker: marker)
                   }
               }
           }
       }
   }
   ```

1. Add `AWSSignatureV4Delegate` file under the **ViewModel** folder. This file is used to sign with all the MapView http requests to render the map:

   ```
   import MapLibre
   import AmazonLocationiOSAuthSDK
    
   class AWSSignatureV4Delegate : NSObject, MLNOfflineStorageDelegate {
       private let awsSigner: AWSSigner
     
       init(credentialsProvider: LocationCredentialsProvider) {
           self.awsSigner = DENY LIST ERROR , serviceName: "geo")
           super.init()
       }
    
       func offlineStorage(_ storage: MLNOfflineStorage, urlForResourceOf kind: MLNResourceKind, with url: URL) -> URL {
           if url.host?.contains("amazonaws.com") != true {
               return url
           }
           let signedURL = awsSigner.signURL(url: url, expires: .hours(1))
           
           return signedURL
       }
   }
   ```

1. Add `UserLocationView.swift` file under **Views** folder. This adds a button which centers the map to the user's location

   ```
   import SwiftUI
   
   struct UserLocationView: View {
       @ObservedObject var trackingViewModel: TrackingViewModel
       var body: some View {
               Button(action: {
                   trackingViewModel.locateMe()
               }) {
                   Image(systemName: "scope")
                       .resizable()
                       .frame(width: 24, height: 24)
                       .padding(5)
                       .background(Color.white)
                       .foregroundColor(.blue)
                       .clipShape(RoundedRectangle(cornerRadius: 8))
                       .shadow(color: Color.black.opacity(0.3), radius: 3, x: 0, y: 2)
               }
               .accessibility(identifier: "LocateMeButton")
               .padding(.trailing, 10)
               .padding(.bottom, 10)
               .frame(maxWidth: .infinity, alignment: .trailing)
       }
   }
   ```

1. Add the `TrackingView.swift` file with the following code:

   ```
   import SwiftUI
   
   struct TrackingView: View {
       @ObservedObject var trackingViewModel: TrackingViewModel
       var body: some View {
           ZStack(alignment: .bottom) {
               MapView(trackingViewModel: trackingViewModel)
               VStack {
                   UserLocationView(trackingViewModel: trackingViewModel)
               }
           }
           .onAppear() {
               if !trackingViewModel.identityPoolId.isEmpty {
                   trackingViewModel.authWithCognito(identityPoolId: trackingViewModel.identityPoolId)
               }
           }
       }
   }
   ```

You can now build the application. To run it, you may have to set up a device to emulate it in Xcode or use the app on your device. Use this app to see how the map control behaves. You can pan by dragging on the map and pinch to zoom. On your own, you can change how the map control works to customize it to the needs of your application.

# Add Amazon Location search to your application
<a name="qs-ios-add-search"></a>

 You now will add reverse geocoding search to the application, where you find the items at a location. To simplify the use of an iOS app, we will search the center of the screen. To find a new location, move the map to where you want to search. We will place a marker at the center of the map to show where we are searching.

1. Add the following code in `TrackingViewModel.swift` file which is related to the reverse geocoding search

   ```
   func reverseGeocodeCenter(centerCoordinate: CLLocationCoordinate2D, marker: MLNPointAnnotation) {
       let position = [NSNumber(value: centerCoordinate.longitude), NSNumber(value: centerCoordinate.latitude)]
       searchPositionAPI(position: position, marker: marker)
   }
   
   func searchPositionAPI(position: [Double], marker: MLNPointAnnotation) {
       if let amazonClient = authHelper.getLocationClient() {
           Task {
               let searchRequest = SearchPlaceIndexForPositionInput(indexName: indexName, language: "en" , maxResults: 10, position: position)
               let searchResponse = try? await amazonClient.searchPosition(indexName: indexName, input: searchRequest)
               DispatchQueue.main.async {
                   self.centerLabel = searchResponse?.results?.first?.place?.label ?? ""
                   self.mlnMapView?.selectAnnotation(marker, animated: true, completionHandler: {})
               }
           }
       }
   }
   ```

1. Update `TrackingView.swift` file with the following code which will show the mapview's centered location's address

   ```
   import SwiftUI
   
   struct TrackingView: View {
       @ObservedObject var trackingViewModel: TrackingViewModel
       var body: some View {
           ZStack(alignment: .bottom) {
               if trackingViewModel.mapSigningIntialised {
                   MapView(trackingViewModel: trackingViewModel)
                   VStack {
                       UserLocationView(trackingViewModel: trackingViewModel)
                       CenterAddressView(trackingViewModel: trackingViewModel)
                   }
               }
               else {
                   Text("Loading...") 
               }
           }
           .onAppear() {
               if !trackingViewModel.identityPoolId.isEmpty {
                   Task {
                       do {
                           try await trackingViewModel.authWithCognito(identityPoolId: trackingViewModel.identityPoolId)
                       }
                       catch {
                           print(error)
                       }
                   }
               }
           }
       }
   }
   ```

# Add Amazon Location tracking to your application
<a name="qs-ios-add-tracking"></a>

The last step for your application is to add tracking functionality to your app. In this case, you will add start tracking, stop tracking, fetch and display tracker points on your app.

1. Add the `TrackingBottomView.swift` file in your project. Which has a button that starts and stops tracking user locations and shows tracking points on the map.

   ```
   import SwiftUI
   
   struct TrackingBottomView: View {
       @ObservedObject var trackingViewModel: TrackingViewModel
       var body: some View {
              Button(action: {
                  Task {
                      if(trackingViewModel.trackingButtonText == NSLocalizedString("StartTrackingLabel", comment: "")) {
                          trackingViewModel.startTracking()
                      } else {
                          trackingViewModel.stopTracking()
                      }
                  }
              }) {
                  HStack {
                      Spacer()
                      Text("Tracking")
                          .foregroundColor(trackingViewModel.trackingButtonColor)
                          .background(.white)
                          .cornerRadius(15.0)
                      
                      Image(systemName: trackingViewModel.trackingButtonIcon)
                          .resizable()
                          .frame(width: 24, height: 24)
                          .padding(5)
                          .background(.white)
                          .foregroundColor(trackingViewModel.trackingButtonColor)
   
                  }
              }
              .accessibility(identifier: "TrackingButton")
              .background(.white)
              .clipShape(RoundedRectangle(cornerRadius: 8))
              .padding(.trailing, 10)
              .padding(.bottom, 40)
              .frame(width: 130, alignment: .trailing)
              .shadow(color: Color.black.opacity(0.3), radius: 3, x: 0, y: 2)
          }
   }
   ```

1. Update `TrackingView.swift` file with the following code

   ```
   import SwiftUI
   
   struct TrackingView: View {
       @ObservedObject var trackingViewModel: TrackingViewModel
       var body: some View {
           ZStack(alignment: .bottom) {
               if trackingViewModel.mapSigningIntialised {
                   MapView(trackingViewModel: trackingViewModel)
                   VStack {
                       UserLocationView(trackingViewModel: trackingViewModel)
                       CenterAddressView(trackingViewModel: trackingViewModel)
                       TrackingBottomView(trackingViewModel: trackingViewModel)
                   }
               }
               else {
                   Text("Loading...") 
               }
           }
           .onAppear() {
               if !trackingViewModel.identityPoolId.isEmpty {
                   Task {
                       do {
                           try await trackingViewModel.authWithCognito(identityPoolId: trackingViewModel.identityPoolId)
                       }
                       catch {
                           print(error)
                       }
                   }
               }
           }
       }
   }
   ```

1. Add the following code in `TrackingViewModel.swift` file. These functions are responsible for start and stop tracking. It will also show an error alert if user location permission is denied.

1. To implement foreground tracking copy paste the following code example:

   ```
   func showLocationDeniedRationale() {
           alertTitle = NSLocalizedString("locationManagerAlertTitle", comment: "")
           alertMessage = NSLocalizedString("locationManagerAlertText", comment: "")
           showAlert = true
       }
       
       // Required in info.plist: Privacy - Location When In Use Usage Description
       func startTracking() {
           do {
               print("Tracking Started...")
               if(client == nil) {
                   initializeClient()
               }
               try client.startTracking()
               DispatchQueue.main.async { [self] in
                   self.trackingButtonText = NSLocalizedString("StopTrackingLabel", comment: "")
                   self.trackingButtonColor = .red
                   self.trackingButtonIcon = "pause.circle"
                   trackingActive = true
               }
           } catch TrackingLocationError.permissionDenied {
               showLocationDeniedRationale()
           } catch {
               print("error in tracking")
           }
       }
       
       func stopTracking() {
           print("Tracking Stopped...")
           client.stopTracking()
           trackingButtonText = NSLocalizedString("StartTrackingLabel", comment: "")
           trackingButtonColor = .blue
           trackingButtonIcon = "play.circle"
           trackingActive = false
       }
   ```
**Note**  
The `startTracking` will ask for the user's location permission. The application must use **When In Use** or **Only Once** permissions. Otherwise, the application will throw a permission denied error.

To get and display tracking locations, follow this procedure:

1. To get the locations from the user's device, you need to provide the start and end date and time. A single call returns a maximum of 100 tracking locations, but if there are more than 100 tracking locations, it will return a `nextToken` value. You will need to call subsequent `getTrackerDeviceLocation` calls with `nextToken` to load more tracking points for the given start and end time.

   ```
    func getTrackingPoints(nextToken: String? = nil) async throws {
           guard trackingActive else {
               return
           }
           // Initialize startTime to 24 hours ago from the current date and time.
           let startTime: Date = Date().addingTimeInterval(-86400)
           var endTime: Date = Date()
           if lastGetTrackingTime != nil {
               endTime = lastGetTrackingTime!
           }
           let result = try await client?.getTrackerDeviceLocation(nextToken: nextToken, startTime: startTime, endTime: endTime)
           if let trackingData = result {
               
               lastGetTrackingTime = Date()
               let devicePositions = trackingData.devicePositions
   
               let positions = devicePositions!.sorted { (pos1: LocationClientTypes.DevicePosition, pos2: LocationClientTypes.DevicePosition) -> Bool in
                   guard let date1 = pos1.sampleTime,
                         let date2 = pos2.sampleTime else {
                       return false
                   }
                   return date1 < date2
               }
   
               let trackingPoints = positions.compactMap { position -> CLLocationCoordinate2D? in
                   guard let latitude = position.position!.last, let longitude = position.position!.first else {
                       return nil
                   }
                   return CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
               }
               DispatchQueue.main.async {
                   self.mapViewDelegate!.drawTrackingPoints( trackingPoints: trackingPoints)
               }
               if let nextToken = trackingData.nextToken {
                   try await getTrackingPoints(nextToken: nextToken)
               }
           }
       }
   ```

1. Now replace the code in the `MapView.swift` file with the following code:

   ```
   import SwiftUI
   import MapLibre
   
   struct MapView: UIViewRepresentable {
       var onMapViewAvailable: ((MLNMapView) -> Void)?
       var mlnMapView: MLNMapView?
       var trackingViewModel: TrackingViewModel
       
       func makeCoordinator() -> MapView.Coordinator {
           return Coordinator(self, trackingViewModel: trackingViewModel)
       }
       
       func makeUIView(context: Context) -> MLNMapView {
           let styleURL = URL(string: "https://maps.geo.\(trackingViewModel.region).amazonaws.com/maps/v0/maps/\(trackingViewModel.mapName)/style-descriptor")
           let mapView = MLNMapView(frame: .zero, styleURL: styleURL)
           mapView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
           mapView.setZoomLevel(15, animated: true)
           mapView.showsUserLocation = true
           mapView.userTrackingMode = .follow
           context.coordinator.mlnMapView = mapView
           mapView.delegate = context.coordinator
   
           mapView.logoView.isHidden = true
           context.coordinator.addCenterMarker()
           
           onMapViewAvailable?(mapView)
           trackingViewModel.mlnMapView = mapView
           return mapView
       }
       
       func updateUIView(_ uiView: MLNMapView, context: Context) {
       }
       
       class Coordinator: NSObject, MLNMapViewDelegate, MapViewDelegate {
           var control: MapView
           var mlnMapView: MLNMapView?
           var trackingViewModel: TrackingViewModel
           var centerMarker: MLNPointAnnotation?
           
           public init(_ control: MapView, trackingViewModel: TrackingViewModel) {
               self.control = control
               self.trackingViewModel = trackingViewModel
               super.init()
               self.trackingViewModel.mapViewDelegate = self
           }
   
           func mapViewDidFinishRenderingMap(_ mapView: MLNMapView, fullyRendered: Bool) {
               if(fullyRendered) {
                   mapView.accessibilityIdentifier = "MapView"
                   mapView.isAccessibilityElement = false
               }
           }
           
           func addCenterMarker() {
               guard let mlnMapView = mlnMapView else {
                   return
               }
   
               let centerCoordinate = mlnMapView.centerCoordinate
               let marker = MLNPointAnnotation()
               marker.coordinate = centerCoordinate
               marker.accessibilityLabel = "CenterMarker"
               mlnMapView.addAnnotation(marker)
               centerMarker = marker
   
               trackingViewModel.reverseGeocodeCenter(centerCoordinate: centerCoordinate, marker: marker)
           }
           
           func mapView(_ mapView: MLNMapView, regionDidChangeAnimated animated: Bool) {
               if let marker = centerMarker {
                   DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
                       mapView.deselectAnnotation(marker, animated: false)
                       marker.coordinate = mapView.centerCoordinate
                       let centerCoordinate = mapView.centerCoordinate
                       self.trackingViewModel.reverseGeocodeCenter(centerCoordinate: centerCoordinate, marker: marker)
                   }
               }
           }
           
           func mapView(_ mapView: MLNMapView, viewFor annotation: MLNAnnotation) -> MLNAnnotationView? {
               guard let pointAnnotation = annotation as? MLNPointAnnotation else {
                   return nil
               }
   
               let reuseIdentifier: String
               var color: UIColor = .black
               if pointAnnotation.accessibilityLabel == "Tracking" {
                   reuseIdentifier = "TrackingAnnotation"
                   color = UIColor(red: 0.00784313725, green: 0.50588235294, blue: 0.58039215686, alpha: 1)
               } else if pointAnnotation.accessibilityLabel == "LocationChange" {
                   reuseIdentifier = "LocationChange"
                   color = .gray
               } else {
                   reuseIdentifier = "DefaultAnnotationView"
               }
   
               var annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: reuseIdentifier)
   
               if annotationView == nil {
                   if reuseIdentifier != "DefaultAnnotationView" {
                       annotationView = MLNAnnotationView(annotation: annotation, reuseIdentifier: reuseIdentifier)
                       //If point annotation is an uploaded Tracking point the radius is 20 and color is blue, otherwise radius is 10 and color is gray
                       let radius = pointAnnotation.accessibilityLabel == "Tracking" ? 20:10
                       annotationView?.frame = CGRect(x: 0, y: 0, width: radius, height: radius)
                       annotationView?.backgroundColor = color
                       annotationView?.layer.cornerRadius = 10
                       
                       if pointAnnotation.accessibilityLabel == "Tracking" {
                           annotationView?.layer.borderColor = UIColor.white.cgColor
                           annotationView?.layer.borderWidth = 2.0
                           annotationView?.layer.shadowColor = UIColor.black.cgColor
                           annotationView?.layer.shadowOffset = CGSize(width: 0, height: 2)
                           annotationView?.layer.shadowRadius = 3
                           annotationView?.layer.shadowOpacity = 0.2
                           annotationView?.clipsToBounds = false
                       }
                   }
                   else {
                       return nil
                   }
               }
   
               return annotationView
           }
           
           func mapView(_ mapView: MLNMapView, didUpdate userLocation: MLNUserLocation?) {
               if (userLocation?.location) != nil {
                   if trackingViewModel.trackingActive {
                       let point = MLNPointAnnotation()
                       point.coordinate = (userLocation?.location!.coordinate)!
                       point.accessibilityLabel = "LocationChange"
                       mapView.addAnnotation(point)
                       Task {
                           do {
                               try await trackingViewModel.getTrackingPoints()
                           }
                           catch {
                               print(error)
                           }
                       }
                   }
               }
           }
           
           func checkIfTrackingAnnotationExists(on mapView: MLNMapView, at coordinates: CLLocationCoordinate2D) -> Bool {
               let existingAnnotation = mapView.annotations?.first(where: { annotation in
                   guard let annotation = annotation as? MLNPointAnnotation else { return false }
                   return annotation.coordinate.latitude == coordinates.latitude &&
                   annotation.coordinate.longitude == coordinates.longitude && annotation.accessibilityLabel == "Tracking" })
               return existingAnnotation != nil
           }
           
           public func drawTrackingPoints(trackingPoints: [CLLocationCoordinate2D]?) {
               guard let mapView = mlnMapView, let newTrackingPoints = trackingPoints, !newTrackingPoints.isEmpty else {
                   return
               }
   
               let uniqueCoordinates = newTrackingPoints.filter { coordinate in
                   !checkIfTrackingAnnotationExists(on: mapView, at: coordinate)
               }
   
               let points = uniqueCoordinates.map { coordinate -> MLNPointAnnotation in
                   let point = MLNPointAnnotation()
                   point.coordinate = coordinate
                   point.accessibilityLabel = "Tracking"
                   return point
               }
               mapView.addAnnotations(points)
           }
       }
   }
   
   protocol MapViewDelegate: AnyObject {
       func drawTrackingPoints(trackingPoints: [CLLocationCoordinate2D]?)
   }
   ```

To localize string values , use the following procedure.

1. Create and add a new file called `Localizable.xcstrings`.

1. Right-click on the `Localizable.xcstrings` file and open it as **Source Code**.

1. Replace its content with the following:

   ```
   {
     "sourceLanguage" : "en",
     "strings" : {
       "Cancel" : {
         "extractionState" : "manual",
         "localizations" : {
           "en" : {
             "stringUnit" : {
               "state" : "translated",
               "value" : "Cancel"
             }
           }
         }
       },
       "Error" : {
         "extractionState" : "manual",
         "localizations" : {
           "en" : {
             "stringUnit" : {
               "state" : "translated",
               "value" : "Error"
             }
           }
         }
       },
       "Loading..." : {
   
       },
       "locationManagerAlertText" : {
         "extractionState" : "manual",
         "localizations" : {
           "en" : {
             "stringUnit" : {
               "state" : "translated",
               "value" : "Allow \\\"Quick Start App\\\" to use your location"
             }
           }
         }
       },
       "locationManagerAlertTitle" : {
         "extractionState" : "manual",
         "localizations" : {
           "en" : {
             "stringUnit" : {
               "state" : "translated",
               "value" : "We need your location to detect your location in map"
             }
           }
         }
       },
       "NotAllFieldsAreConfigured" : {
         "extractionState" : "manual",
         "localizations" : {
           "en" : {
             "stringUnit" : {
               "state" : "translated",
               "value" : "Not all the fields are configured"
             }
           }
         }
       },
       "OK" : {
         "extractionState" : "manual",
         "localizations" : {
           "en" : {
             "stringUnit" : {
               "state" : "translated",
               "value" : "OK"
             }
           }
         }
       },
       "StartTrackingLabel" : {
         "localizations" : {
           "en" : {
             "stringUnit" : {
               "state" : "translated",
               "value" : "Start Tracking"
             }
           }
         }
       },
       "StopTrackingLabel" : {
         "localizations" : {
           "en" : {
             "stringUnit" : {
               "state" : "translated",
               "value" : "Stop Tracking"
             }
           }
         }
       },
       "Tracking" : {
   
       }
     },
     "version" : "1.0"
   }
   ```

1. Save your files, and build and run your app to preview the functionality.

1. Allow the location permission and tap on the tracking button. The app will start uploading user locations and upload them to the Amazon Location tracker. It will also show user location changes, tracking points, and current address on the map.

Your quick-start application is complete. This tutorial has shown you how to create an iOS application that:
+ Creates a map that users can interact with.
+ Handles several map events associated with the user changing the map view.
+ Calls an Amazon Location Service API, specifically to search the map at a location, using Amazon Location's searchByPosition API.

## What's next
<a name="qs-ios-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.

The source code for this application is available on [GitHub](https://github.com/aws-geospatial/amazon-location-samples-ios/tree/main/quick-start).

To get more out of Amazon Location, you can check out the following resources:
+ Dive deeper into the [concepts of Amazon Location Service](how-it-works.md)
+ Get more information about [how to use Amazon Location features and functionality](using-amazon-location.md)
+ See how to expand on this sample and build more complex applications by looking at [code examples using Amazon Location](samples.md)