> For the complete documentation index, see [llms.txt](https://docs.mapbox.com/android/search/llms.txt)

# Offline reverse geocoding

This example does not contain a UI. Results will be logged in Android Studio. To run this example you will need access to our Offline Data API. [Contact our team](https://www.mapbox.com/contact/sales) to request access.

> **Note**
> 
> This example is a part of the [Search SDK for Android sample app](https://github.com/mapbox/mapbox-search-android). You can find the values for all referenced resources in the [`res`](https://github.com/mapbox/mapbox-search-android/tree/main/MapboxSearch/sample/src/main/res) directory. For example, see [`res/values/strings.xml`](https://github.com/mapbox/mapbox-search-android/tree/main/MapboxSearch/sample/src/main/res/values/strings.xml) for `R.string.*` references used in this example. The dependencies can be found [here.](https://github.com/mapbox/mapbox-navigation-android-examples/blob/main/app/build.gradle) The examples use View binding. [See setup documention if necessary.](https://developer.android.com/topic/libraries/view-binding)

**Java**

Title: `MainActivity.java`

[View on GitHub](https://github.com/mapbox/mapbox-search-android/tree/main/MapboxSearch/sample/src/main/java/com/mapbox/search/sample/api/OfflineReverseGeocodingJavaExampleActivity.java)

```java
package com.mapbox.search.sample.api;

import android.os.Bundle;
import android.util.Log;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;

import com.mapbox.common.Cancelable;
import com.mapbox.common.TileRegionLoadOptions;
import com.mapbox.common.TileStore;
import com.mapbox.common.TilesetDescriptor;
import com.mapbox.geojson.Point;
import com.mapbox.search.common.AsyncOperationTask;
import com.mapbox.search.offline.OfflineIndexChangeEvent;
import com.mapbox.search.offline.OfflineIndexChangeEvent.EventType;
import com.mapbox.search.offline.OfflineIndexErrorEvent;
import com.mapbox.search.offline.OfflineResponseInfo;
import com.mapbox.search.offline.OfflineReverseGeoOptions;
import com.mapbox.search.offline.OfflineSearchCallback;
import com.mapbox.search.offline.OfflineSearchEngine;
import com.mapbox.search.offline.OfflineSearchEngineSettings;
import com.mapbox.search.offline.OfflineSearchOptions;
import com.mapbox.search.offline.OfflineSearchResult;
import com.mapbox.search.sample.BuildConfig;
import com.mapbox.search.sample.R;

import java.util.Collections;
import java.util.List;

public class OfflineReverseGeocodingJavaExampleActivity extends AppCompatActivity {

    private OfflineSearchEngine searchEngine;
    private Cancelable tilesLoadingTask;
    @Nullable
    private AsyncOperationTask searchRequestTask;

    private final OfflineSearchEngine.EngineReadyCallback engineReadyCallback =
        () -> Log.i("SearchApiExample", "Engine is ready");

    private final OfflineSearchCallback searchCallback = new OfflineSearchCallback() {

        @Override
        public void onResults(@NonNull List<OfflineSearchResult> results, @NonNull OfflineResponseInfo responseInfo) {
            Log.i("SearchApiExample", "Results: " + results);
        }

        @Override
        public void onError(@NonNull Exception e) {
            Log.i("SearchApiExample", "Search error: ", e);
        }
    };

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        final TileStore tileStore = TileStore.create();

        searchEngine = OfflineSearchEngine.create(
            new OfflineSearchEngineSettings(tileStore)
        );

        searchEngine.addEngineReadyCallback(engineReadyCallback);

        final List<TilesetDescriptor> descriptors = Collections.singletonList(OfflineSearchEngine.createTilesetDescriptor());

        final String tileRegionId = "Washington DC";
        final Point dcLocation = Point.fromLngLat(-77.0339911055176, 38.899920004207516);

        final TileRegionLoadOptions tileRegionLoadOptions = new TileRegionLoadOptions.Builder()
            .descriptors(descriptors)
            .geometry(dcLocation)
            .acceptExpired(true)
            .build();

        searchEngine.addOnIndexChangeListener(new OfflineSearchEngine.OnIndexChangeListener() {
            @Override
            public void onIndexChange(@NonNull OfflineIndexChangeEvent event) {
                if (tileRegionId.equals(event.getRegionId()) && (event.getType() == EventType.ADD || event.getType() == EventType.UPDATE)) {
                    Log.i("SearchApiExample", tileRegionId + " was successfully added or updated");

                    searchRequestTask = searchEngine.reverseGeocoding(
                        new OfflineReverseGeoOptions(dcLocation),
                        searchCallback
                    );
                }
            }

            @Override
            public void onError(@NonNull OfflineIndexErrorEvent event) {
                Log.i("SearchApiExample", "Offline index error: $event");
            }
        });

        Log.i("SearchApiExample", "Loading tiles...");

        tilesLoadingTask = tileStore.loadTileRegion(
            tileRegionId,
            tileRegionLoadOptions,
            progress -> Log.i("SearchApiExample", "Loading progress: " + progress),
            region -> {
                if (region.isValue()) {
                    Log.i("SearchApiExample", "Tiles successfully loaded");
                } else {
                    Log.i("SearchApiExample", "Tiles loading error: " + region.getError());
                }
            }
        );
    }

    @Override
    protected void onDestroy() {
        searchEngine.removeEngineReadyCallback(engineReadyCallback);
        tilesLoadingTask.cancel();
        if (searchRequestTask != null) {
            searchRequestTask.cancel();
        }
        super.onDestroy();
    }
}
```

**Kotlin**

Title: `MainActivity.kt`

[View on GitHub](https://github.com/mapbox/mapbox-search-android/tree/main/MapboxSearch/sample/src/main/java/com/mapbox/search/sample/api/OfflineReverseGeocodingKotlinExampleActivity.kt)

```kt
package com.mapbox.search.sample.api

import android.os.Bundle
import com.mapbox.common.Cancelable
import com.mapbox.common.TileRegionLoadOptions
import com.mapbox.common.TileStore
import com.mapbox.geojson.Point
import com.mapbox.search.common.AsyncOperationTask
import com.mapbox.search.offline.OfflineIndexChangeEvent
import com.mapbox.search.offline.OfflineIndexChangeEvent.EventType
import com.mapbox.search.offline.OfflineIndexErrorEvent
import com.mapbox.search.offline.OfflineResponseInfo
import com.mapbox.search.offline.OfflineReverseGeoOptions
import com.mapbox.search.offline.OfflineSearchCallback
import com.mapbox.search.offline.OfflineSearchEngine
import com.mapbox.search.offline.OfflineSearchEngineSettings
import com.mapbox.search.offline.OfflineSearchResult
import com.mapbox.search.sample.R

class OfflineReverseGeocodingKotlinExampleActivity : BaseKotlinExampleActivity() {

    override val titleResId: Int = R.string.action_open_offline_reverse_geocoding_kt_example

    private lateinit var searchEngine: OfflineSearchEngine
    private var tilesLoadingTask: Cancelable? = null
    private var searchRequestTask: AsyncOperationTask? = null

    private val engineReadyCallback = object : OfflineSearchEngine.EngineReadyCallback {
        override fun onEngineReady() {
            logI("SearchApiExample", "Engine is ready")
        }
    }

    private val searchCallback = object : OfflineSearchCallback {

        override fun onResults(results: List<OfflineSearchResult>, responseInfo: OfflineResponseInfo) {
            logI("SearchApiExample", "Results:", results)
            onFinished()
        }

        override fun onError(e: Exception) {
            logI("SearchApiExample", "Search error", e)
            onFinished()
        }
    }

    private val tileRegionId = "Washington DC"
    private val tileStore = TileStore.create()
    private val descriptors = listOf(OfflineSearchEngine.createTilesetDescriptor())
    private val dcLocation = Point.fromLngLat(-77.0339911055176, 38.899920004207516)

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        searchEngine = OfflineSearchEngine.create(
            OfflineSearchEngineSettings(
                tileStore = tileStore
            )
        )

        searchEngine.addEngineReadyCallback(engineReadyCallback)

        searchEngine.addOnIndexChangeListener(object : OfflineSearchEngine.OnIndexChangeListener {
            override fun onIndexChange(event: OfflineIndexChangeEvent) {
                if (event.regionId == tileRegionId && (event.type == EventType.ADD || event.type == EventType.UPDATE)) {
                    logI("SearchApiExample", "$tileRegionId was successfully added or updated")

                    searchRequestTask = searchEngine.reverseGeocoding(
                        OfflineReverseGeoOptions(center = dcLocation),
                        searchCallback
                    )
                }
            }

            override fun onError(event: OfflineIndexErrorEvent) {
                logI("SearchApiExample", "Offline index error:", event)
                onFinished()
            }
        })
    }

    override fun startExample() {
        logI("SearchApiExample", "Loading tiles...")

        val tileRegionLoadOptions = TileRegionLoadOptions
            .Builder()
            .descriptors(descriptors)
            .geometry(dcLocation)
            .acceptExpired(true)
            .build()

        tilesLoadingTask = tileStore.loadTileRegion(
            tileRegionId,
            tileRegionLoadOptions,
            { progress -> logI("SearchApiExample", "Loading progress: $progress") },
            { result ->
                if (result.isValue) {
                    logI("SearchApiExample", "Tiles successfully loaded: ${result.value}")
                } else {
                    logI("SearchApiExample", "Tiles loading error: ${result.error}")
                }
            }
        )
    }

    override fun onDestroy() {
        searchEngine.removeEngineReadyCallback(engineReadyCallback)
        tilesLoadingTask?.cancel()
        searchRequestTask?.cancel()
        super.onDestroy()
    }
}
```