# Android (Kotlin)

## Overview

This guide will walk you through the necessary steps to use the Terra SDK with Android-based integrations in your Android app. It covers everything from SDK initialization, user connection, permission handling, and background data updates.

The TerraAndroid SDK supports the following integrations:

* Samsung Health
* Health Connect

## 1. Install the SDK

#### **1. Install Terra in `build.gradle`**

* Inside the dependencies section of your `build.gradle` file, add the following line of code.

<pre class="language-gradle" data-title="build.gradle"><code class="lang-gradle"><strong>implementation 'co.tryterra:terra-android:{VERSION_NUMBER}'
</strong></code></pre>

* You can find the latest version number on [Maven Central](https://central.sonatype.com/artifact/co.tryterra/terra-android/).

#### 2. Sync your project with **`build.gradle`**

Sync your project with Gradle by clicking on the "**Sync Project with Gradle Files**" button in the toolbar. This will download the **TerraAndroid SDK** and make it available to your project.

{% hint style="info" %}

#### Requirements

* Your app build config must be for **Android 28 (minSDK 28)** and above.
* The device must have the required app installed, e.g. Health Connect or Samsung Health
  {% endhint %}

#### 3. Configure Health Permissions

{% tabs %}
{% tab title="Apply to use Samsung Health" %}
Terra has a privileged partnership with Samsung that gives you direct access to the Samsung Health SDK — no Health Connect intermediary needed. This is the recommended route for Samsung devices.

**1. Apply for Samsung Health access**

Submit your application through the [Samsung Health partnership portal](https://developer.samsung.com/SHealth/business-partner/m48wvqi1mt9w2w4c).

{% hint style="info" %}
While waiting for approval, you can start development immediately using the **Health Connect** route (see the other tab). Switching to Samsung direct later is just a version bump — no code changes needed.
{% endhint %}

**2. Install the Samsung-tagged SDK**

After approval, switch to the Samsung-tagged version of the Terra Android SDK:

```gradle
implementation 'co.tryterra:terra-android:{SAMSUNG_VERSION_NUMBER}'
```

Find Samsung-tagged versions on [Maven Central](https://central.sonatype.com/artifact/co.tryterra/terra-android/) — look for versions with `samsung` in the name.

**3. Add ProGuard rule (required for release builds)**

Add this to your `proguard-rules.pro`:

```proguard
-keep class com.samsung.android.** { *; }
```

Without this, R8 minification will strip Samsung SDK classes and cause runtime crashes in production.

**4. Requirements**

* **Samsung Health** app must be installed on the device
* **Android 28 (minSDK 28)** and above
* Enable **Developer Mode** in Samsung Health on test devices (Settings > About Samsung Health > tap version number repeatedly)
* No additional manifest or Gradle changes needed — the Terra SDK handles everything
  {% endtab %}

{% tab title="Apply to use Health Connect" %}
**1. In the Health Connect app**

Give all permissions between the apps you wish to read from (e.g. **Samsung Health, Google Fit, etc**) & Health Connect.

**2. Add Health Connect capability to your app**

Include the permission tags under the Activity you wish to link the user to when they click the **privacy policy** link in the Health Connect permission screen. Here are the steps:

1. Go to your Android App's `AndroidManifest.xml`
2. Go to your **Privacy Policy** <mark style="color:purple;">`<activity>`</mark> and include the following tags under this <mark style="color:purple;">`<activity>`</mark> tag.

"Your Android manifest needs to have an Activity that displays your app's **privacy policy**, which is your app's rationale of the requested permissions, describing how the user's data is used and handled." — Health Connect.

<pre class="language-xml" data-title="AndroidManifest.xml" data-line-numbers><code class="lang-xml"><strong>&#x3C;intent-filter>
</strong>  &#x3C;action android:name="androidx.health.ACTION_SHOW_PERMISSIONS_RATIONALE" />
 &#x3C;/intent-filter>
  
&#x3C;intent-filter>
   &#x3C;action android:name="android.intent.action.VIEW_PERMISSION_USAGE"/>
  &#x3C;category android:name="android.intent.category.HEALTH_PERMISSIONS"/>
&#x3C;/intent-filter>
</code></pre>

{% hint style="warning" %}

#### Apply for Health Connect access

Before going **live** (release), you will need to apply for permissions to access the Health Connect API with Google.

1. Use this [application form](https://developer.android.com/health-and-fitness/guides/health-connect/publish/declare-access#explain-use-data-types).
2. For each permission which you are ***not*** using, please add the following lines to your AndroidManifest.xml

```xml
<uses-permission android:name="android.permission.health.READ_HEART_RATE" tools:node="remove"/>
```

with `android.permission.health.XXX` for each permission you aren't using
{% endhint %}
{% endtab %}
{% endtabs %}

***

## 2. Initialize the SDK

The initialization only needs to be done **once** **on** **app** **start**, (e.g. in your `MainActivity` file or equivalent), **and** **every time** the app is brought into the foreground. This ensures that the SDK is properly set up and ready to be used.

{% hint style="warning" %}
The SDK should be initialized every time your app is started.

This is a necessary prerequisite for other SDK functions to run as expected
{% endhint %}

#### **Step 1: Import `Terra` and `TerraManager`**

In your Android Studio project, you should now be able to import classes from the Terra SDK.

{% code title="MainActivity.kt" lineNumbers="true" %}

```kotlin
import co.tryterra.terra.Terra
import co.tryterra.terra.TerraManager
```

{% endcode %}

#### **Step 2: Get a `TerraManager` Instance**

To do this, run the [Terra manager initialization function](https://app.gitbook.com/s/eJJpVMsUARUJq9lYmL6t/health-and-fitness-api/sdk-references/android-kotlin#initialization-of-terra-manager) as below:

{% code title="MainActivity.kt" lineNumbers="true" %}

```kotlin
import co.tryterra.terra.Terra
import co.tryterra.terra.TerraManager

import java.lang.IllegalStateException

class MainActivity : AppCompatActivity() {
    private lateinit var terra: TerraManager

    public override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        
        Terra.instance("YOUR DEV ID", "REFERENCE ID", this) { manager, error ->
            error?.let {
                throw IllegalStateException("🤯: Error initialising terra ${it.message}")
            }
            terra = manager
        }
    }
}
```

{% endcode %}

(**N.B** This call is asynchronous, please ensure this is complete before using the manager).

***

## 3. Connect to a User

Once Terra is initialized, you can create a connection (e.g. Samsung Health or Health Connect).

Call [`terra.initConnection`](https://app.gitbook.com/s/eJJpVMsUARUJq9lYmL6t/health-and-fitness-api/sdk-references/android-kotlin#initconnection) from the `TerraManager` instance you've created above to have the corresponding permission screen pop up.

#### 1. Call [`initConnection()`](https://app.gitbook.com/s/eJJpVMsUARUJq9lYmL6t/health-and-fitness-api/sdk-references/ios-swift#initconnection)

This method triggers a permission popup and establishes the connection.

From the `TerraManager` instance, call [`initConnection()`](https://app.gitbook.com/s/eJJpVMsUARUJq9lYmL6t/health-and-fitness-api/sdk-references/ios-swift#initconnection) with the following arguments:

* `type`: Specify the connection type — `Connections.SAMSUNG` for Samsung Health or `Connections.HEALTH_CONNECT` for Health Connect
* `token`: A **one-time authentication token** generated from your **backend** **server** using Terra API. This ensures secure communication between your app and the Terra servers.
* `customPermissions`: A **set of permissions** that define what data you want to request (e.g., heart rate, steps). If empty, it defaults to all available permissions.
* `schedulerOn`: To allow Terra to make scheduled requests whenever the app is in the foreground.

To learn more about these parameters and their different options, check the [Android SDK Reference.](https://app.gitbook.com/s/eJJpVMsUARUJq9lYmL6t/health-and-fitness-api/sdk-references/android-kotlin)

{% tabs %}
{% tab title="Samsung Health" %}
{% code title="MainActivity.kt" lineNumbers="true" %}

```kotlin
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log

import co.tryterra.terra.Terra
import co.tryterra.terra.TerraManager
import co.tryterra.terra.enums.Connections

import java.lang.IllegalStateException

class MainActivity : AppCompatActivity() {
    private lateinit var terra: TerraManager

    override fun onCreate(savedInstanceState: Bundle?) {
        // Creation of Terra Manager as in Step 2!
    }

    fun initialiseUserConnection() {
        if (!this::terra.isInitialized){
            throw IllegalStateException("🤯: Terra Manager not initialised yet")
        }
        val token = "your_generated_token_from_backend"

        terra.initConnection(
            connection = Connections.SAMSUNG,
            token = token,
            context = this,
            customPermissions = setOf(),
            schedulerOn = true,
            startIntent = null
        ) { success, error ->
            error?.let {
                throw IllegalStateException("🤯: ${it.message}")
            }
            Log.i("MainActivity", "Auth Success status: $success")
        }
    }
}
```

{% endcode %}
{% endtab %}

{% tab title="Health Connect" %}
{% code title="MainActivity.kt" lineNumbers="true" %}

```kotlin
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log

import co.tryterra.terra.Terra
import co.tryterra.terra.TerraManager
import co.tryterra.terra.enums.Connections

import java.lang.IllegalStateException

class MainActivity : AppCompatActivity() {
    private lateinit var terra: TerraManager

    override fun onCreate(savedInstanceState: Bundle?) {
        // Creation of Terra Manager as in Step 2!
    }

    fun initialiseUserConnection() {
        if (!this::terra.isInitialized){
            throw IllegalStateException("🤯: Terra Manager not initialised yet")
        }
        val token = "your_generated_token_from_backend"

        terra.initConnection(
            connection = Connections.HEALTH_CONNECT,
            token = token,
            context = this,
            customPermissions = setOf(),
            schedulerOn = true,
            startIntent = null
        ) { success, error ->
            error?.let {
                throw IllegalStateException("🤯: ${it.message}")
            }
            Log.i("MainActivity", "Auth Success status: $success")
        }
    }
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

{% hint style="info" %}
**`initConnection` only needs to be called a single time.**

**Health Connect** prohibits the permission popup to appear more than once for any given permission, so calling `initConnection` more than once will result in no action at all

The only case where it would re-appear is if:

a. you call initConnection with **an expanded set of `customPermissions`**

b. the **app is deleted & reinstalled.**

c. **a permission that was not granted to use on release by Google has been requested by the app**
{% endhint %}

#### 2. Generate an Auth Token

To be able to call the `initConnection()` method, you need to pass a `token` as an argument.

This `token` is a **single-use token** created to ensure the authentication endpoint for creating a connection (and connecting the SDK to Terra's servers) does not get abused.

Generate the token with this endpoint <mark style="color:orange;">`POST`</mark>`https://api.tryterra.co/v2/auth/generateAuthToken` . Make sure to call it with your Terra `x-api-key` and `dev-id` in the headers from **your backend server.** After you generate the token, provide the response to your client side using your own logic.&#x20;

Go to the **SDK Reference** to find more details on the [Generate the Mobile SDK Auth Token **API Endpoint**](https://app.gitbook.com/s/eJJpVMsUARUJq9lYmL6t/health-and-fitness-api/sdk-references)**.**

{% hint style="warning" %}

* During the development phase, it it acceptable to place this call on the **client** side, exposing your API key in your mobile app.
* For a production implementation, **DO NOT** expose your API key this way, and make sure to **only** make this call from your **backend.**
  {% endhint %}

***

## 4. Validate the Connection

To ensure a connection is still valid on the client side, use the [`terra.getUserId()`](https://app.gitbook.com/s/eJJpVMsUARUJq9lYmL6t/health-and-fitness-api/sdk-references/android-kotlin#getuserid) method. This function is synchronous and returns the `user_id` right away or null if none exists.

{% hint style="info" %}

## Always validate the connection before using the SDK

Check if a `user_id` exists right after **initializing the Terra SDK** to see if the connection still exists.

1. **Check if the User is Connected**&#x20;
   1. If the function returns a user ID, the user is still connected, 🎉 keep vibing along!
   2. If the function returns <mark style="color:red;">`nil`</mark>, the user needs to reconnect.
2. **Re-connect if Needed**\
   If the connection is lost, you can call `terra.initConnection()` again to re-establish the connection.&#x20;

Calling `terra.initConnection()` when the user is already connected or just needs a reconnection will not trigger any permission screens from Apple Health, and the user flow will remain uninterrupted. The connection will be re-established if necessary.
{% endhint %}

***

Now you'll start receiving health data events **automatically** to your Data Destination (e.g. webhook)!

You can also request historical data to backfill, to verify that data exists, or as a fallback.

Check out the [Android SDK reference](https://docs.tryterra.co/health-and-fitness-api/mobile-only-sources/android-kotlin) for details about all the functions in the SDK.

***

## 📱 App Example

{% code title="MainActivity.kt" lineNumbers="true" %}

```kotlin
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log

import co.tryterra.terra.Terra
import co.tryterra.terra.TerraManager
import co.tryterra.terra.enums.Connections

import java.lang.IllegalStateException

class MainActivity : AppCompatActivity() {
    private lateinit var terra: TerraManager

    public override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        
        Terra.instance("YOUR DEV ID", "REFERENCE ID", this) { manager, error ->
            error?.let{it -> 
                throw IllegalStateException("🤯: Error initialising terra ${it.message}")
            }
            terra = manager
            this.initialiseUserConnection()
        }
    }

    fun initialiseUserConnection() {
        if (!this::terra.isInitialized){
            throw IllegalStateException("🤯: Terra Manager not initialised yet")
        }
        
        if (terra.getUserId(Connections.SAMSUNG) != null){
            // User already connected
            return
        }
        
        // Initialize the connection to Samsung Health
        terra.initConnection(
            connection = Connections.SAMSUNG,   // Connecting to Samsung Health
            token = "AUTH TOKEN",                      // Token passed from backend
            context = this,                  // The activity context
            customPermissions = setOf(),  // Custom permissions set (empty set defaults to all permissions)
            schedulerOn = true,                 // Background scheduler on
            startIntent = null                  // Deprecated - always set to null
        ) { success, error ->
            error?.let {
                throw IllegalStateException("🤯: ${it.message}")
            }
            // Connection successful!
            Log.i("MainActivity", "Auth Success status: $success")
        }
    }
}
```

{% endcode %}

***

## Disconnecting a user

In order to disconnect an SDK user, you may use [the same endpoint as for Web API-based integrations](https://app.gitbook.com/s/eJJpVMsUARUJq9lYmL6t/health-and-fitness-api/readme#auth-deauthenticateuser), called from your backend.

***

## Historical Data retrieval

You can request for historical data using one of the [data retrieval functions](https://app.gitbook.com/s/eJJpVMsUARUJq9lYmL6t/health-and-fitness-api/sdk-references/android-kotlin#data-retrieval).

You may set `toWebhook` to false if you wish for the callback function to return the data payload on the client side.

{% code title="MainActivity.kt" lineNumbers="true" %}

```kotlin
import co.tryterra.terra.enums.Connections
import java.time.Instant
import java.time.temporal.ChronoUnit
import java.util.*

fun requestData() {
    val startDate = Date.from(Instant.now().minus(1, ChronoUnit.DAYS))
    val endDate = Date()

    // Request for yesterday and today's data
    terra.getDaily(
        type = Connections.SAMSUNG,
        startDate = startDate,
        endDate = endDate,
        toWebhook = false 
    ) { success, payload, error ->
        error?.let{
            throw IllegalStateException("🤯: Error requesting data ${it.message}")    
        }
        // Process payload here
    }
}
```

{% endcode %}

{% hint style="warning" %}

## Data Sources requiring the Terra **Mobile-SDK**

The **Mobile SDK** is <mark style="color:red;">**ONLY**</mark> used to connect to the following integrations:

1. <img src="https://464213908-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FVGMJVuZnZyOtvV4b53cY%2Fuploads%2FDH2JWDtg632mUQlEdrLH%2F4p3k173m8ihe71872bi9r0292q-0af5626e815091005bacb793985c1870.png?alt=media&#x26;token=062c917e-02fe-4029-9809-fc881cf09de3" alt="" data-size="line">**Apple Health -** iOS
2. <img src="https://464213908-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FVGMJVuZnZyOtvV4b53cY%2Fuploads%2F0lTv9KpldVVjBdg3JJQs%2Fimgbin_samsung-galaxy-samsung-health-samsung-electronics-android-png.png?alt=media&#x26;token=b58f3118-a2e1-4b09-9d30-4f862253adb6" alt="" data-size="line"> **Samsung Health -** Android
3. <img src="https://464213908-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FVGMJVuZnZyOtvV4b53cY%2Fuploads%2FmotL0wnZKiEWOKt46zOU%2Fvecteezy_google-fit-icon-logo-symbol_22484515.png?alt=media&#x26;token=a2d0ae73-5116-49fd-8ce1-0f7b5e6f716b" alt="" data-size="line"> **Google Fit & Health Connect**- Android.&#x20;

Note: the [Health & Fitness API](https://docs.tryterra.co/health-and-fitness-api) is the preferred way to connect to Google Fit due to better reliability.

For **ALL** other integrations, please refer to Integration Setup the [Health & Fitness API](https://docs.tryterra.co/health-and-fitness-api).
{% endhint %}
