> 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/react-native.md).

# React Native

## Prerequisites

1. Install the [`react-native-terra-rt-react`](https://www.npmjs.com/package/react-native-terra-rt-react) package:

```bash
npm install react-native-terra-rt-react
```

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 `Connections.APPLE`)
3. **iOS:** Run `pod install` in your `/ios` directory.
4. **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 %}

Set up event emitters for receiving data, then initialize:

```tsx
import { NativeEventEmitter, NativeModules, Platform } from 'react-native';
import {
  initTerra, initConnection, startDeviceScan, startRealtime,
  stopRealtime, disconnect, getUserId,
  Connections, DataTypes,
} from 'react-native-terra-rt-react';
import type { Update, Device, SuccessMessage } from 'react-native-terra-rt-react';

// Set up event listeners (do this once, e.g. in useEffect)
const updateEmitter = new NativeEventEmitter(NativeModules.UpdateHandler);
updateEmitter.addListener('Update', (update: Update) => {
  console.log(`${update.type}: ${update.val}`);
});

const deviceEmitter = new NativeEventEmitter(NativeModules.DeviceHandler);
deviceEmitter.addListener('Device', (device: Device) => {
  console.log(`Found device: ${device.name}`);
});

const connectionEmitter = new NativeEventEmitter(NativeModules.ConnectionHandler);
connectionEmitter.addListener('ConnectionUpdate', (connected: boolean) => {
  console.log(`Websocket connected: ${connected}`);
});

// Initialize the SDK
const result = await initTerra('YOUR_DEV_ID', 'YOUR_REFERENCE_ID');
if (!result.success) {
  console.error('Failed to initialize:', result.error);
}
```

## Initializing a Connection

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

```tsx
const token = 'yourAuthToken'; // Generated from your backend

const connResult = await initConnection(token);
if (connResult.success) {
  console.log('Connection initialized!');
}
```

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

BLE device scanning works differently on iOS and Android:

{% tabs %}
{% tab title="Android" %}
On Android, use `startDeviceScan` which shows a built-in device picker:

```tsx
const scanResult = await startDeviceScan(Connections.BLE);
if (scanResult.success) {
  console.log('Device connected!');
}
```

{% endtab %}

{% tab title="iOS" %}
On iOS, `startDeviceScan` is not supported. Instead, use the `BLWidget` native view component:

```tsx
import { requireNativeComponent } from 'react-native';

const BLWidget = requireNativeComponent('BLWidget');

// In your JSX:
<BLWidget
  style={{ flex: 1 }}
  withCache={false}
  onSuccessfulConnection={(event) => {
    console.log('Connected:', event.nativeEvent.success);
  }}
/>
```

Render this component when you want to show the BLE scanner. It displays a list of discovered devices and handles connection automatically.
{% endtab %}
{% endtabs %}

**Platform-conditional pattern:**

```tsx
const startScanning = () => {
  if (Platform.OS === 'android') {
    startDeviceScan(Connections.BLE).then((result) => {
      console.log('Connected:', result.success);
    });
  } else {
    // Show BLWidget in your UI (see iOS tab above)
  }
};
```

## Real-Time Data Streaming

Once a device is connected, start streaming data. Updates arrive via the `Update` event emitter you set up earlier.

```tsx
const dataTypes = [DataTypes.HEART_RATE, DataTypes.STEPS];

// Start streaming locally (no server)
await startRealtime(Connections.BLE, dataTypes);
```

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

## Stop & Disconnect

```tsx
await stopRealtime(Connections.BLE);
await disconnect(Connections.BLE);
```

## WatchOS Integration

To stream data from an Apple Watch, call `connectWithWatchOS()` on the iOS companion app side, then start streaming with `Connections.WATCH_OS`:

```tsx
import { connectWithWatchOS } from 'react-native-terra-rt-react';

// Connect to paired Apple Watch (iOS only — rejects on Android)
await connectWithWatchOS();

// Start receiving watch data
await startRealtime(Connections.WATCH_OS, [DataTypes.HEART_RATE]);
```

{% 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 %}


---

# 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/react-native.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.
