Skip to main content
This guide explains, step by step, how to build a voice search experience using the libraries provided by Algolia and Compose UI. This guide walks you through the steps needed to create a full InstantSearch Android experience from scratch. It includes:
  • A search box for users to type queries
  • A list to display search results
  • A list to results
  • Statistics about the search

Before you begin

To use InstantSearch, you need an Algolia account. Sign up for a new account or use the following credentials (which include a pre-loaded dataset of products appropriate for this guide):
  • : latency
  • Search : 1f6fd3a6fb973cb08419fe7d288fa4db
  • name: instant_search

Create a new project and add InstantSearch Android

In Android Studio, create a new project:
  • Select Phone and Tablet template
  • Select Empty Compose Activity screen

Add project dependencies

In your gradle/libs.version.toml file, add the following:
TOML
In your build.gradle.kts file, under the app module, add the following in the dependencies block:
Kotlin
You also need to add dependencies for Paging and extended Material Icons, in gradle/libs.version.toml:
TOML
In build.gradle.kts:
Kotlin
To perform network operations in your application, AndroidManifest.xml must include the following permissions:
XML
Set up kotlinx.serialization by adding the serialization plugin to your build.gradle:
Kotlin

Implementation

Application architecture overview

  • MainActivity: this activity controls displayed views
  • MainViewModel: a ViewModel from Android Architecture Components. The business logic lives here
  • Search: composes the search UI

Define your data class

Define a structure that represents the in your index. For simplicity’s sake, this structure only provides the name of the product. Add the following data class definition to the Product.kt file:
Kotlin

Add search business logic

You need three components for the basic search experience:
  • HitsSearcher performs search requests and obtains search results.
  • SearchBoxConnector handles a textual input and triggers a search request when needed.
  • Paginator displays hits and manages the pagination logic.
The setupConnections method establishes the connections between these components to make them work together seamlessly. The central part of your search experience is the Searcher. The Searcher performs a and obtains search results. Most InstantSearch components connected to the Searcher. In this tutorial you’re targeting one index, so instantiate a HitsSearcher with the proper credentials. Create a new MainViewModel.kt file and add the following:
Kotlin
Most InstantSearch components should connect and disconnect in accordance to the Android Lifecycle to avoid memory leaks. A ConnectionHandler handles a set of Connection s for you: each += call with a component implementing the Connection interface connects it and makes it active. Whenever you want to free resources or deactivate a component, call the disconnect method.
Get an instance of your ViewModel in your MainActivity by adding the following:
Kotlin
A ViewModel is a good place to put your data sources. This way, the data persists during configuration changes. Create a SearchScreen.kt file that holds the search UI. Add a composable function ProductsList to display a list of products, the hit row represented by a column with a Text presenting the name of the item and a Divider:
Kotlin
Complete your search experience by putting the SearchBox and ProductsList views together:
Kotlin
Add the Search composable into the setContent section in MainActivity and pass it your business logic components from MainViewModel:
Kotlin
Launch your app to see the basic search experience in action. You should see that the results are changing on each key stroke.
Screenshot of a mobile app with a search box and product list, including 'Sony - PlayStation 4 (500GB)' and 'Apple® - iPad® mini Wi-Fi - 16GB - White/Silver'.Screenshot of a mobile search interface with 'SearchBox' showing 'Sony' and product suggestions like 'Sony - PlayStation 4 (500GB)'.

Displaying metadata: Stats

To make the search experience more user-friendly, you can give more context about the search results to your users. You can do this with different InstantSearch modules. First, add a statistics component. This component shows the hit count and the request processing time. This gives users a complete understanding of their search, without the need for extra interaction. The StatsConnector extracts the metadata from the search response, and provides an interface to present it to users. Add the StatsConnector to the MainViewModel and connect it to the Searcher.
Kotlin
The StatsConnector receives the search statistics now, but doesn’t display it yet. Create a new composable Stats:
Kotlin
Add the Stats composable into the Column, in the middle of the SearchBox and ProductsList:
Kotlin
Update MainActivity to pass StatsState instance to Search:
Kotlin
Rebuild your app. You should now see updated results and an updated hit count on each keystroke. Screenshot of a mobile app showing a search box and product list with'10000 hits in 1ms' above results.

Filter your results: FacetList

With your app, you can search more than 10,000 products. But, you don’t want to scroll to the bottom of the list to find the exact product you’re looking for. One can more accurately filter the results by making use of the FilterListConnector components. This section explains how to build a filter that allows to filter products by their category. First, add a FilterState component to the MainViewModel. This component provides a convenient way to manage the state of your filters. Add the manufacturer refinement attribute. Next, add the FilterListConnector, which stores the list of facets retrieved with search result. Add the connections between HitsSearcher, FilterState and FilterListConnector.
Kotlin
Create the FacetRow composable to display a facet. The row represented by a column with two Text s for the facet value and count, plus an Icon to display a checkmark for selected facets:
Kotlin
Create the FacetList composable to display facets list. Use a Text for the attribute and a LazyColumn to display FacetRow s:
Kotlin
Put it all together using a ModalBottomSheetLayout:
  • Inside content, put your earlier Search content, add clickable filter Icon to show the facets list
  • Create FacetList inside sheetContent to display your facets list.
Kotlin
Update Search in MainActivity to include the instance of FacetListState from your MainViewModel:
Kotlin
Rebuild your app. Now you see a filter button on top right of your screen. Click it to show the refinements list and select one or more refinements. Dismiss the refinements list to see the changes happening live to your hits.
Screenshot of a mobile search interface showing a list of products with a 'Search' input field and a 'filter' icon.Screenshot of a mobile app's 'Categories' filter menu, showing options like 'Movies and TV Shows' and 'Headphones,' with 'Movies and TV Shows' selected.

Improve the user experience: Hightlighting

Highlighting enhances the user experience by putting emphasis on the parts of the result that match the query. It’s a visual indication of why a result is relevant to the query. You can add highlighting by implementing the Highlightable interface on Product. Define a highlightedName field to retrieve the highlighted value for the name attribute.
Kotlin
Use the .toAnnotatedString() extension function to convert an HighlightedString into a AnnotatedString assignable to a Text to display the highlighted names.
Kotlin
Screenshot of a search interface with 'hello' in the query bar, showing results like 'Hello Kitty - Over-the-Ear Headphones' and other products.

Going further

You now have a fully working search experience: your users can search for products, refine their results, and understand how many records are returned and why they’re relevant to the query. Find the full source code in the GitHub repository.
Last modified on July 22, 2026