# Places

> **Note (legacy): Not compatible with the Maps SDK v10**
> 
> This plugin is not compatible with the Maps SDK v10 or higher. To add search functionality to an application using the Maps SDK v10 and higher, see the [Search SDK for Android](https://docs.mapbox.com/android/search/guides/) documentation.

The **Places Plugin for Android** lets users search for a destination, explore what's nearby, or find their favorite restaurants, coffee shops, or stores. Built on top of the [Mapbox Geocoding API](https://docs.mapbox.com/api/search/geocoding/), the plugin offers UI components that you can integrated inside your app with a few lines of code.

![](https://docs.mapbox.com/android/assets/ideal-img/plugins-overview-places-splash.5a5d032.480.png)

## Search options

Mapbox provides two options for adding location search into your Android application:

-   **Java SDK**: The Java SDK includes a Java wrapper for building [Mapbox Geocoding API](https://docs.mapbox.com/api/search/) requests. Use the API response in your Java or Android project. Read more in the [Java SDK documentation](https://docs.mapbox.com/android/java/guides/services/geocoder/).
-   **Places Plugin for Android**: This plugin is a wrapper *around* the Mapbox Java SDK's Geocoding API that also provides a search UI. View the [Places Plugin example](https://docs.mapbox.com/android/legacy/plugins/examples/global-location-search/) and [place picker example](https://docs.mapbox.com/android/legacy/plugins/examples/place-picker/).

Each option provides a different set of features:

| Feature | Java SDK | Places Plugin |
| --- | --- | --- |
| Foward geocoding |  |  |
| Reverse geocoding |  |  |
| Access to raw Geocoding API response |  |  |
| Drop-in search bar UI |  |  |
| Built-in dropdown list of search results |  |  |
| Place picker |  |  |
| View results in a separate activity or fragment |  |  |

> **Note: Forward and reverse geocoding**
> 
> Both the **Java SDK** and the **Places Plugin** enable you to make forward and reverse geocoding queries to the Mapbox Geocoding API, but the two differ in their flexibility and the query methods. As a reminder, a forward geocoding query converts a text query into geographic coordinates. Reverse geocoding turns geographic coordinates into geographical information (for example, address, place name, place category, and geometry type).

## Install the Places Plugin

To start developing an application using the Places Plugin, you'll need to add the appropriate dependencies inside your `build.gradle` file. This dependency includes the Maps SDK for Android and the [Mapbox Java SDK's Geocoding API](https://docs.mapbox.com/android/java/guides/services/geocoder/). You can find all dependencies given below on MavenCentral.

> **Note: Android's 64K method count limit**
> 
> If your application is over the 64K method limit, you can [shrink, obfuscate, and optimize your code](https://developer.android.com/studio/build/shrink-code) with R8 or ProGuard. If those steps do not lower your method count below 64K, you can also [enable multidex](https://developer.android.com/studio/build/multidex).

### Add the dependency

1.  Open Android Studio.
    
2.  Open up your application's `build.gradle`.
    
3.  Make sure that your project's `minSdkVersion` is API 14 or higher.
    
4.  Under dependencies, add a new build rule for the latest `mapbox-android-plugin-places-v9`.
    
    ```groovy
    repositories {
      mavenCentral()
    }
    
    dependencies {
      implementation 'com.mapbox.mapboxsdk:mapbox-android-plugin-places-v9:0.12.0'
    }
    ```
    
5.  Declare Java 8 support in the `android { }` block of the application's `build.gradle` file
    
    ```groovy
    android {
      // Configure only for each module that uses Java 8
      // language features (either in its source code or
      // through dependencies).
      compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
      }
      // For Kotlin projects
      kotlinOptions {
        jvmTarget = "1.8"
      }
    }
    ```
    
6.  Click the `Sync Project with Gradle Files` link near in the upper right hand corner of Android Studio.
    

## Add Autocomplete

The **Autocomplete** UI component offers users the ability to search addresses or places and receive information including the latitude and longitude, phone number, categories, and plenty of other information. As the user types, place predictions display at once to the user along with any searched places.

There are two ways to use the Autocomplete service:

-   Launch as an activity for result
-   Display as a fragment

### Launch as an activity for result

If a separate search activity makes sense in your application, you can use the `PlaceAutocomplete` class to build your intent and then launch the included search activity using `startActivityForResult`. Using this intent builder, you pass in the required access token along with a `placeOptions` object.

**Java**

```java

Intent intent = new PlaceAutocomplete.IntentBuilder()
	.accessToken(MAPBOX_ACCESS_TOKEN)
	.placeOptions(placeOptions)
	.build(this);
startActivityForResult(intent, REQUEST_CODE_AUTOCOMPLETE);
```

**Kotlin**

```kt

val intent = PlaceAutocomplete.IntentBuilder()
	.accessToken(MAPBOX_ACCESS_TOKEN)
	.placeOptions(placeOptions)
	.build(this)
startActivityForResult(intent, REQUEST_CODE_AUTOCOMPLETE)
```

When the user finishes selecting a place inside the autocomplete activity, `finish()` will be called. To receive the `CarmenFeature` which describes the place the user selected, override the `onActivityResult` method, check that the request and result codes are correct, and use the `PlaceAutocomplete` static method `getPlace` passing in the intent.

**Java**

```java

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  super.onActivityResult(requestCode, resultCode, data);
  if (resultCode == Activity.RESULT_OK && requestCode == REQUEST_CODE_AUTOCOMPLETE) {
    CarmenFeature feature = PlaceAutocomplete.getPlace(data);
    Toast.makeText(this, feature.text(), Toast.LENGTH_LONG).show();
  }
}
```

**Kotlin**

```kt

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent) {
	super.onActivityResult(requestCode, resultCode, data)
		if (resultCode == Activity.RESULT_OK && requestCode == REQUEST_CODE_AUTOCOMPLETE) {
	    val feature = PlaceAutocomplete.getPlace(data)
	    Toast.makeText(this, feature.text(), Toast.LENGTH_LONG).show()
		}
}
```

### Display as a fragment

If you need more control over the UI and would like to place the Autocomplete component inside an activity container, you can use the provided `PlaceAutocompleteFragment` to include the search UI. This class extends the [Support Library Fragment](https://developer.android.com/reference/android/support/v4/app/Fragment.html) implementation, which means the `SupportFragmentManager` should be used. In the code snippet provided below, it checks to make sure no more than one `autocompleteFragment` instance is always being used. If there isn't an instance of `autocompleteFragment`, it creates a new one and adds it to the container. If there is, it displays the `autocompleteFragment` to the user using the `TAG`.

**Java**

```java

PlaceAutocompleteFragment autocompleteFragment;

if (savedInstanceState == null) {
	autocompleteFragment = PlaceAutocompleteFragment.newInstance("<access_token>");

final FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.add(R.id.fragment_container, autocompleteFragment,TAG);
transaction.commit();

} else {
  autocompleteFragment = (PlaceAutocompleteFragment)
  getSupportFragmentManager().findFragmentByTag(TAG);
}

```

**Kotlin**

```kt

val autocompleteFragment: PlaceAutocompleteFragment

if (savedInstanceState == null) {

autocompleteFragment = PlaceAutocompleteFragment.newInstance("<access_token>")
val transaction = supportFragmentManager.beginTransaction()
transaction.add(R.id.fragment_container, autocompleteFragment, TAG)
transaction.commit()

} else {
	autocompleteFragment = supportFragmentManager.findFragmentByTag(TAG) as PlaceAutocompleteFragment
}
```

To listen for when the user selects a place or cancels out of the `autocompleteFragment`, you can set a `PlaceSelectionListener` on the fragment and the callback will be invoked when the event occurs.

**Java**

```java

autocompleteFragment.setOnPlaceSelectedListener(new PlaceSelectionListener() {
  @Override
  public void onPlaceSelected(CarmenFeature carmenFeature) {
    Toast.makeText(AutocompleteFragmentActivity.this,
      carmenFeature.text(), Toast.LENGTH_LONG).show();
    finish();
  }

  @Override
  public void onCancel() {
    finish();
  }
});
```

**Kotlin**

```kt

 autocompleteFragment.setOnPlaceSelectedListener(object : PlaceSelectionListener {
	override fun onPlaceSelected(carmenFeature: CarmenFeature) {
	    Toast.makeText(this@AutocompleteFragmentActivity,
	            carmenFeature.text(), Toast.LENGTH_LONG).show()
	    finish()
	}

	override fun onCancel() {
	    finish()
	}
})         
```

## Customize Autocomplete results

Create a `PlaceOptions` object to customize the Autocomplete search results and the UI component.

Once your `PlaceOptions` object's created you'll need to pass it in either by using the `PlaceAutocompleteFragment.newInstance(<access token>, placeOptions);` if you are using the fragment or `new PlaceAutocomplete.IntentBuilder().placeOptions(placeOptions)` otherwise.

### Customize search results

You can narrow the search results based on the following parameters:

| API | Description |
| --- | --- |
| `proximity` | Bias local results based on a provided GeoJSON Point. This oftentimes increases accuracy in the returned results. |
| `limit` | Limit the number of results returned. The default is 10. |
| `bbox` | Limit results to a bounding box. |
| `geocodingTypes` | Optional, use to filter the results returned inside the suggestions. |
| `country` | Limit results to one or more countries. |
| `injectedPlaces` | Optionally inject Carmen Features into the suggestion view so users can access points of interest quickly without typing a single character. Typical places include, the users home, work, or favorite POI. |

### Customize the UI component

There are two modes to further change the Autocomplete component UI to fit your app better:

-   **Full screen mode**: will place all the search history, results, and injected places into a view which has a width equal to the app width.
-   **Card view mode**: the place search history, results, and injected places in an Android Support Library CardView.

| API | Description |
| --- | --- |
| `backgroundColor` | Set the autocomplete's layout background color. |
| `toolbarColor` | The autocomplete's layout toolbar color. This only applies if the mode is full screen. |

### Add suggestions

When users are searching for places inside your app, oftentimes, they have a few places that are visited often and thus searched. Make things simpler for them by adding specific place suggestions such as their home, work, or favorite restaurant. This feature can also be used to insert store locations, or popular places your app is advertising.

To get started, you'll need to first get or create the `CarmenFeature` which describes this place. See an example of creating a `CarmenFeature` below which only includes the necessary information for your app, neglecting the large amount of additional information you could provide to describe the location.

**Java**

```java

CarmenFeature work = CarmenFeature.builder().text("Directions to Work")
  .geometry(Point.fromLngLat(1.0, 2.0))
  .placeName("300 Massachusetts Ave NW")
  .id("directions-work")
  .properties(new JsonObject())
  .build();
```

**Kotlin**

```kt

val work = CarmenFeature.builder().text("Directions to Work")
	.geometry(Point.fromLngLat(1.0, 2.0))
	.placeName("300 Massachusetts Ave NW")
	.id("directions-work")
	.properties(JsonObject())
	.build()
```

Once complete, you will need to pass this feature into the `PlaceOptions` object using either the `addInjectedFeature()` or `injectedPlaces()` methods.

## Clear search history

Typically found inside any application which offers search history like the places plugin does by default, they will also need to occasionally clear the search history. It's recommended to add a setting in your apps preferences to do this. If the user request clearing of the search history, you can use the static method provided inside the `PlaceAutocomplete` class called `clearRecentHistory()` which will clear all the data from the saved database at once.

**Java**

```java

PlaceAutocomplete.clearRecentHistory(this);
```

**Kotlin**

```kt

PlaceAutocomplete.clearRecentHistory(this);
```

## Place Picker

![](https://docs.mapbox.com/android/assets/ideal-img/plugins-overview-place-picker-android.5356f4e.480.png)

The Autocomplete UI component described above, searches for a place based on an address or name. The **Place Picker** UI component retrieves information about a selected map location. With the Place Picker, you can launch an activity for result and provide your users with a way to pick a visual location on the map. The result returned is a `CarmenFeature`, which can be used to get information such as the coordinate, place name, address, phone number, and more.

To begin, create the Place Picker `IntentBuilder`, which builds an intent ready to be launched by the `startActivityForResult` method.

**Java**

```java

private static final int PLACE_SELECTION_REQUEST_CODE = 56789

...

Intent intent = new PlacePicker.IntentBuilder()
  .accessToken(Mapbox.getAccessToken())
  .placeOptions(
		PlacePickerOptions.builder()
			.statingCameraPosition(
				new CameraPosition.Builder()
		        .target(new LatLng(40.7544, -73.9862))
		        .zoom(16)
		      	.build())
    	.build())
.build(this);
startActivityForResult(intent, PLACE_SELECTION_REQUEST_CODE);
```

**Kotlin**

```kt

companion object {
	private val PLACE_SELECTION_REQUEST_CODE = 56789
}
...

val intent = PlacePicker.IntentBuilder()
	.accessToken(Mapbox.getAccessToken()!!)
	.placeOptions(
	PlacePickerOptions.builder()
	.statingCameraPosition(
		CameraPosition.Builder()
			.target(LatLng(40.7544, -73.9862))
			.zoom(16.0)
			.build())
		.build())
	.build(this)
startActivityForResult(intent, PLACE_SELECTION_REQUEST_CODE)
```

Override the `onActivityResult()` method and extract information from the `CarmenFeature`:

**Java**

```java

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data);

	if (requestCode == REQUEST_CODE && resultCode == RESULT_OK){

	// Retrieve the information from the selected location's CarmenFeature

	CarmenFeature carmenFeature = PlacePicker.getPlace(data);
	}
}
```

**Kotlin**

```kt

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent) { super.onActivityResult(requestCode, resultCode, data)

	if (requestCode == REQUEST_CODE && resultCode == Activity.RESULT_OK) {

	// Retrieve the information from the selected location's CarmenFeature

	val carmenFeature = PlacePicker.getPlace(data)

   }
}
```

If you'd like to show the Place Picker UI without any geocoding information, use the `PlacePickerOptions` class' `includeReverseGeocode()` method. This method takes a boolean parameter and if `false` is passed through, makes no geocoding call. The selected location's coordinates will be returned in the `onActivityResult` callback, rather than a geocoding result's `CarmenFeature`.

You might want an app user to choose a precise location. For example, the user needs to choose a place on the map to share with friends. But, as an app developer, you don't care about the geocoding metadata associated with those coordinates. Your app needs a way for a user to pick the place so that the coordinates can be used. A new geocoding call happens every time the map is moved with the Place Picker Plugin. These constant geocoding calls are billed to your Mapbox account. Using `includeReverseGeocode(false)` would provide the UI that you truly need and save you money.

### `PlaceOptions` for Place Picker

Besides some of the options listed in the `PlaceOptions` documentation above, the Place Picker includes options for setting the initial map camera position. This is useful when you want the map location to start at the user's current location.