Get started
Official React Native SDK for iHealth Bluetooth health devices.
@ihealth/ihealthlibrary-react-native v2 fully supports the React Native New Architecture (TurboModules) and remains compatible with the old Bridge architecture.
info
React Native device pages in this docs site still contain many legacy DeviceEventEmitter examples. For v2, please use the NativeEventEmitter pattern shown on this page. Device APIs such as startMeasure(), getOfflineData(), and disconnect() remain the same.
Requirements
- React Native
>= 0.76.0 - iOS
12.0+ - Android
7.0+(API 24+)
Installation
npm install @ihealth/ihealthlibrary-react-native
# or
yarn add @ihealth/ihealthlibrary-react-native
iOS setup
Install pods
cd ios && pod install
Add Bluetooth permissions
Add the following entries to Info.plist:
<key>NSBluetoothAlwaysUsageDescription</key>
<string>Required to connect to iHealth devices</string>
<key>NSBluetoothPeripheralUsageDescription</key>
<string>Required to connect to iHealth devices</string>
Enable the New Architecture
For React Native 0.76+, enabling the New Architecture is recommended.
Update ios/Podfile.properties.json:
{
"newArchEnabled": "true"
}
Then run pod install again.
iOS license note
iOS does not require SDK license authentication.
Android setup
Add Bluetooth permissions
Add the following to android/app/src/main/AndroidManifest.xml:
<!-- Bluetooth for Android 11 and below -->
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<!-- Bluetooth for Android 12+ -->
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
Request runtime permissions
import { PermissionsAndroid, Platform } from 'react-native';
export async function requestBluetoothPermissions() {
if (Platform.OS !== 'android') return true;
const permissions =
Platform.Version >= 31
? [
PermissionsAndroid.PERMISSIONS.BLUETOOTH_SCAN,
PermissionsAndroid.PERMISSIONS.BLUETOOTH_CONNECT,
PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
]
: [PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION];
const result = await PermissionsAndroid.requestMultiple(permissions);
return Object.values(result).every(
value => value === PermissionsAndroid.RESULTS.GRANTED
);
}
Authenticate the SDK license
Android requires a .pem license file from iHealth.
- Sign up at dev.ihealthlabs.com.
- Create your app and obtain the
.pemfile from the developer portal. - Place the file under
android/app/src/main/assets/. - Call
sdkAuthWithLicense()once during app startup.
import { iHealthDeviceManagerModule } from '@ihealth/ihealthlibrary-react-native';
iHealthDeviceManagerModule.sdkAuthWithLicense('your_license_file.pem');
Enable the New Architecture
Update android/gradle.properties:
newArchEnabled=true
Quick start
The example below shows a complete scan, connect, and measure flow using the BP5S blood pressure monitor.
import React, { useEffect, useState } from 'react';
import { Button, NativeEventEmitter, NativeModules, Text, View } from 'react-native';
import {
BP5SModule,
iHealthDeviceManagerModule,
} from '@ihealth/ihealthlibrary-react-native';
export default function BP5SScreen() {
const [devices, setDevices] = useState([]);
const [connectedMac, setConnectedMac] = useState(null);
const [result, setResult] = useState('');
useEffect(() => {
const managerEmitter = new NativeEventEmitter(
NativeModules.iHealthDeviceManagerModule
);
const onScan = managerEmitter.addListener(
iHealthDeviceManagerModule.Event_Scan_Device,
event => setDevices(prev => [...prev, event])
);
const onConnected = managerEmitter.addListener(
iHealthDeviceManagerModule.Event_Device_Connected,
event => setConnectedMac(event.mac)
);
const onDisconnect = managerEmitter.addListener(
iHealthDeviceManagerModule.Event_Device_Disconnect,
() => setConnectedMac(null)
);
return () => {
onScan.remove();
onConnected.remove();
onDisconnect.remove();
};
}, []);
useEffect(() => {
const bp5sEmitter = new NativeEventEmitter(NativeModules.BP5SModule);
const onData = bp5sEmitter.addListener(BP5SModule.Event_Notify, event => {
setResult(JSON.stringify(event));
});
return () => onData.remove();
}, []);
return (
<View>
<Button
title="Scan"
onPress={() => {
setDevices([]);
iHealthDeviceManagerModule.startDiscovery(iHealthDeviceManagerModule.BP5S);
}}
/>
{devices.map(device => (
<Button
key={device.mac}
title={`Connect ${device.mac}`}
onPress={() =>
iHealthDeviceManagerModule.connectDevice(
device.mac,
iHealthDeviceManagerModule.BP5S
)
}
/>
))}
{connectedMac && (
<Button
title="Start Measure"
onPress={() => BP5SModule.startMeasure(connectedMac)}
/>
)}
<Text>{result}</Text>
</View>
);
}
Event listening in v2
Required listener pattern
v2.0.0 is a breaking change for event subscriptions: use NativeEventEmitter, not DeviceEventEmitter.
import { NativeEventEmitter, NativeModules } from 'react-native';
import { BP5SModule } from '@ihealth/ihealthlibrary-react-native';
useEffect(() => {
const emitter = new NativeEventEmitter(NativeModules.BP5SModule);
const listener = emitter.addListener(BP5SModule.Event_Notify, event => {
console.log(event);
});
return () => listener.remove();
}, []);
Common mistakes
- Do not use
DeviceEventEmitter. - Do not create the emitter at module top level.
- Create the emitter after the app is mounted, usually inside
useEffect. - Always remove listeners on unmount.
NativeModules mapping
Use the matching native module when creating the emitter:
iHealthDeviceManagerModule->NativeModules.iHealthDeviceManagerModuleBP5SModule->NativeModules.BP5SModulePO3Module->NativeModules.PO3ModuleHS2SModule->NativeModules.HS2SModuleBG5SModule->NativeModules.BG5SModuleAM6Module->NativeModules.AM6ModuleBTMModule->NativeModules.BTMModule
Device management
Scan for devices
import { iHealthDeviceManagerModule } from '@ihealth/ihealthlibrary-react-native';
iHealthDeviceManagerModule.startDiscovery(iHealthDeviceManagerModule.BP5S);
iHealthDeviceManagerModule.stopDiscovery();
Common device type constants include:
iHealthDeviceManagerModule.BP5iHealthDeviceManagerModule.BP5SiHealthDeviceManagerModule.BP7iHealthDeviceManagerModule.BP7SiHealthDeviceManagerModule.BP3LiHealthDeviceManagerModule.KN550iHealthDeviceManagerModule.PO3iHealthDeviceManagerModule.PO1iHealthDeviceManagerModule.HS2SiHealthDeviceManagerModule.BG5SiHealthDeviceManagerModule.BG1AiHealthDeviceManagerModule.BG1SiHealthDeviceManagerModule.AM3SiHealthDeviceManagerModule.AM4iHealthDeviceManagerModule.AM5iHealthDeviceManagerModule.AM6iHealthDeviceManagerModule.BTMiHealthDeviceManagerModule.NT13BiHealthDeviceManagerModule.TS28BiHealthDeviceManagerModule.PT3SBT
Connect and disconnect
iHealthDeviceManagerModule.connectDevice(mac, iHealthDeviceManagerModule.BP5S);
iHealthDeviceManagerModule.disconnectDevice(mac, iHealthDeviceManagerModule.BP5S);
Device manager events
Listen on NativeModules.iHealthDeviceManagerModule for:
Event_Scan_DeviceEvent_Scan_FinishEvent_Device_ConnectedEvent_Device_Connect_FailedEvent_Device_DisconnectEvent_Authenticate_Resulton Android only
Supported devices
React Native v2 supports the following device families:
- Blood pressure:
BP5,BP5S,BP3L,BP7,BP7S,KN-550BT - Blood oxygen:
PO3,PO1 - Scales:
HS2S,HS2S Pro,HS4S,HS6 - Blood glucose:
BG5S,BG5,BG1,BG1A,BG1S - Activity trackers:
AM3S,AM4,AM5,AM6 - Thermometers:
BTM,TS28B,NT13B,PT3SBT
See the left sidebar for per-device API details.
Migration from v1.x
If you are upgrading from React Native SDK v1.x, the main code change is the event listener migration:
// v1.x
import { DeviceEventEmitter } from 'react-native';
DeviceEventEmitter.addListener(BP5SModule.Event_Notify, handler);
// v2.x
import { NativeEventEmitter, NativeModules } from 'react-native';
const emitter = new NativeEventEmitter(NativeModules.BP5SModule);
emitter.addListener(BP5SModule.Event_Notify, handler);
Your device API calls generally do not need to change.
FAQ
I can scan and connect, but I never receive measurement data
Make sure the NativeEventEmitter is created inside useEffect rather than at module top level or too early in component initialization.
Android calls have no effect
Check that:
- the
.pemfile is present inandroid/app/src/main/assets/ sdkAuthWithLicense()is called once on app startup- Bluetooth runtime permissions were granted