HERE Technologies LogoHERE
HERE Technologies LogoHERE
HERE Technologies LogoHERE
SDKs & dev tools

4 min read

28 October 2025

Search for places with the HERE SDK and Jetpack Compose

jetpackSDK1

Introduction

In this tutorial, you will learn how to build a reusable search box with Jetpack Compose, connect it to the `SearchEngine` provided by the HERE SDK for Android, and display results as map markers. This tutorial works with the Explore and the Navigate license.

This is what the completed app looks like

Setting up the map and search engine

Before creating the UI, you need to initialize the HERE SDK in your project and set up a `MapView`. The map will be embedded in a Compose layout using `AndroidView`. For a detailed guide on setting up a MapView with Jetpack Compose, please visit: MapView with Jetpack Compose

Once your map is ready, you can initialize a `SearchEngine` instance, which provides access to HERE’s online search services:

Kotlin
```kotlin
private var searchEngine: SearchEngine? = null
...
private fun initializeSearchEngine() {
try {
searchEngine = SearchEngine()
Log.d(TAG, "Search engine initialized successfully")
} catch (e: Exception) {
Log.e(TAG, "Error initializing search engine: ${e.message}")
}
}
```

Make sure you have valid HERE SDK credentials and that your project is correctly configured according to the HERE SDK setup guide HERE SDK setup guide.

Creating a simple search bar UI

In Jetpack Compose, you can create a search bar with an `OutlinedTextField` that lets users type queries. To make it interactive, track the input using a `remember` state. When the user presses the search button or triggers an action, the app calls the HERE SDK to find places.

Here’s a possible implementation of such a UI component:

Kotlin
```kotlin
@Composable
fun SearchBar(onSearch: (String) -> Unit) {
var query by remember { mutableStateOf("") }
Row(modifier = Modifier.padding(16.dp)) {
OutlinedTextField(
value = query,
onValueChange = { query = it },
label = { Text("Search places...") },
modifier = Modifier.weight(1f)
)
Spacer(Modifier.width(8.dp))
Button(onClick = { onSearch(query) }) {
Text("Search")
}
}
}
```

This `SearchBar` calls the `onSearch()` callback whenever the user initiates a search. You can reuse this component anywhere in your app. Note that we did not integrate suggestion handling into the `SearchBar`. It might be a topic for another blog post as the HERE SDK provides an easy way to search for suggestions while a user is typing.

Performing a text-based search

The HERE SDK’s `SearchEngine` supports text-based searches within a specific geographic area. To get meaningful results, you should define a viewport based on the visible map area. The viewport is represented by a `GeoBox`, which you can calculate from your `MapView`:

Kotlin
```kotlin
val mapViewGeoBox: GeoBox
get() {
val bottomLeft = mapView!!.viewToGeoCoordinates(Point2D(0.0, mapView!!.height.toDouble()))
val topRight = mapView!!.viewToGeoCoordinates(Point2D(mapView!!.width.toDouble(), 0.0))
return GeoBox(bottomLeft!!, topRight!!)
}
```

Once you have the `GeoBox`, perform a search query using the `SearchEngine`:

Kotlin
```kotlin
fun searchPlaces(query: String, geoBox: GeoBox, onResult: (List<Place>) -> Unit, onError: (String) -> Unit) {
val textQuery = TextQuery(query, TextQuery.Area(geoBox))
val options = SearchOptions().apply {
languageCode = LanguageCode.EN_US
maxItems = 20 // Limit results to prevent performance issues
}
searchEngine?.searchByText(textQuery, options, SearchCallback { searchError, places ->
if (searchError != null) {
onError(searchError.name)
return@SearchCallback
}
onResult(places ?: emptyList())
})
}
```

This function uses the HERE SDK to search for places and returns the results asynchronously. You can call it from your Compose UI by passing in the query text.

Displaying search results on the map

After receiving results, it’s good practice to clear any previous markers before adding new ones. Each result can be represented as a `MapMarker` at the returned coordinates. You can also animate the camera to focus on the selected location:

Kotlin
```kotlin
fun addMarkerForPlace(place: Place) {
val coords = place.geoCoordinates ?: return
val image = MapImageFactory.fromResource(resources, R.drawable.poi)
val marker = MapMarker(coords, image, Anchor2D(0.5, 1.0))
mapView!!.mapScene.addMapMarker(marker)
mapView!!.camera.lookAt(coords, MapMeasure(MapMeasure.Kind.DISTANCE_IN_METERS, 8000.0))
}
```

This adds a simple visual marker at the searched location and smoothly adjusts the camera.

Connecting everything together

To make everything work together, combine the `SearchBar` composable and the map in a single screen. When the user performs a search, call the `searchPlaces()` function, then update the map with the results:

Kotlin
```kotlin
@Composable
fun PlaceSearchScreen() {
var results by remember { mutableStateOf<List<Place>>(emptyList()) }
Column(Modifier.fillMaxSize()) {
SearchBar { query ->
val geoBox = mapViewGeoBox
searchPlaces(query, geoBox,
onResult = { places ->
results = places
places.forEach { place ->
addMarkerForPlace(place)
}
},
onError = { Log.e("HERE", it) }
)
}
}
}
```

This creates a simple but functional search experience. The search box sits on top of the map, and each query triggers a HERE SDK search within the visible area.

Our app in action

Our place finder app in action.

Wrapping up

With just a few lines of Kotlin and Jetpack Compose, you can integrate HERE SDK’s `SearchEngine` into your app and create a responsive search interface. The key idea is to separate the search logic from the UI, keeping the search box reusable and independent. From here, you can extend this example by showing search results in a bottom sheet, highlighting selected places, or combining search with routing.

For more advanced scenarios, explore the HERE SDK search documentation HERE SDK search documentation to add features like reverse geocoding, filtering, or offline search.

Portrait of Aaron Falk

Aaron Falk

Principal Developer Evangelist

Share article