# Android

## Prerequisites

Ensure you have the following before you begin:

1. **Android Studio**: The latest stable version.
2. **Terra Account**: Access to your Terra Developer account and API key.
3. **Gradle Dependency**: Ensure you include the TerraRT SDK in your project by adding the necessary dependencies.

   ```gradle
   implementation 'co.tryterra:terra-rtandroid:X.X.X'
   ```

   based on [the latest version on maven central](https://central.sonatype.com/artifact/co.tryterra/terra-rtandroid)

## SDK Initialization

{% hint style="info" %}
Always initialize the `TerraRT` class to begin using the SDK.

Do so every time the app is opened or brought into the foreground.
{% endhint %}

To do this, run the [TerraRT manager initialization function](/reference/streaming-api/reference/android-kotlin.md#terrart) as below:

```kotlin
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import co.tryterra.terrartandroid.TerraRT

class MainActivity : AppCompatActivity() {
    private lateinit var terraRT: TerraRT

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

        val developerId = "yourDeveloperId"
        val referenceId: String? = "yourReferenceId"

        terraRT = TerraRT(
            devId = developerId,
            context = this,
            referenceId = referenceId
        ) { success ->
            if (success) {
                println("TerraRT initialized successfully")
            } else {
                println("Failed to initialize TerraRT")
            }
        }
    }
}
```

## **Initializing a Connection**

Register the [phone](/reference/streaming-api/core-concepts.md#phone) by calling [`initConnection`](/reference/streaming-api/reference/android-kotlin.md#initconnection).

This connects the [phone](/reference/streaming-api/core-concepts.md#phone) to Terra, allows you to use other SDK functions, and allows it to be a [producer](/reference/streaming-api/core-concepts.md#producer) once a [device](/reference/streaming-api/core-concepts.md#device) is connected later on.

Use the [terraRT instance created above](#sdk-initialization) and call initConnection as below using an **authentication token**.

```kotlin
val token = "yourAuthToken"  // Generated from your backend

terraRT.initConnection(token) { success ->
    if (success) {
        println("Connection initialized successfully!")
    } else {
        println("Failed to initialize connection.")
    }
}
```

To generate the **token**, make the below call **from your backend**

{% openapi src="<https://raw.githubusercontent.com/tryterra/openapi/refs/heads/master/v5.yml>" path="/auth/generateAuthToken" method="post" %}
<https://raw.githubusercontent.com/tryterra/openapi/refs/heads/master/v5.yml>
{% endopenapi %}

## Device Connection Management

Once initialized, you can scan for devices and connect to them using the TerraRT SDK.

You can scan for devices using

* BLE
* ANT+ (if supported by the Android phone used)

#### Start Device Scan

You can start scanning for devices and allow the user to connect to a wearable device using [startDeviceScan](/reference/streaming-api/reference/android-kotlin.md#startdevicescan).

You can choose whether to use cached devices (ones you've connected to before) or show a connection widget if no cached device is found.

```kotlin
import co.tryterra.terrartandroid.enums.Connections

// Option 1: Widget-based scan with auto-connection
terraRT.startDeviceScan(
    type = Connections.BLE,
    useCache = false,
    showWidgetIfCacheNotFound = true
) { success ->
    if (success) {
        println("Device connected successfully!")
    } else {
        println("Failed to connect to the device.")
    }
}

// Option 2: Programmatic scan with device callback
terraRT.startDeviceScan(type = Connections.BLE) { device ->
    println("Found device: ${device.deviceName}")
    // Connect to the chosen device
    terraRT.connectDevice(device) { connected ->
        println("Device connected: $connected")
    }
}
```

### Real-Time Data Streaming

Once the device is connected, you can start streaming real-time data such as heart rate, steps, and more.

{% hint style="info" %}
Receiving a real time data stream depends on the [device](/reference/streaming-api/core-concepts.md#device) being configured to broadcast the data it is collecting through BLE or ANT+
{% endhint %}

#### Start Real-Time Streaming

```kotlin
import co.tryterra.terrartandroid.enums.DataTypes

val dataTypes: Set<DataTypes> = setOf(DataTypes.HEART_RATE, DataTypes.STEPS)

// Stream data locally (no server)
terraRT.startRealtime(type = Connections.BLE, dataTypes = dataTypes) { update ->
    println("${update.type}: ${update.`val`}")
}
```

#### Stop Real-Time Streaming

```kotlin
terraRT.stopRealtime(type = Connections.BLE)
```

#### Disconnect Device

```kotlin
terraRT.disconnect(type = Connections.BLE)
```

### Example Usage

#### Full Example: Managing a BLE Connection and Streaming Data

```kotlin
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import co.tryterra.terrartandroid.TerraRT
import co.tryterra.terrartandroid.enums.Connections
import co.tryterra.terrartandroid.enums.DataTypes
import co.tryterra.terrartandroid.models.Update

class MainActivity : AppCompatActivity() {
    private lateinit var terraRT: TerraRT

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

        terraRT = TerraRT(
            devId = "yourDeveloperId",
            context = this,
            referenceId = "yourReferenceId"
        ) { success ->
            if (success) {
                println("TerraRT initialized")
                connectAndStream()
            }
        }
    }

    private fun connectAndStream() {
        val token = "yourAuthToken"

        terraRT.initConnection(token) { success ->
            if (success) {
                // Scan and connect to a BLE device
                terraRT.startDeviceScan(
                    type = Connections.BLE,
                    useCache = false
                ) { scanSuccess ->
                    if (scanSuccess) {
                        // Start streaming heart rate data
                        val dataTypes = setOf(DataTypes.HEART_RATE, DataTypes.STEPS)
                        terraRT.startRealtime(
                            type = Connections.BLE,
                            dataTypes = dataTypes
                        ) { update ->
                            handleUpdate(update)
                        }
                    }
                }
            }
        }
    }

    private fun handleUpdate(update: Update) {
        println("${update.type}: ${update.`val`} at ${update.ts}")
    }

    override fun onDestroy() {
        super.onDestroy()
        terraRT.stopRealtime(type = Connections.BLE)
        terraRT.disconnect(type = Connections.BLE)
    }
}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.tryterra.co/streaming-api/connect-wearable-to-sdk/android.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
