# Tutorials

## Setup the access key for the NextBillion mapview

* Modify AndroidManifest.xml

Locate the &lt;application&gt; tag in your project's `AndroidManifest.xml` file and include the following element inside it. This element declares `androidx.startup.InitializationProvider`, which is responsible for application initialization.

```xml
<provider
    android:name="androidx.startup.InitializationProvider"
    android:authorities="${applicationId}.androidx-startup"
    android:exported="false"
    tools:node="merge">
    <meta-data
    android:name=".AppDataInitStartup"
    android:value="androidx.startup" />
</provider>
```

* Create AppDataInitStartup Class

Next, create a class named AppDataInitStartup in your project. This class implements the Initializer interface. In the create method of this class, perform the application's initialization tasks.
In this example, the initialization task is performed using `Nextbillion.getInstance(context, "YOUR-ACCESS-KEY")`.

Replace "YOUR-ACCESS-KEY" with your actual access key.

```kotlin
class AppDataInitStartup : Initializer<Boolean> {

    override fun create(context: Context): Boolean {
        Nextbillion.getInstance(context, "YOUR-ACCESS-KEY")
        return true
    }

    override fun dependencies(): List<Class<out Initializer<*>>> {
        return emptyList()
    }
}
```

By following these steps, you have integrated the `AppDataInitStartup` code into your Android project. This code will be executed when the application starts, performing the initialization tasks defined in the `create` method.

## Add NextBillionMap to your app

This example embeds `NextBillionMap` into your application using the Compose extension.

```kotlin
import ai.nextbillion.maps.extension.compose.NextBillionMap

public class SimpleMapActivity : ComponentActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            NextBillionMap(modifier = Modifier.fillMaxSize())
        }
    }
    ...
}
```

## Setting Up the Map Style and Initial Camera Position

To configure the initial map style and camera position, utilize the `NextbillionMapOptions` by constructing it with the context obtained from the `createFromAttributes` function. The `NextbillionMapOptions` is the same object used when constructing a MapView.

```kotlin
override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            NextBillionMap(
                modifier = Modifier.fillMaxSize(),
                mapType = MapType.SATELLITE,
                mapOptionsFactory = { context ->
                    NextbillionMapOptions.createFromAttributes(context)
                        .camera(
                            CameraPosition.Builder()
                                .target(LatLng(21.142364, 79.094730))
                                .zoom(12.0)
                                .build()
                        )
                }
            )
        }
    }
```

## Use raw NextbillionMap methods through NextBillionMapEffect

The NextBillion Compose Extension is constructed around MapView within the SDK of the base maps. Due to the extensive API surface of the map SDK, it's impractical to cover every aspect within this wrapper. Hence, we provide access to the raw `NextBillionMap` reference through `NextBillionMapEffect`. This enables you to leverage the entire API surface within a `NextBillionMapEffect`.
It's essential to exercise caution when employing raw `NextBillionMap` APIs within `NextBillionMapEffect`. Doing so may introduce internal state changes that could potentially disrupt Compose states, leading to unexpected behaviors.

The subsequent example showcases how to activate debug features using `NextBillionMapEffect`.

```kotlin
override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            NextBillionMap(
                modifier = Modifier.fillMaxSize(),
            ) {
                NextBillionMapEffect(Unit) { nbMap ->
                    // Use NextbillionMap to access all the NextBillion Maps APIs .
                    // For example, to enable debug mode:
                    nbMap.isDebugActive = true
                }
            }
        }
    }
```

## Use Camera Animation or Position state APIs

In the Compose environment, the map's camera and position animations are accessed through `CameraPositionState`. Internally, these functionalities are implemented using the Transform feature of the base maps SDK.

Currently, we offer high-level camera animation APIs such as `setCameraPosition`, `animate`,`easeCamera`, and move within the `CameraPositionState`.
Below is an example demonstrating the addition of a button to execute a flyTo animation to the designated camera position.

```kotlin
override fun onCreate(savedInstanceState: Bundle?) {
  super.onCreate(savedInstanceState)
  setContent {
    // Hold the hoisted CameraPositionState to manipulate the map camera.
    val cameraPositionState = rememberCameraPositionState{
        position = CameraPosition.Builder().target(LatLng(21.142364, 79.094730)).zoom(15.0)
            .build()
    }

    Box(modifier = Modifier.fillMaxSize()) {
        NextBillionMap(
            modifier = Modifier.matchParentSize(),
            cameraPositionState = cameraPositionState,
        )
        Button(
            onClick = {
                cameraPositionState.easeCamera(CameraPosition.Builder().target(LatLng(21.152364, 79.098730)).build(), durationMs = 5000)
            }
        ) {
            Text(text = "Animate camera with easeCamera")
        }
    }
  }
}
```

## Add Annotations to the map

The Annotation support is added with the initial compose extension. You can add `Marker`, `Polyline`, and `Polygon` annotations as composable functions within the NextBillionMap composable function.

### Add a single Marker to the map

The following example showcases adding one marker annotation to the map.

```kotlin
override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            NextBillionMap(
                modifier = Modifier.fillMaxSize(),
                ) {
                Marker(
                    state = MarkerState(LatLng(21.152364, 79.098730))
                )
            }
        }
    }
```

### Add a Polyline to the map

The following example showcases adding one polyline annotation to the map.

```kotlin
 override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            NextBillionMap(
                modifier = Modifier.fillMaxSize(),
                mapOptionsFactory = { context ->
                    NextbillionMapOptions.createFromAttributes(context)
                        .camera(
                            CameraPosition.Builder()
                                .target(LatLng(4.454029847741182, 102.12279928897392))
                                .zoom(7.0)
                                .build()
                        )
                }
            ) {
                Polyline(
                    color = Color.Red,
                    points = listOf(LatLng(4.173966011743196, 102.56143332932972), LatLng(4.757388856118707, 102.84923902653723)),
                    width = 10.0f,
                    onClick = {
                       // On click call back here
                    }
                )
            }
        }
    }
```

### Add a Polygon to the map

The following example showcases adding one polygon annotation to the map.

```kotlin
override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            NextBillionMap(
                modifier = Modifier.fillMaxSize(),
                mapOptionsFactory = { context ->
                    NextbillionMapOptions.createFromAttributes(context)
                        .camera(
                            CameraPosition.Builder()
                                .target(LatLng(5.454029847741182, 102.12279928897392))
                                .zoom(7.0)
                                .build()
                        )
                }
            ) {
                Polygon(
                    points = listOf<LatLng>(
                        LatLng(5.905950548125056, 102.20094147543449),
                        LatLng(5.447582810324074, 102.4236053421908),
                        LatLng(5.319304234490461, 103.13322846086854),
                        LatLng(5.113456220724453, 101.63920008098916),
                        LatLng(5.5704634364237124, 101.24733645772515),
                        LatLng(5.5069783817472056, 101.93764874951532),
                        LatLng(5.905950548125056, 102.20094147543449)
                    ),
                    fillColor = Color.Blue,
                    strokeColor = Color.Red,
                    onClick = {
                        // On click call back
                    }
                )
            }
        }
```

These examples demonstrate how to add various types of annotations to the map within your Compose-based application.

## Configure MapView settings

You can easily configure `MapView` settings such as AttributionSettings, CompassSettings, GesturesSettings, LocationComponentSettings, and LogoSettings by using `MutableState` within the `NextBillionMap` composable functions.

### Gestures settings

In this example, we configure the gestures setting using MutableState. The user can interact with a button to update the gestures settings dynamically.

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

        setContent {
            var gesturesSettings by remember { mutableStateOf(GesturesSettings { }) }
            NextBillionMap(
                modifier = Modifier.fillMaxSize(),
                gesturesSettings = gesturesSettings
            )
            Button(
                onClick = {
                    gesturesSettings =
                        gesturesSettings.toBuilder().setScrollGesturesEnabled(false).build()
                }
            ) {
                Text(text = "Disable gesture scroll")
            }
        }
    }
```

Users can configure other `MapView` settings using the `MutableState` in the same manner.
