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

# Advanced Usage

> **Note (beta): Public preview**
> 
> The Mapbox Search SDK for Android is in public preview. All features and workflows are subject to change.

Search engine help users find specific addresses, points of interest (POIs), and places. The Mapbox Search SDK for Android provides the [`SearchEngine`](https://docs.mapbox.com/android/search/api/core/2.28.2/sdk/com.mapbox.search/-search-engine/) class for:

-   [forward geocoding](https://docs.mapbox.com/android/ja/search/guides/search-engine/geocoding/#forward-geocoding)
-   [reverse geocoding](https://docs.mapbox.com/android/ja/search/guides/search-engine/geocoding/#reverse-geocoding)
-   [category search](https://docs.mapbox.com/android/ja/search/guides/search-engine/geocoding/#category-search)

**Forward geocoding** is likely what comes to mind when you think about a typical search experience: for the given `String` query a user gets geographic coordinates of an address or place. For example, you can type in `Lincoln Memorial` and retrieve the geographic location of a place that matches that query (`-77.050,38.889`).

**Reverse geocoding** is an opposite operation of forward geocoding: for the given geographic coordinates a user gets place names or addresses. For example, turning `-77.050, 38.889` into `2 Lincoln Memorial Circle NW` address.

**Category search** allows you to select a category (for example, `restaurants`) and retrieve a list of POIs that belong to that category. For example, if you want to display many restaurants within walking distance of a theater on a map, you can use category search with the `restaurants` category.

## Integration

The Mapbox Search SDK for Android provides a [`SearchEngine`](https://docs.mapbox.com/android/search/api/core/2.28.2/sdk/com.mapbox.search/-search-engine/) class for executing forward geocoding search requests, reverse geocoding search requests, and making category search requests. You get an instance of the engine via the [`SearchEngine.createSearchEngine(SearchEngineSettings)`](https://docs.mapbox.com/android/search/api/core/2.28.2/sdk/com.mapbox.search/-search-engine/-companion/create-search-engine.html) function or via the [`createSearchEngineWithBuiltInDataProviders(SearchEngineSettings)`](https://docs.mapbox.com/android/search/api/core/2.28.2/sdk/com.mapbox.search/-search-engine/-companion/create-search-engine-with-built-in-data-providers.html) function. To get an instance of the engine with `history` and `favorites` [data providers](https://docs.mapbox.com/android/ja/search/guides/search-engine/data-providers/#built-in-data-providers) registered by default.

```kotlin
val searchEngine = SearchEngine.createSearchEngine(
    SearchEngineSettings(getString(R.string.mapbox_access_token))
)
```

or

```kotlin
val searchEngine = SearchEngine.createSearchEngineWithBuiltInDataProviders(
    SearchEngineSettings(getString(R.string.mapbox_access_token))
)
```

### API type

`SearchEngine` factory-functions [`createSearchEngine()`](https://docs.mapbox.com/android/search/api/core/2.28.2/sdk/com.mapbox.search/-search-engine/-companion/create-search-engine.html) and [`createSearchEngineWithBuiltInDataProviders()`](https://docs.mapbox.com/android/search/api/core/2.28.2/sdk/com.mapbox.search/-search-engine/-companion/create-search-engine-with-built-in-data-providers.html) accept optional parameter [`apiType`](https://docs.mapbox.com/android/search/api/core/2.28.2/sdk/com.mapbox.search/-api-type/) which defines the search endpoint that will be used for search requests.

There are two types of the `ApiType`:

-   [`ApiType.GEOCODING`](https://docs.mapbox.com/android/search/api/core/2.28.2/sdk/com.mapbox.search/-api-type/-g-e-o-c-o-d-i-n-g/). `SearchEngines` created with the `GEOCODING` API Type will target the [Geocoding API](https://docs.mapbox.com/api/search/geocoding/). This is a default API Type for the `SearchEngine`.
-   [`ApiType.SEARCH_BOX`](https://docs.mapbox.com/android/search/api/core/2.28.2/sdk/com.mapbox.search/-api-type/-s-e-a-r-c-h_-b-o-x/). `SearchEngines` created with the `SEARCH_BOX` API Type will target the [Mapbox Search Box API](https://docs.mapbox.com/api/search/search-box/).

## POI metadata in search responses

`SearchEngine` might provide POI metadata in search responses. The metadata includes:

-   Place's information like phone number, website, open hours
-   Average rating and number of reviews
-   Parking information
-   Place images

This data can be accessed via [`SearchResult.metadata`](https://docs.mapbox.com/android/search/api/core/2.28.2/sdk/com.mapbox.search.result/-search-result/metadata.html). By default, the metadata is available to selected customers only, [contact sales team](https://www.mapbox.com/contact/sales/) if you are interested in receiving metadata as part of search results.

## Add search to an app

This example will show you how to use pre-built UI component to quickly add search to an app.

Open the activity's XML **manifest** file. Set permissions and reference the name of the Application you created in the last step:

```text
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:theme="@style/AppTheme"
    >

    <activity
        android:name=".MainActivity"
        android:exported="true">

        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>
```

Open the activity's XML **layout** file and add the following view:

```text
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >

    <EditText
        android:id="@+id/query_edit_text"
        android:layout_width="match_parent"
        android:layout_height="56dp"
        android:hint="Where to?"
        android:paddingHorizontal="16dp"
    />

    <com.mapbox.search.ui.view.SearchResultsView
        android:id="@+id/search_results_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginTop="56dp"
        android:paddingVertical="16dp"
    />
</FrameLayout>
```

Create a new **Activity** or open an existing Activity and add the code below:

```text
import android.Manifest.permission
import android.content.Context
import android.content.pm.PackageManager
import android.os.Bundle
import android.text.Editable
import android.text.TextWatcher
import android.widget.EditText
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import com.mapbox.search.ApiType
import com.mapbox.search.ResponseInfo
import com.mapbox.search.SearchEngine
import com.mapbox.search.SearchEngineSettings
import com.mapbox.search.ServiceProvider
import com.mapbox.search.offline.OfflineResponseInfo
import com.mapbox.search.offline.OfflineSearchEngine
import com.mapbox.search.offline.OfflineSearchEngineSettings
import com.mapbox.search.offline.OfflineSearchResult
import com.mapbox.search.record.HistoryRecord
import com.mapbox.search.result.SearchResult
import com.mapbox.search.result.SearchSuggestion
import com.mapbox.search.ui.view.CommonSearchViewConfiguration
import com.mapbox.search.ui.view.DistanceUnitType
import com.mapbox.search.ui.view.SearchResultsView

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val accessToken = getString(R.string.mapbox_access_token)

        val queryEditText = findViewById<EditText>(R.id.query_edit_text)
        val searchResultsView = findViewById<SearchResultsView>(R.id.search_results_view)
        searchResultsView.initialize(
            SearchResultsView.Configuration(
                commonConfiguration = CommonSearchViewConfiguration(DistanceUnitType.IMPERIAL)
            )
        )

        val searchEngine = SearchEngine.createSearchEngineWithBuiltInDataProviders(
            apiType = ApiType.GEOCODING,
            settings = SearchEngineSettings(accessToken)
        )

        val offlineSearchEngine = OfflineSearchEngine.create(
            OfflineSearchEngineSettings(accessToken)
        )

        val searchEngineUiAdapter = SearchEngineUiAdapter(
            view = searchResultsView,
            searchEngine = searchEngine,
            offlineSearchEngine = offlineSearchEngine,
        )

        searchEngineUiAdapter.addSearchListener(object : SearchEngineUiAdapter.SearchListener {

            private fun showToast(message: String) {
                Toast.makeText(applicationContext, message, Toast.LENGTH_SHORT).show()
            }

            override fun onSuggestionsShown(suggestions: List<SearchSuggestion>, responseInfo: ResponseInfo) {
                // not implemented
            }

            override fun onSearchResultsShown(
                suggestion: SearchSuggestion,
                results: List<SearchResult>,
                responseInfo: ResponseInfo
            ) {
                // not implemented
            }

            override fun onOfflineSearchResultsShown(results: List<OfflineSearchResult>, responseInfo: OfflineResponseInfo) {
                // not implemented
            }

            override fun onSuggestionSelected(searchSuggestion: SearchSuggestion): Boolean {
                return false
            }

            override fun onSearchResultSelected(searchResult: SearchResult, responseInfo: ResponseInfo) {
                showToast("SearchResult clicked: ${searchResult.name}")
            }

            override fun onOfflineSearchResultSelected(searchResult: OfflineSearchResult, responseInfo: OfflineResponseInfo) {
                showToast("OfflineSearchResult clicked: ${searchResult.name}")
            }

            override fun onError(e: Exception) {
                showToast("Error happened: $e")
            }

            override fun onHistoryItemClick(historyRecord: HistoryRecord) {
                showToast("HistoryRecord clicked: ${historyRecord.name}")
            }

            override fun onPopulateQueryClick(suggestion: SearchSuggestion, responseInfo: ResponseInfo) {
                queryEditText.setText(suggestion.name)
            }

            override fun onFeedbackItemClick(responseInfo: ResponseInfo) {
                // not implemented
            }
        })

        queryEditText.addTextChangedListener(object : TextWatcher {

            override fun onTextChanged(s: CharSequence, start: Int, before: Int, after: Int) {
                searchResultsView.search(s.toString())
            }

            override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {
                // not implemented
            }

            override fun afterTextChanged(e: Editable) { /* not implemented */ }
        })

        if (!isPermissionGranted(permission.ACCESS_FINE_LOCATION)) {
            ActivityCompat.requestPermissions(
                this,
                arrayOf(permission.ACCESS_FINE_LOCATION, permission.ACCESS_COARSE_LOCATION),
                PERMISSIONS_REQUEST_LOCATION
            )
        }
    }

    private companion object {

        private const val PERMISSIONS_REQUEST_LOCATION = 0

        fun Context.isPermissionGranted(permission: String): Boolean {
            return ContextCompat.checkSelfPermission(
                this, permission
            ) == PackageManager.PERMISSION_GRANTED
        }
    }
}
```

Run your application and you will see a functional search UI. Begin typing in the search bar to see results:

![A screenshot of the final product after completing the quickstart.](https://docs.mapbox.com/android/ja/assets/ideal-img/search-overview-quickstart.44ba62a.480.png)

## Search Engine Pricing

There is no separate charge if you choose to use Mapbox Search SDK for Android to access our APIs, you only pay by the Search API usage.

Usage of the Search Engine depends on the [API type](#api-type) you choose. Details about the number of API requests included in the free tier and the cost per request beyond what is included in the free tier are available on the [pricing page](https://www.mapbox.com/pricing/#search).

-   For API type `GEOCODING`, see [Temporary Geocoding API Pricing](https://www.mapbox.com/pricing/#temporary-geocoding-api),
-   For API type `SEARCH_BOX`, see [Search Box API Sessions Pricing](https://www.mapbox.com/pricing/#search-api-session).

---