Skip to main content

Apple Health

danger

If you are interested in configure and use Apple Health and Health Connect (Android) we highly recommend to refer to Rook SDK

This SDK enables apps to extract and upload data from Apple Health, with this sdk you will be able to extract and upload data, if you need check our app demo

Installation

To build a project using the Rook Apple Health in React native you need to use at least react v16 and react native v65. This SDK is only available on iOS this means that it won't work with Android.

The SDK requires Xcode 14.0.1 or higher. To run your app using the Rook SDK on a connected device with iOS 16.2 or later you need Xcode 14.2 or higher.

The minimum version of iOS is 13.0

npm

npm i react-native-rook-sdk-apple-health

yarn

yarn add react-native-rook-sdk-apple-health

Configuration

Add your client uuid in order to be authorized, follow the next example, add at the top level of your tree components the RookSyncGate, password refers to the secret key.

import { RookSyncGate } from "react-native-rook-sdk-apple-health";

<RookSyncGate
environment="sandbox | production"
clientUUID="YOUR_CLIENT_UUID"
password="YOUR_PASSWORD"
enableLogs={true | false | undefined}
enableBackgroundSync={true | false}
enableEventsBackgroundSync={true | false | undefined}
>
<YOUR_COMPONENTS />
</RookSyncGate>;

The value of enableLogs will display or not local logs in the console for certain SDK operations. We recommend you to ask your users if they want to enable the automatic sync, then save their preference in local storage and set enableBackgroundSync conditionally.

The value of enableEventsBackgroundSync will include or exclude the events of the background sync.

Then we need to add Health Kit Framework to our project in order to that please:

  • Open your project in Xcode.
  • Click on your project file in the Project Navigator.
  • Select your target and then click on the "Build Phases" tab.
  • Click on the "+" button under the "Link Binary With Libraries" section and select "HealthKit.framework" from the list.
  • Select your target and then click on the "Signing Capabilities" tab.
  • Click on "Add Capability" and search for "HealthKit"

Additionally add the following to the info.plist

<key>NSHealthShareUsageDescription</key>
<string>This app requires access to your health and fitness data in order to track your workouts and activity levels.</string>
<key>NSHealthUpdateUsageDescription</key>
<string>This app requires permission to write healt data to HealthKit.</string>

Usage

useRookConfiguration

This hook will help you to configure the user ID you want to sync.

const useRookConfiguration = () => {
ready: boolean;
getUserID: () => Promise<string>;
updateUserID: (userID: string) => Promise<boolean>;
clearUserID: () => Promise<boolean>;
syncUserTimeZone: () => Promise<boolean>;
removeUserFromRook: () => Promise<boolean>;
enableSyncYesterday: () => Promise<boolean>;
disableSyncYesterday: () => Promise<boolean>;
}
  • ready: Indicates when the hook is ready to work.
  • getUserID: Return the current user ID.
  • updateUserID: Change the current user ID.
  • clearUserID: Clear the current user ID.
  • syncUserTimeZone: Update the time zone of the user, you should only call this when is strictly necessary.
  • removeUserFromRook: Remove the user from the Rook services.
  • enableSyncYesterday: This method enables the automatic upload of the summaries from the previous day of the current device's date. Every time the user opens the app it will try to upload the summaries, before use this method is necessary to add a user id and request permissions.
  • disableSyncYesterday: This method disables the automatic upload of the summaries from the previous day of the current device's date.

Note: If you delete the user from the Rook services you have to create the user again with updateUserID and request permissions.

info

Any call to updateUserID the userID will override the previous userID and reset the sync status, so if you are using background sync all health data will synchronize again the next time the app is launched.

Continuous Upload


The hook useRookConfiguration helps you to enable or disable continuous data upload. every time a user opens the app, the sdk will try to upload the data from the previous day of the device's current date.

Note: before enable this feature it is necessary to add a user a request permission from apple health

MethodDescription
enableYesterdaySyncThis method enables the automatic upload of the summaries from the previous day of the current device's date. Every time the user opens the app it will try to upload the summaries, before use this method is necessary to add a user id and request permissions.
disableYesterdaySyncThis method disables the automatic upload of the summaries from the previous day of the current device's date.

useRookPermissions

This hook will help you to request permissions to extract data.

export type CheckPermissionsParam = {
type: PermissionsType;
};

export type PermissionStatus =
| "permissionNotRequested"
| "permissionIndeterminate"
| "permissionGranted";

export type PermissionsType =
| "appleExerciseTime"
| "appleMoveTime"
| "appleStandTime"
| "basalEnergyBurned"
| "activeEnergyBurned"
| "stepCount"
| "distanceCycling"
| "distanceWalkingRunning"
| "distanceSwimming"
| "swimmingStrokeCount"
| "flightsClimbed"
| "walkingSpeed"
| "walkingStepLength"
| "runningPower"
| "runningSpeed"
| "height"
| "bodyMass"
| "bodyMassIndex"
| "waistCircumference"
| "bodyFatPercentage"
| "bodyTemperature"
| "basalBodyTemperature"
| "appleSleepingWristTemperature"
| "heartRate"
| "restingHeartRate"
| "walkingHeartRateAverage"
| "heartRateVariabilitySDNN"
| "electrocardiogram"
| "workout"
| "sleepAnalysis"
| "vo2Max"
| "oxygenSaturation"
| "respiratoryRate"
| "uvExposure"
| "biologicalSex"
| "dateOfBirth"
| "bloodPressureSystolic"
| "bloodPressureDiastolic"
| "bloodGlucose"
| "dietaryEnergyConsumed"
| "dietaryProtein"
| "dietarySugar"
| "dietaryFatTotal"
| "dietaryCarbohydrates"
| "dietaryFiber"
| "dietarySodium"
| "dietaryCholesterol";

const useRookPermissions: () => {
ready: boolean;
checkPermissionsStatus: (
param?: CheckPermissionsParam
) => Promise<PermissionStatus>;
openAppleHealthSettings: () => Promise<void>;
requestAllPermissions: () => Promise<void>;
requestBodyPermissions: () => Promise<void>;
requestPhysicalPermissions: () => Promise<void>;
requestSleepPermissions: () => Promise<void>;
requestUserInfoPermissions: () => Promise<void>;
};
  • ready: Indicates when the hook is ready to work.
  • checkPermissionsStatus: The SDK try to infer if the SDK has permissions granted for the specified type by default looks for steps permissions, the result indicates the status of the permissions.
    • permissionNotRequested: Indicates that the screen of the permissions is not presented yet.
    • permissionNotIndeterminate: Indicates that could not be determined the status cause maybe the user do not have data available at the moment of the request or the permissions are not granted
    • permissionGranted: The SDK could extract information.
  • openAppleHealthSettings: Open the health app.
  • requestAllPermissions: Request all the permissions.
  • requestSleepPermissions: Request sleep the permissions.
  • requestPhysicalPermissions: Request Physical the permissions.
  • requestBodyPermissions: Request Body the permissions.
  • requestUserInfoPermissions: Request User Info the permissions.
danger

The callback of each method will return a promise if the permission window was successfully presented. This value does not indicate whether the user actually granted permission. Please keep in mind, that Apple Health does not allow to check the status of permission for types which were requested to be read. If the user does not allow data types reading by mistake or on purpose, it simply appears as if there is no data of the requested type in the HealthKit store. Any further change must be performed by the user through the Apple Health application.

useRookBackGroundSync

The hook useRookBackGround helps to enable background upload for summaries, this allows to your app to upload health data while your app is in background. it is recommended to combine continuous upload, background upload and manual sync for a better performance.

const useRookBackGround = () => {
ready: boolean;
enableBackgroundForSummaries: () => Promise<boolean>;
disableBackgroundForSummaries: () => Promise<boolean>;
enableBackgroundForEvents: () => Promise<boolean>;
disableBackgroundForEvents: () => Promise<boolean>;
isBackGroundForSummariesEnable: () => Promise<boolean>;
isBackGroundForEventsEnable: () => Promise<boolean>;
}
  • ready: Indicates when the hook is ready to work.
  • enableBackgroundForSummaries : Enables the background updates for summaries.
  • disableBackgroundForSummaries: Disables the background updates for summaries.
  • enableBackgroundForEvents: Enables background updates for events.
  • disableBackgroundForEvents: Disables the background updates for events.
  • isBackGroundForSummariesEnable: Checks if the summaries are syncing in the background
  • isBackGroundForEventsEnable: Checks if the events are syncing in the background

Note: Please note that for security, iOS devices encrypt the HealthKit storage when users lock their devices. As a result, apps may not be able to read data from Apple Health when it runs in the background. Please refer to the official documentation for more information.

MethodDescription
enableBackgroundForSummariesThis method enables the background upload of the summaries.
disableBackgroundForSummariesThis method disables the background upload of the summaries.
enableBackgroundForEventsThis method disables background upload of the events.
disableBackgroundForEventsThis method disables background upload of the events.

To configure background upload you need to follow the steps bellow:

  • Add health kit to your project and enable background delivery.
  • Add Background modes and enable Background fetch.

background_delivery

  • In the app delegate of your app add the setBackListeners method in didFinishLaunchingWithOptions function.

Example


#import "AppDelegate.h"
#import "RookSDK/RookSDK-Swift.h"
#import <React/RCTBundleURLProvider.h>

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.moduleName = @"RookSdkAppleHealthExample";
// You can add your custom initial props in the dictionary below.
// They will be passed down to the ViewController used by React Native.
self.initialProps = @{};
[[RookBackGroundSync shared] setBackListeners];

return [super application:application didFinishLaunchingWithOptions:launchOptions];
}

- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
{
#if DEBUG
return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index"];
#else
return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
#endif
}

@end

useRookSummaries

This hook will help you to extract and send data from apple health to Rook servers.

const useRookSummaries: () => {
ready: boolean;
syncSummaries: () => Promise<boolean>;
syncSleepSummary: (date: string) => Promise<boolean>;
syncPhysicalSummary: (date: string) => Promise<boolean>;
syncBodySummary: (date: string) => Promise<boolean>;
syncPendingSummaries: () => Promise<boolean>;
};
  • ready: Indicates when the hook is ready to work.
  • syncSummaries : Upload all the data of summaries from the days that have not been uploaded, and if it is the first time it is being executed, upload the last fifteen days.
  • syncSleepSummary: Send the summary to rook servers.
  • syncBodySummary: Send the summary to rook servers.
  • syncPhysicalSummary: Send the summary to rook servers.
  • syncPendingSummaries: In case you try to sync a summary and fail, this function help to try to send again.

useRookEvents

This hook will help you to extract and send data from apple health to Rook servers.

const useRookEvents: () => {
ready: boolean;
syncEvents: () => Promise<boolean>;
syncBodyHeartRateEvent: (date: string) => Promise<boolean>;
syncPhysicalHeartRateEvent: (date: string) => Promise<boolean>;
syncBodyOxygenationEvent: (date: string) => Promise<boolean>;
syncPhysicalOxygenationEvent: (date: string) => Promise<boolean>;
syncTrainingEvent: (date: string) => Promise<boolean>;
syncTemperatureEvent: (date: string) => Promise<boolean>;
syncPressureEvent: (date: string) => Promise<boolean>;
syncGlucoseEvent: (date: string) => Promise<boolean>;
};
  • ready: Indicates when the hook is ready to work.
  • syncEvents: Upload all the data of events from the days that have not been uploaded, and if it is the first time it is being executed, upload the last fifteen days.
  • syncBodyHeartRateEvents: Send body heart rate events for the specified date.
  • syncPhysicalHeartRateEvents: Send physical heart rate events for the specified date.
  • syncBodyOxygenationEvents: Send body oxygenation events for the specified date.
  • syncPhysicalOxygenationEvents: Send physical oxygenation events for the specified date.
  • syncTrainingEvent: Send training events for the specified date.
  • syncTemperatureEvent: Send temperature events for the specified date.
  • syncPressureEvent: Send pressure events for the specified date.
  • syncGlucoseEvent: Send glucose events for the specified date.
  • syncBodyMetricsEvent: Send body metrics events for the specified date, like change of weight or height.

useRookDataSources

This hook enables you to access available ROOK data sources by requesting a JSON object with the information or by displaying a basic view with a set of buttons.

export interface DataSource {
name: string;
authorizationURL: string;
imageUrl: string;
description: string;
connected: boolean;
}

type options = {
redirectURL?: string;
};

export type DataSourceType =
| "Garmin"
| "Oura"
| "Polar"
| "Fitbit"
| "Withings"
| "Whoop";

const useRookDataSources: () => {
ready: boolean;
getAvailableDataSources: (options?: options) => Promise<DataSource[]>;
presentDataSourceView: (options?: options) => Promise<boolean>;
revokeDataSource: (type: DataSourceType) => Promise<boolean>;
};
  • ready: Indicates when the hook is ready to work.
  • getAvailableDataSources: Return a list of available data sources, with the ability to configure with the options param
  • presentDataSourceView: Present a default view with the available data sources, with the ability to configure with the options param
  • revokeDataSource: Revokes user authorization for the specified data source.

useRookVariable

This hook will help you to extract and send data from apple health to Rook servers.

const useRookVariable: () => {
ready: boolean;
getTodaySteps: () => Promise<string>;
};
  • ready: Indicates when the hook is ready to work.
  • getTodaySteps: Gets the steps accumulated for the current day.

Additional information

Listen for Permissions Notifications

The ROOK SDK allows you to listen for permission notifications, enabling you to respond to changes in permissions, as shown in the following example:

import { getRookModule } from "react-native-rook-sdk";

...

useEffect(() => {
const rookModule = getRookModule();
const eventEmitter = new NativeEventEmitter(rookModule);

// Subscribe to the event
const subscription = eventEmitter.addListener(
"ROOK_NOTIFICATION",
handleRookNotification
);

// Clean up subscription when the component unmounts
return () => {
subscription.remove();
};
}, []);

const handleRookNotification = (notification) => {
const { type, ...rest } = notification;

switch (type) {
case "ROOK_BACKGROUND_ERROR":
console.log(`Background error: ${rest}`);
break;
case "ROOK_BACKGROUND_ENABLED":
console.log(`Background services enabled: ${rest}`);
break;
default:
console.log(`Unknown notification: ${rest}`);
}
};

The notification type indicates the following:

  • ROOK_BACKGROUND_ANDROID_PERMISSIONS: Specifies whether the user has granted Android permissions.
  • ROOK_HEALTH_CONNECT_PERMISSIONS: Specifies whether the user has granted Health Connect permissions.
  • ROOK_BACKGROUND_ENABLED: Indicates whether background sync was successfully enabled."