How to Use Road Shields with the HERE SDK
Abhishek Kumar — 14 July 2025
4 min read
28 October 2025

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
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```kotlinprivate 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.
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@Composablefun 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.
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```kotlinval 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```kotlinfun 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.
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```kotlinfun 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.
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@Composablefun 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 place finder app in action.
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.

Aaron Falk
Principal Developer Evangelist
Share article
Abhishek Kumar — 14 July 2025
Sachin Jonda — 12 December 2024
Sachin Jonda — 25 November 2024