> ## Documentation Index
> Fetch the complete documentation index at: https://algolia.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Upgrading InstantSearch Android

> Upgrade your InstantSearch Android version

## Upgrade from InstantSearch v3 to v4

In InstantSearch v4.0.0 and later, InstantSearch uses Kotlin 2.2 and the Algolia Kotlin API client 3.x.
This client updates models and simplifies types.

```kotlin Kotlin icon=code theme={"system"}
val searcher = HitsSearcher(
  applicationID = "ALGOLIA_APPLICATION_ID",
  apiKey = "ALGOLIA_SEARCH_API_KEY",
  indexName = "indexName",
  isAutoSendingHitsViewEvents = true
)
```

<Warning>
  InstantSearch v4.0 is a major upgrade and includes breaking changes.
  It removes wrapper types and legacy searchers (Answers and Places), and updates Insights to v3 events.
</Warning>

## Requirements

InstantSearch Android 4.x has updated minimum requirements:

| Requirement          | 3.x  | 4.x  |
| -------------------- | ---- | ---- |
| Kotlin               | 1.9+ | 2.2+ |
| Android `minSdk`     | 21   | 23   |
| Android `compileSdk` | 33   | 35   |
| Ktor                 | 2.3  | 3.3  |
| Algolia client       | 2.x  | 3.x  |

## Wrapper types removed

The Kotlin API client 3.x removed primitive wrapper types. Use plain `String` values instead:

| Type           | 3.x                    | 4.x     |
| -------------- | ---------------------- | ------- |
| Application ID | `ApplicationID("...")` | `"..."` |
| API key        | `APIKey("...")`        | `"..."` |
| Index name     | `IndexName("...")`     | `"..."` |
| Attribute      | `Attribute("...")`     | `"..."` |
| Object ID      | `ObjectID("...")`      | `"..."` |
| Query ID       | `QueryID("...")`       | `"..."` |
| Event name     | `EventName("...")`     | `"..."` |
| User token     | `UserToken("...")`     | `"..."` |

<CodeGroup>
  ```kotlin Before 3.x theme={"system"}
  val searcher = HitsSearcher(
      applicationID = ApplicationID("YourApplicationID"),
      apiKey = APIKey("YourSearchOnlyAPIKey"),
      indexName = IndexName("index_name")
  )
  ```

  ```kotlin After 4.x theme={"system"}
  val searcher = HitsSearcher(
      applicationID = "YourApplicationID",
      apiKey = "YourSearchOnlyAPIKey",
      indexName = "index_name"
  )
  ```
</CodeGroup>

## Search parameters

Replaces the `Query` class with `SearchParamsObject` from the Algolia Kotlin Client 3.x:

| Type              | 3.x                | 4.x                       |
| ----------------- | ------------------ | ------------------------- |
| Query             | `Query(...)`       | `SearchParamsObject(...)` |
| Search parameters | `SearchParameters` | `SearchParamsObject`      |

<CodeGroup>
  ```kotlin Before 3.x theme={"system"}
  val query = Query(analytics = false)
  val searcher = HitsSearcher(
      applicationID = ApplicationID("YourApplicationID"),
      apiKey = APIKey("YourSearchOnlyAPIKey"),
      indexName = IndexName("index_name"),
      query = query
  )
  ```

  ```kotlin After 4.x theme={"system"}
  val query = SearchParamsObject(analytics = false)
  val searcher = HitsSearcher(
      applicationID = "YourApplicationID",
      apiKey = "YourSearchOnlyAPIKey",
      indexName = "index_name",
      query = query
  )
  ```
</CodeGroup>

## Response types

Search response types have been updated to match the Kotlin API client 3.x:

| Type            | 3.x                       | 4.x                            |
| --------------- | ------------------------- | ------------------------------ |
| Search response | `ResponseSearch`          | `SearchResponse`               |
| Facets response | `ResponseSearchForFacets` | `SearchForFacetValuesResponse` |
| Facet           | `Facet`                   | `FacetHits`                    |

<CodeGroup>
  ```kotlin Before 3.x theme={"system"}
  val facet = Facet("red", 10)
  ```

  ```kotlin After 4.x theme={"system"}
  val facet = FacetHits("red", "", 10)
  ```
</CodeGroup>

## Filters

InstantSearch now owns its own filter model. Update your imports:

| Type            | 3.x                                               | 4.x                                                |
| --------------- | ------------------------------------------------- | -------------------------------------------------- |
| Filter          | `com.algolia.search.model.filter.Filter`          | `com.algolia.instantsearch.filter.Filter`          |
| FilterGroup     | `com.algolia.search.model.filter.FilterGroup`     | `com.algolia.instantsearch.filter.FilterGroup`     |
| NumericOperator | `com.algolia.search.model.filter.NumericOperator` | `com.algolia.instantsearch.filter.NumericOperator` |

<CodeGroup>
  ```kotlin Before 3.x theme={"system"}
  Filter.Facet(Attribute("color"), "red")
  ```

  ```kotlin After 4.x theme={"system"}
  Filter.Facet("color", "red")
  ```
</CodeGroup>

## Request options

`RequestOptions` uses immutable construction from the Algolia Kotlin Client 3.x:

<CodeGroup>
  ```kotlin Before 3.x theme={"system"}
  val requestOptions = RequestOptions().also {
      it.headers[KeyForwardedFor] = "1.2.3.4"
  }
  ```

  ```kotlin After 4.x theme={"system"}
  val requestOptions = RequestOptions(
      headers = mapOf("X-Forwarded-For" to "1.2.3.4")
  )
  ```
</CodeGroup>

## Insights

Insights has been updated to use v3 events and the `pushEvents` API:

| Type               | 3.x                        | 4.x                 |
| ------------------ | -------------------------- | ------------------- |
| Event construction | `InsightsEvent.Click(...)` | Direct method calls |
| Event names        | `EventName("...")`         | `"..."`             |
| User tokens        | `UserToken("...")`         | `"..."`             |

<CodeGroup>
  ```kotlin Before 3.x theme={"system"}
  sharedInsights?.clicked(
      InsightsEvent.Click(
          eventName = EventName("eventName"),
          indexName = IndexName("indexName"),
          userToken = UserToken("userToken"),
          timestamp = System.currentTimeMillis(),
          queryID = QueryID("queryId"),
          resources = InsightsEvent.Resources.ObjectIDs(
              listOf(ObjectID("objectID1"))
          )
      )
  )
  ```

  ```kotlin After 4.x theme={"system"}
  sharedInsights?.clickedObjectIDsAfterSearch(
      eventName = "eventName",
      indexName = "indexName",
      userToken = "userToken",
      timestamp = System.currentTimeMillis(),
      queryID = "queryId",
      objectIDs = listOf("objectID1"),
      positions = listOf(1)
  )
  ```
</CodeGroup>

## Trackers

Tracker initialization now uses `String` for event names:

<CodeGroup>
  ```kotlin Before 3.x theme={"system"}
  val hitsTracker = HitsTracker(
      eventName = EventName("hits"),
      searcher = searcher,
      insights = sharedInsights(indexName)
  )
  ```

  ```kotlin After 4.x theme={"system"}
  val hitsTracker = HitsTracker(
      eventName = "hits",
      searcher = searcher,
      insights = sharedInsights(indexName)
  )
  ```
</CodeGroup>

## Indexable interface

Hit models for tracking must implement the `Indexable` interface:

```kotlin Kotlin icon=code theme={"system"}
import com.algolia.instantsearch.core.Indexable

data class Product(
    override val objectID: String,
    val name: String
) : Indexable
```

## Removed features

The following features have been removed in v4:

| Feature                                       | Status                                  |
| --------------------------------------------- | --------------------------------------- |
| `SearcherAnswers`                             | Removed (Answers deprecated by Algolia) |
| `SearcherPlaces`                              | Removed (Places deprecated by Algolia)  |
| Wrapper types (`Attribute`, `ObjectID`, etc.) | Removed (use `String`)                  |

## Dependencies

Update your dependencies in `build.gradle` or `gradle/libs.versions.toml`:

```kotlin theme={"system"}
// Kotlin
kotlin = "2.2.0"

// Algolia
implementation("com.algolia:instantsearch-android:4.0.0")
implementation("com.algolia:algoliasearch-client-kotlin:3.37.2")

// Ktor (if using directly)
ktor = "3.3.3"

// Compose (if using)
composeUi = "1.10.0"
composeCompiler = "2.2.0"
```

## Migration checklist

1. **Update dependencies** to the versions listed above
2. **Update `minSdk`** to 23 in your `build.gradle`
3. **Remove wrapper types**: replace `ApplicationID`, `APIKey`, `IndexName`, `Attribute`, `ObjectID`, `QueryID`, `EventName`, `UserToken` with plain `String`
4. **Update query types**: replace `Query` with `SearchParamsObject`
5. **Update response types**: replace `ResponseSearch` with `SearchResponse`, `Facet` with `FacetHits`
6. **Update filter imports**: use `com.algolia.instantsearch.filter.Filter` instead of `com.algolia.search.model.filter.Filter`
7. **Update Insights**: use v3 event methods instead of `InsightsEvent` constructors
8. **Implement `Indexable`**: ensure hit models implement `Indexable` for tracking
9. **Remove Answers/Places**: if using `SearcherAnswers` or `SearcherPlaces`, migrate to standard search
10. **Test thoroughly**: the new versions include significant internal changes

## Upgrade event tracking

**Starting from v3.2.0, InstantSearch makes it easier to send view events using the [`isAutoSendingHitsViewEvents`](/doc/api-reference/widgets/instantsearch/android#param-is-auto-sending-hits-view-events) option** on [`HitsSearcher`](/doc/api-reference/widgets/instantsearch/android#hitssearcher):

```kotlin Kotlin theme={"system"}
val searcher = HitsSearch(
  applicationID = ApplicationID("ALGOLIA_APPLICATION_ID"),
  apiKey = APIKey("ALGOLIA_SEARCH_API_KEY"),
  indexName = IndexName("indexName"),
  isAutoSendingHitsViewEvents = true
)
```

<Warning>
  From v3.2.0 to v3.3.0, this option was set to `true` by default. Ensure you're using the latest version of InstantSearch to send the required events.
</Warning>

## Upgrade from InstantSearch v2 to v3

The library version `3.0` uses Kotlin `1.6` and Algolia Kotlin API Client `2.0`. Below are the steps to migrate.

<Note>
  This new version removes all deprecated methods and features from `v2`.
</Note>

### InstantSearch Android package

InstantSearch Android package has changed. Update your imports accordingly:

| Module                | 2.x                                        | 3.x                                 |
| --------------------- | ------------------------------------------ | ----------------------------------- |
| InstantSearch Android | `com.algolia.instantsearch.helper.android` | `com.algolia.instantsearch.android` |

### Kotlin API client

The Kotlin API client (and its underlying Ktor client) is part of the library's binary interface. Read the [migration guide](https://github.com/algolia/algoliasearch-client-kotlin/blob/master/docs/guide/Migrate_1.x_2.x.md), or apply the following changes:

#### `LogLevel`

The library uses `LogLevel` from the Kotlin API client instead of Ktor's `Loglevel`:

| Subsystem | 2.x                                        | 3.x                                   |
| --------- | ------------------------------------------ | ------------------------------------- |
| LogLevel  | `io.ktor.client.features.logging.LogLevel` | `com.algolia.search.logging.LogLevel` |

#### Public constants

Constants (for example, `KeyIndexName`, `KeyEnglish`, and `RouteIndexesV1`) aren't exposed. Use your constants instead.

#### Ktor client

For more information, refer to Ktor's [migration guide](https://ktor.io/docs/migrating-2.html#feature-plugin-client).

### Searchers

Legacy searchers are removed. Migrate as follows:

| Searcher              | 2.x                     | 3.x              |
| --------------------- | ----------------------- | ---------------- |
| Single Index Searcher | `SearcherSingleIndex`   | `HitsSearcher`   |
| Facets Searcher       | `SearcherForFacets`     | `FacetsSearcher` |
| Multi Index Searcher  | `SearcherMultipleIndex` | `MultiSearcher`  |

### Extension modules

Multiple extensions have been extracted to modules:

| Subsystem                   | Module                                      |
| --------------------------- | ------------------------------------------- |
| AndroidX SwipeRefreshLayout | `com.algolia:instantsearch-android-loading` |
| AndroidX Paging 3           | `com.algolia:instantsearch-android-paging3` |
| AndroidX Paging 2           | Removed                                     |

## Upgrade from InstantSearch v1 to v2

InstantSearch v2 introduces a new architecture and new widgets, which brings several breaking changes from v1:

* **No longer an `InstantSearch` component** automatically connecting widgets. You are now in control of the `Searcher` and responsible for connecting and disconnecting it from widgets and other components.
* The widgets are now **built around `ViewModel`s**, holding their data and business logic.

  Compared to the V1 where widgets were Android `Views`, now the core of the widget is its view-model, and the UI is behind an interface to ensure minimal coupling.

You can learn more about the philosophy of InstantSearch v2 in [What is InstantSearch](/doc/guides/building-search-ui/what-is-instantsearch/android). Once ready to start migrating, learn the steps to building an InstantSearch v2 app in the [getting started guide](/doc/guides/building-search-ui/getting-started/android)..

<Note>
  The InstantSearch Android v1 documentation is available on the [legacy docs page](https://algolia.com/old-docs/deprecated/instantsearch/android/v1/api-ref/api-ref/).
</Note>
