> For the complete documentation index, see [llms.txt](https://docs.tryterra.co/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.tryterra.co/streaming-api/connect-wearable-to-sdk/flutter.md).

# Flutter

## Prerequisites

1. Add [`terra_flutter_rt`](https://pub.dev/packages/terra_flutter_rt) to your `pubspec.yaml`:

```yaml
dependencies:
  terra_flutter_rt: ^X.X.X
```

2. **iOS:** In your `Info.plist`, add:
   * `Privacy - Bluetooth Always Usage Description`: Justification for BLE usage
   * `Privacy - Motion Usage Description`: Justification for motion sensor usage (required if streaming accelerometer, gyroscope, or step data from the phone's built-in sensors via `Connection.apple`)
3. **Android:** Permissions are requested automatically by the SDK on initialization.

## SDK Initialization

{% hint style="info" %}
Initialize the SDK every time the app is opened or brought into the foreground.
{% endhint %}

```dart
import 'package:terra_flutter_rt/terra_flutter_rt.dart';
import 'package:terra_flutter_rt/types.dart';

await TerraFlutterRt.init('YOUR_DEV_ID', 'YOUR_REFERENCE_ID');
```

## Initializing a Connection

Register the device with Terra using an authentication token generated **from your backend**:

```dart
final token = 'yourAuthToken'; // Generated from your backend

await TerraFlutterRt.initConnection(token);
```

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

{% openapi src="<https://raw.githubusercontent.com/tryterra/openapi/refs/heads/master/dist/v2-bundled.yaml>" path="/auth/generateAuthToken" method="post" %}
<https://raw.githubusercontent.com/tryterra/openapi/refs/heads/master/dist/v2-bundled.yaml>
{% endopenapi %}

## Device Scanning

Two approaches depending on your needs:

### Option 1: Built-in scan widget

On Android, this shows a native device picker. On iOS, use the `iOSScanView` widget.

```dart
import 'package:terra_flutter_rt/ios_controller.dart';

// Android: shows native picker
await TerraFlutterRt.startDeviceScan(
  Connection.ble,
  connectionCallback: (connected) {
    print('Device connected: $connected');
  },
);

// iOS: embed the native BLE scanner view in your widget tree
// (renders empty Container on Android)
iOSScanView()
```

### Option 2: Programmatic scan with callback

Discover devices one by one and connect manually:

```dart
await TerraFlutterRt.startDeviceScanToCallback(
  Connection.ble,
  (Device device) async {
    print('Found: ${device.deviceName}');
    // Connect to this device
    await TerraFlutterRt.connectDevice(device);
  },
  connectionCallback: (connected) {
    print('Connection status: $connected');
  },
);
```

## Real-Time Data Streaming

Once a device is connected, start streaming data to your app via a callback:

```dart
void onUpdate(Update data) {
  print('${data.type.datatypeString}: ${data.val}');
}

await TerraFlutterRt.startRealtimeToApp(
  Connection.ble,
  [DataType.heartRate, DataType.steps],
  onUpdate,
);
```

To stream to Terra's server instead, see [Your App → Terra](/streaming-api/your-app-greater-than-terra/flutter.md).

## Stop & Disconnect

```dart
await TerraFlutterRt.stopRealtime(Connection.ble);
await TerraFlutterRt.disconnect(Connection.ble);
```

## WatchOS Integration

To stream data from an Apple Watch:

```dart
// Connect to paired Apple Watch (iOS only — returns false on Android)
final connected = await TerraFlutterRt.connectWatchOS();

if (connected) {
  // Start receiving watch data
  await TerraFlutterRt.startRealtimeToApp(
    Connection.watchOs,
    [DataType.heartRate],
    onUpdate,
  );
}
```

{% hint style="info" %}
The watchOS app itself must be written in native Swift using the `Terra` class from the `TerraRTiOS` framework. See the [iOS WatchOS guide](/streaming-api/connect-wearable-to-sdk/ios-swift.md#watchos-integration) for the watch-side setup.
{% endhint %}

You can also control workout sessions on the watch from your Flutter app:

```dart
await TerraFlutterRt.resumeWatchOSWorkout();
await TerraFlutterRt.pauseWatchOSWorkout();
await TerraFlutterRt.stopWatchOSWorkout();
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## 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, and the optional `goal` query parameter:

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

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

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.
