Automotive Navigation Application

The SearchManager enables developers to search for locations, addresses, and points of interest (POIs). It supports free-text search, category-based filtering, and geographic filtering to help users find destinations.

Overview

SearchManager provides functionality for:

  • Free-text search for addresses and POIs
  • Category-based POI search (restaurants, gas stations, etc.)
  • Brand name filtering
  • Geographic filtering (around position, along route)
  • Result type filtering
  • Paginated results

Perform a simple search with a query string:

import android.util.Log
import com.tomtom.automotive.integration.client.api.model.Coordinate
import com.tomtom.automotive.integration.client.api.model.search.SearchRequest
import com.tomtom.automotive.integration.client.api.model.search.SearchResult
import com.tomtom.automotive.integration.client.api.model.search.filters.GeoFilter
import com.tomtom.automotive.integration.client.api.search.SearchCallback
import com.tomtom.automotive.integration.client.api.search.SearchFailure
import com.tomtom.automotive.integration.client.api.search.SearchManager
import com.tomtom.automotive.integration.client.api.search.SearchParameters
import com.tomtom.automotive.integration.client.api.search.SearchResponse
import com.tomtom.automotive.integration.client.common.Callback
import com.tomtom.automotive.integration.client.common.Result
import com.tomtom.automotive.integration.client.common.SdkReleasable
private val TAG = "Search"
private var searchReleasable: SdkReleasable? = null
fun search(searchManager: SearchManager, query: String, currentPosition: Coordinate) {
val geoFilter = GeoFilter.ByPositionBias(coordinate = currentPosition)
val searchRequest = SearchRequest(
query = query,
resultLimit = 10,
geoFilter = geoFilter,
filters = emptySet(),
pageSize = 5
)
searchReleasable = searchManager.search(
SearchParameters(searchRequest),
object : SearchCallback {
override fun onResult(response: Result<SearchResponse, SearchFailure>) {
when (response) {
is Result.Success -> {
val results = response.value.results
Log.d(TAG, "Found ${results.size} results")
results.forEach { result ->
logSearchResult(result)
}
}
is Result.Failure -> {
Log.e(TAG, "Search failed: ${response.reason}")
}
}
}
override fun onFunctionalityUnavailable(reason: Callback.Reason) {
Log.e(TAG, "Search unavailable: ${reason.devMessage}")
}
}
)
}
private fun logSearchResult(result: SearchResult) {
val coordinate = result.data?.coordinate
when (result) {
is SearchResult.Poi -> Log.d(TAG, "POI: ${result.poiName} at $coordinate")
is SearchResult.Street -> Log.d(TAG, "Street: ${result.address.formattedAddress} at $coordinate")
is SearchResult.Area -> Log.d(TAG, "Area at $coordinate")
else -> Log.d(TAG, "Result at $coordinate")
}
}
fun cancelSearch() {
searchReleasable?.release()
searchReleasable = null
}

Search with location context

Provide current position for better, location-relevant results:

import android.util.Log
import com.tomtom.automotive.integration.client.api.model.Coordinate
import com.tomtom.automotive.integration.client.api.model.quantity.Distance
import com.tomtom.automotive.integration.client.api.model.search.SearchRequest
import com.tomtom.automotive.integration.client.api.model.search.filters.GeoFilter
import com.tomtom.automotive.integration.client.api.search.SearchCallback
import com.tomtom.automotive.integration.client.api.search.SearchFailure
import com.tomtom.automotive.integration.client.api.search.SearchManager
import com.tomtom.automotive.integration.client.api.search.SearchParameters
import com.tomtom.automotive.integration.client.api.search.SearchResponse
import com.tomtom.automotive.integration.client.common.Callback
import com.tomtom.automotive.integration.client.common.Result
private val TAG = "Search"
fun searchNearby(searchManager: SearchManager, query: String, currentPosition: Coordinate) {
// Search within 5000 meters of current position
val geoFilter = GeoFilter.ByRadius(
center = currentPosition,
radius = Distance.meters(5000)
)
val searchRequest = SearchRequest(
query = query,
resultLimit = 20,
geoFilter = geoFilter,
filters = emptySet(),
pageSize = 10
)
searchManager.search(
SearchParameters(searchRequest),
object : SearchCallback {
override fun onResult(response: Result<SearchResponse, SearchFailure>) {
when (response) {
is Result.Success -> {
Log.d(TAG, "Found ${response.value.results.size} nearby results")
}
is Result.Failure -> {
Log.e(TAG, "Nearby search failed: ${response.reason}")
}
}
}
override fun onFunctionalityUnavailable(reason: Callback.Reason) {
Log.e(TAG, "Search unavailable: ${reason.devMessage}")
}
}
)
}

Available geo filters

  • GeoFilter.ByPositionBias - Bias results toward a coordinate
  • GeoFilter.ByRadius - Search within a radius of a coordinate
  • GeoFilter.ByGeoBox - Search within a bounding box
  • GeoFilter.ByRoute - Search for POIs along the active route

Search for POIs by category (e.g., restaurants, gas stations):

import android.util.Log
import com.tomtom.automotive.integration.client.api.model.Coordinate
import com.tomtom.automotive.integration.client.api.model.quantity.Distance
import com.tomtom.automotive.integration.client.api.model.search.SearchRequest
import com.tomtom.automotive.integration.client.api.model.search.filters.GeoFilter
import com.tomtom.automotive.integration.client.api.model.search.filters.SearchFilter
import com.tomtom.automotive.integration.client.api.model.search.poi.PoiCategory
import com.tomtom.automotive.integration.client.api.search.SearchCallback
import com.tomtom.automotive.integration.client.api.search.SearchFailure
import com.tomtom.automotive.integration.client.api.search.SearchManager
import com.tomtom.automotive.integration.client.api.search.SearchParameters
import com.tomtom.automotive.integration.client.api.search.SearchResponse
import com.tomtom.automotive.integration.client.common.Callback
import com.tomtom.automotive.integration.client.common.Result
private val TAG = "Search"
fun searchByCategory(searchManager: SearchManager, categories: Set<PoiCategory>, currentPosition: Coordinate) {
val geoFilter = GeoFilter.ByRadius(
center = currentPosition,
radius = Distance.meters(10000)
)
val filters = setOf(
SearchFilter.ByPoiCategory(categories)
)
val searchRequest = SearchRequest(
query = "",
resultLimit = 30,
geoFilter = geoFilter,
filters = filters,
pageSize = 10
)
searchManager.search(
SearchParameters(searchRequest),
object : SearchCallback {
override fun onResult(response: Result<SearchResponse, SearchFailure>) {
when (response) {
is Result.Success -> {
Log.d(TAG, "Found ${response.value.results.size} category results")
}
is Result.Failure -> {
Log.e(TAG, "Category search failed: ${response.reason}")
}
}
}
override fun onFunctionalityUnavailable(reason: Callback.Reason) {
Log.e(TAG, "Search unavailable: ${reason.devMessage}")
}
}
)
}
// Example: Find petrol stations
// searchByCategory(searchManager, setOf(PoiCategory.PETROL_STATION), currentPosition)

Filtering by brand name

Search for specific brands:

import android.util.Log
import com.tomtom.automotive.integration.client.api.model.Coordinate
import com.tomtom.automotive.integration.client.api.model.quantity.Distance
import com.tomtom.automotive.integration.client.api.model.search.SearchRequest
import com.tomtom.automotive.integration.client.api.model.search.filters.GeoFilter
import com.tomtom.automotive.integration.client.api.model.search.filters.SearchFilter
import com.tomtom.automotive.integration.client.api.search.SearchCallback
import com.tomtom.automotive.integration.client.api.search.SearchFailure
import com.tomtom.automotive.integration.client.api.search.SearchManager
import com.tomtom.automotive.integration.client.api.search.SearchParameters
import com.tomtom.automotive.integration.client.api.search.SearchResponse
import com.tomtom.automotive.integration.client.common.Callback
import com.tomtom.automotive.integration.client.common.Result
private val TAG = "Search"
fun searchByBrand(searchManager: SearchManager, brandNames: Set<String>, currentPosition: Coordinate) {
val geoFilter = GeoFilter.ByRadius(
center = currentPosition,
radius = Distance.meters(15000)
)
val filters = setOf(
SearchFilter.ByBrandName(brandNames)
)
val searchRequest = SearchRequest(
query = "coffee",
resultLimit = 20,
geoFilter = geoFilter,
filters = filters,
pageSize = 5
)
searchManager.search(
SearchParameters(searchRequest),
object : SearchCallback {
override fun onResult(response: Result<SearchResponse, SearchFailure>) {
when (response) {
is Result.Success -> {
Log.d(TAG, "Found ${response.value.results.size} brand results")
}
is Result.Failure -> {
Log.e(TAG, "Brand search failed: ${response.reason}")
}
}
}
override fun onFunctionalityUnavailable(reason: Callback.Reason) {
Log.e(TAG, "Search unavailable: ${reason.devMessage}")
}
}
)
}
// Example: Find Starbucks locations
// searchByBrand(searchManager, setOf("Starbucks"), currentPosition)

Result type filtering

Filter results by type (POI, street, coordinate, etc.):

import android.util.Log
import com.tomtom.automotive.integration.client.api.model.Coordinate
import com.tomtom.automotive.integration.client.api.model.quantity.Distance
import com.tomtom.automotive.integration.client.api.model.search.SearchRequest
import com.tomtom.automotive.integration.client.api.model.search.filters.GeoFilter
import com.tomtom.automotive.integration.client.api.model.search.filters.SearchFilter
import com.tomtom.automotive.integration.client.api.model.search.filters.SearchResultType
import com.tomtom.automotive.integration.client.api.search.SearchCallback
import com.tomtom.automotive.integration.client.api.search.SearchFailure
import com.tomtom.automotive.integration.client.api.search.SearchManager
import com.tomtom.automotive.integration.client.api.search.SearchParameters
import com.tomtom.automotive.integration.client.api.search.SearchResponse
import com.tomtom.automotive.integration.client.common.Callback
import com.tomtom.automotive.integration.client.common.Result
private val TAG = "Search"
fun searchPOIsOnly(searchManager: SearchManager, query: String, currentPosition: Coordinate) {
val geoFilter = GeoFilter.ByRadius(
center = currentPosition,
radius = Distance.meters(5000)
)
val filters = setOf(
SearchFilter.ByResultType(setOf(SearchResultType.POI))
)
val searchRequest = SearchRequest(
query = query,
resultLimit = 15,
geoFilter = geoFilter,
filters = filters,
pageSize = 5
)
searchManager.search(
SearchParameters(searchRequest),
object : SearchCallback {
override fun onResult(response: Result<SearchResponse, SearchFailure>) {
when (response) {
is Result.Success -> {
Log.d(TAG, "Found ${response.value.results.size} POI results")
}
is Result.Failure -> {
Log.e(TAG, "POI search failed: ${response.reason}")
}
}
}
override fun onFunctionalityUnavailable(reason: Callback.Reason) {
Log.e(TAG, "Search unavailable: ${reason.devMessage}")
}
}
)
}

Available result types

  • SearchResultType.POI - Points of interest
  • SearchResultType.STREET - Street addresses
  • SearchResultType.COORDINATE - Geographic coordinates
  • SearchResultType.INTERSECTION - Street intersections
  • SearchResultType.AREA - An area on map which represents administrative division of a land i.e. country, state, city.

Parsing search results

Handle different types of search results:

import android.util.Log
import com.tomtom.automotive.integration.client.api.model.search.SearchResult
private val TAG = "Search"
fun handleSearchResult(result: SearchResult) {
val coordinate = result.data?.coordinate
val areas = result.data?.areas ?: emptyList()
when (result) {
is SearchResult.Poi -> {
val name = result.poiName
val address = result.address
val poiDetails = result.poiDetails
Log.d(TAG, "POI: $name at $coordinate")
Log.d(TAG, "Address: ${address.formattedAddress}")
poiDetails?.let {
val phone = it.phone
val website = it.website
val categories = it.category
Log.d(TAG, "Phone: $phone, Website: $website")
Log.d(TAG, "Categories: $categories")
}
}
is SearchResult.Street -> {
val address = result.address
Log.d(TAG, "Street: ${address.formattedAddress} at $coordinate")
}
is SearchResult.Coordinate -> {
val address = result.address
Log.d(TAG, "Coordinate: $coordinate, Address: ${address.formattedAddress}")
}
is SearchResult.Area -> {
Log.d(TAG, "Area at $coordinate, areas: $areas")
}
is SearchResult.Intersection -> {
val address = result.address
Log.d(TAG, "Intersection: ${address.formattedAddress} at $coordinate")
}
else -> {
Log.d(TAG, "Unhandled result type")
}
}
}

Converting results to navigable locations

Use search results for trip planning:

import com.tomtom.automotive.integration.client.api.model.Address
import com.tomtom.automotive.integration.client.api.model.NavigableLocation
import com.tomtom.automotive.integration.client.api.model.search.AddressData
import com.tomtom.automotive.integration.client.api.model.search.SearchResult
fun toNavigableLocation(result: SearchResult): NavigableLocation.Place? {
val coordinate = result.data?.coordinate ?: return null
return when (result) {
is SearchResult.Poi -> {
NavigableLocation.Place(
coordinate = coordinate,
address = result.address.toAddress(),
name = result.poiName,
poiDetails = result.poiDetails
)
}
is SearchResult.Street -> {
NavigableLocation.Place(
coordinate = coordinate,
address = result.address.toAddress(),
name = result.address.formattedAddress
)
}
is SearchResult.Coordinate -> {
NavigableLocation.Place(
coordinate = coordinate,
address = result.address.toAddress()
)
}
else -> {
NavigableLocation.Place(
coordinate = coordinate,
address = null
)
}
}
}
private fun AddressData.toAddress(): Address {
return Address(
houseNumber = houseNumber,
streetName = streetNames.firstOrNull(),
cityName = null,
postalCode = extendedPostalCode,
stateName = null,
stateCode = null,
cityDistrict = null,
countryName = null,
countryCode = null,
extendedPostalCode = extendedPostalCode,
formattedAddress = formattedAddress
)
}

Reverse geocoding

The ReverseGeocoderManager converts geographic coordinates into human-readable addresses and place information.

Convert coordinate to address

import android.util.Log
import com.tomtom.automotive.integration.client.api.model.Coordinate
import com.tomtom.automotive.integration.client.api.model.NavigableLocation
import com.tomtom.automotive.integration.client.api.reversegeocoder.ReverseGeocoderManager
import com.tomtom.automotive.integration.client.api.reversegeocoder.getplacesforcoordinate.GetPlacesForCoordinateCallback
import com.tomtom.automotive.integration.client.api.reversegeocoder.getplacesforcoordinate.GetPlacesForCoordinateFailure
import com.tomtom.automotive.integration.client.api.reversegeocoder.getplacesforcoordinate.GetPlacesForCoordinateParameters
import com.tomtom.automotive.integration.client.api.reversegeocoder.getplacesforcoordinate.GetPlacesForCoordinateResponse
import com.tomtom.automotive.integration.client.common.Callback
import com.tomtom.automotive.integration.client.common.Result
import com.tomtom.automotive.integration.client.common.SdkReleasable
private val TAG = "ReverseGeocoder"
private var reverseGeocoderReleasable: SdkReleasable? = null
fun reverseGeocode(reverseGeocoderManager: ReverseGeocoderManager, coordinate: Coordinate) {
val parameters = GetPlacesForCoordinateParameters(coordinate = coordinate)
reverseGeocoderReleasable = reverseGeocoderManager.getPlacesForCoordinate(
parameters,
object : GetPlacesForCoordinateCallback {
override fun onGeocoderResult(
result: Result<GetPlacesForCoordinateResponse, GetPlacesForCoordinateFailure>
) {
when (result) {
is Result.Success -> {
val places = result.value.places
when {
places.isEmpty() -> {
Log.d(TAG, "No places found for coordinate")
}
places.size == 1 -> {
Log.d(TAG, "Found place: ${places.first().name}")
logPlace(places.first())
}
else -> {
Log.d(TAG, "Found ${places.size} places")
places.forEach { place -> logPlace(place) }
}
}
}
is Result.Failure -> {
when (result.reason) {
GetPlacesForCoordinateFailure.INTERNAL_ERROR -> {
Log.e(TAG, "Reverse geocoding failed: Internal error")
}
GetPlacesForCoordinateFailure.UNHANDLED -> {
Log.e(TAG, "Reverse geocoding failed: Unhandled error")
}
}
}
}
}
override fun onFunctionalityUnavailable(reason: Callback.Reason) {
Log.e(TAG, "Reverse geocoding unavailable: ${reason.devMessage}")
}
}
)
}
private fun logPlace(place: NavigableLocation.Place) {
Log.d(TAG, "Name: ${place.name}")
Log.d(TAG, "Coordinate: ${place.coordinate}")
place.address?.let {
Log.d(TAG, "Address: ${it.formattedAddress}")
Log.d(TAG, "Street: ${it.streetName} ${it.houseNumber ?: ""}")
Log.d(TAG, "City: ${it.cityName}, ${it.postalCode}")
}
}
fun cancelReverseGeocode() {
reverseGeocoderReleasable?.release()
reverseGeocoderReleasable = null
}

The response contains a list of NavigableLocation.Place objects which may be empty (no data available), contain a single place (typical case), or contain multiple places.

Paginated results

Fetch additional results using pagination:

import android.util.Log
import com.tomtom.automotive.integration.client.api.search.SearchCallback
import com.tomtom.automotive.integration.client.api.search.SearchFailure
import com.tomtom.automotive.integration.client.api.search.SearchManager
import com.tomtom.automotive.integration.client.api.search.SearchResponse
import com.tomtom.automotive.integration.client.api.search.nextpage.GetNextPageParameters
import com.tomtom.automotive.integration.client.common.Callback
import com.tomtom.automotive.integration.client.common.Result
private val TAG = "Search"
fun getNextPage(searchManager: SearchManager, searchSessionId: String) {
searchManager.getNextPage(
GetNextPageParameters(searchSessionId),
object : SearchCallback {
override fun onResult(response: Result<SearchResponse, SearchFailure>) {
when (response) {
is Result.Success -> {
val additionalResults = response.value.results
val hasMore = response.value.hasMoreData
Log.d(TAG, "Fetched ${additionalResults.size} more results, hasMore: $hasMore")
}
is Result.Failure -> {
Log.e(TAG, "Failed to fetch next page: ${response.reason}")
}
}
}
override fun onFunctionalityUnavailable(reason: Callback.Reason) {
Log.e(TAG, "Search unavailable: ${reason.devMessage}")
}
}
)
}
// Example usage with searchSessionId from initial search response:
// if (searchResponse.hasMoreData) {
// getNextPage(searchManager, searchResponse.searchSessionId)
// }