Places
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, the plugin offers UI components that you can integrated inside your app with a few lines of code.
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 requests. Use the API response in your Java or Android project. Read more in the Java SDK documentation.
- 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 and place picker example.
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 |
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. You can find all dependencies given below on MavenCentral.
Add the dependency
-
Open Android Studio.
-
Open up your application's
build.gradle
. -
Make sure that your project's
minSdkVersion
is API 14 or higher. -
Under dependencies, add a new build rule for the latest
mapbox-android-plugin-places-v9
.repositories {
mavenCentral()
}
dependencies {
implementation 'com.mapbox.mapboxsdk:mapbox-android-plugin-places-v9:0.12.0'
} -
Declare Java 8 support in the
android { }
block of the application'sbuild.gradle
fileandroid {
// 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"
}
} -
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.
Intent intent = new PlaceAutocomplete.IntentBuilder()
.accessToken(MAPBOX_ACCESS_TOKEN)
.placeOptions(placeOptions)
.build(this);
startActivityForResult(intent, REQUEST_CODE_AUTOCOMPLETE);
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.
@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();
}
}
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 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
.
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);
}
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.
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();
}
});
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.
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();
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.
PlaceAutocomplete.clearRecentHistory(this);
PlaceAutocomplete.clearRecentHistory(this);
Place Picker
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.
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);
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
:
@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);
}
}
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.