# HealthKit

* [General Info](#general-info)
* [Bubble.io Web Apps](#bubble.io-web-apps)
* [Other Websites](#other-websites)

## General Info

HealthKit is a framework developed by Apple that allows health and wellness data to be collected, analyzed, and shared across different applications.

By taking advantage of the HealthKit framework, you can create a more robust and effective health and wellness app that meets the needs of today’s mobile-savvy users.

HealthKit integration can improve the user experience of your health and wellness app, provide more accurate data and insights, increase user engagement, and enhance data security and privacy. By taking advantage of the HealthKit framework, you can create a more robust and effective health and wellness app that meets the needs of today’s mobile-savvy users.

HealthKit is a huge framework, but Natively has access to several values (for now). Quantity, characteristics, and category.

1. Each of these types **needs** to be **requested permission** to read them.
2. **Quantity Values** are calculated with a default Apple's [HKStatisticsCollection](https://developer.apple.com/documentation/healthkit/hkstatisticscollectionquery)
3. All **Quantity Values** have different values to work with (e.g. milliseconds, count/s, count/min, etc.)



**Quantity Values:**

*   &#x20;**HRV (Heart Rate Variability SDNN)**

    The standard deviation of heartbeat intervals, measured in _**milliseconds**_
*   **RHR (Resting Heart Rate)**

    User’s resting heart rate, measured in _**count/s**_
* **BMI (Body Mass Index)**\
  User’s body mass index, measured in _**count**_
* **HEIGHT**\
  User’s height, measured in _**centimeters**_
* **BODY\_MASS - User's body mass**\
  User's body mass, measured in _**kilograms**_
* **STEPS**\
  User's steps, measured in _**count**_
* **HEART\_RATE**\
  User's heart rate, measured in _**count/min**_
* **ACTIVE\_ENERGY**\
  User's burned active energy, measured in _**kilocalories**_
* **BLOOD\_OXYGEN**\
  User's blood oxygen, measured in _**percent**_

**Characteristics Values:**

* **DATE\_OF\_BIRTH**\
  User's age, measured in _**years**_ _(e.g. **67**)_
* **BLOOD\_TYPE**\
  User's blood type (e.g. _**AB- / AB+ / A- / B+ / B- / B+ / O- / O+ / NOT\_SET**)_
* **SEX**\
  User's biological sex - (e.g. _**MEN / WOMAN / OTHER / NOT\_SET**)_
* **SKIN\_TYPE**\
  User's skin type - (e.g. _**I / II / III / IV / V / VI / NOT\_SET**)_
* **WHEELCHAIR**\
  A value indicating the user’s wheelchair use - (e.g. _**YES / NO / NOT\_SET**)_

**Category Values:**

*   [**SLEEP\_ANALYSIS**](https://developer.apple.com/documentation/healthkit/hkcategoryvaluesleepanalysis)

    Has a few different types:

    * **IN\_BED**
    * **AWAKE**
    * **ASLEEP** - available only in iOS 16+ (only with Apple Watch)
    * **ASLEEP\_REM** - available only in iOS 16+ (only with Apple Watch)
    * **ASLEEP\_DEEP** - available only in iOS 16+ (only with Apple Watch)
    * **ASLEEP\_UNSPECIFIED**
    * **UNKNOWN**

<figure><img src="https://docs-assets.developer.apple.com/published/88d1eb5c0f/renderedDark2x-1667248100.png" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
More details about each Sleep Analysis value can be found [here](https://developer.apple.com/documentation/healthkit/hkcategoryvaluesleepanalysis)
{% endhint %}



* **ACTIVITY\_SUMMARY**\
  Main fields:
  * **Active Energy Burned** (.activeBurned) - kilocalories
  * **Active Energy Goal** (.activeGoal) - kilocalories
  * **Exercise Time** (.exerciseTime) - time interval in minutes
  * **Exercise Goal** (.exerciseGoal) - time interval in minutes
  * **Move Time** (.moveTime) - time interval in minutes **(available only in iOS 14+)**
  * **Move Goal** (.moveGoal) - time interval in minutes **(available only in iOS 14+)**
  * **Stand Hours** (.standHours) - count
  * **Stand Goal** (.standGoal) - count

{% hint style="info" %}
More details about each Activity Summary value can be found [here](https://developer.apple.com/documentation/healthkit/hkactivitysummary)
{% endhint %}

* **WORKOUTS (JS SDK >= 2.13.0)**\
  Main fields:
  * **Total Energy Burned - kilocalories**
  * **Basal Energy Burned - kilocalories (>iOS 16)**
  * **Active Energy Burned - kilocalories (>iOS 16)**
  * **Workout Name - string, more details** [**here**](https://stackoverflow.com/a/71454827)
  * **Heart Rate - count/min**
  * **Start Date - date**
  * **End Date - date**
  * **Duration - seconds**\


**To implement HealthKit correctly you need to:**

1. [Turn on **DEBUG** mode](../how-to-get-started#mode-headers-optional) for a development purpose
2. Check if HealthKit is available on a device. (iPads are not supported)
3. Request permissions for specific Values (e.g. SKIN\_TYPE, HEART\_RATE, SLEEP\_ANALYSIS, WORKOUTS)
4. We're highly recommending writing a good [Permission Description](../../natively-platform/features/healthkit) that explains to the user why you need such permission (otherwise, you will be rejected by Apple, or the User will not give access to specific data)
5. Request the data and receive it
6. All values requests are taking some time (except characteristics values). The calculation happens on a device, so if you're requesting a lot of data for an extended period (3-12 months), it might take 5-30 seconds to return it.



## Bubble.io Web Apps

HealthKit can be integrated with our Bubble.io plugin. More details about it can be found [here](how-to-get-started).

Plugin contains 3 elements: **Natively - HealthKit BASE,** **Natively - HealthKit SLEEP** & **Natively - HealthKit ACTIVITY**

The first is used for general purposes like requesting permissions and getting characteristics and quantity values. The second is specifically for Category Value **Sleep Analysis.** And the third is for the **Activity Summary.**

### 1. Natively - HealthKit BASE

#### Actions:

* Get Health Availability - Checking if HealthKit is available on a device
* Request Permissions
  * read (e.g. **HRV, RHR, SLEEP\_ANALYSIS, BMI, etc.)**
* Get Permission Status - Checking if you've requested permission before (**After requesting permission once, it might return YES every time, it doesn't guarantee that the user has provided access to their data cause of privacy reasons by Apple**)
  * type (e.g. **HRV, RHR, SLEEP\_ANALYSIS, BMI, etc.)**
* Get All **Characteristic Values**
* Get Statistic **Quantity Values**
  * data\_type (**Quantity Values** only!) (e.g. **HRV, RHR, BMI, etc.)**
  * interval (DAY / WEEK / MONTH / YEAR) - means how HealthKit will return a data \
    Daily, Weekly ... and so on.
  * start\_date - The start date from which HealthKit will search and return a data
  * end\_date - End date till which HealthKit will search and return a data

{% hint style="info" %}
So basically, if you wanna get the daily steps to count for the current month you will need to select **DAY** interval with **start\_date=startofmonth** & **end\_date=today**
{% endhint %}

#### Events:

* Get Permission Value Updated - Get called once the state updated
* Get Health Availability Value Updated - Get called once the state updated
* Request Permission Value Updated - Get called once the state updated
* Get All Characteristics Updated - Get called once the state updated
* Get Quantity Updated - Get called once the state updated

#### States:

* Latest Get Health Availability Result
* Latest Get Permission Result - **After requesting permission once, it might return YES every time. It doesn't guarantee that the user has provided access to their data cause of privacy reasons by Apple**
* Latest Request Permission Result
* Latest All Characteristics (CharacteristicObject)
  * Age - number
  * Sex - text  (e.g. _**MEN / WOMAN / OTHER / NOT\_SET**)_
  * Blood - text  (e.g. _**AB- / AB+ / A- / B+ / B- / B+ / O- / O+ / NOT\_SET**)_
  * Skin - text  (e.g. _**I / II / III / IV / V / VI / NOT\_SET**)_
  * Wheelchair - text  (e.g. _**YES / NO / NOT\_SET**)_
* Latest Get Quantity Response - (QuantityStatisticsObject)

{% hint style="warning" %}
IMPORTANT! Set QuantityStatisticsObject & CharacteristicObject type from a list in the element field.\
No need to create a new type for this. It's already defined.
{% endhint %}

Here is a small example of setup:

{% embed url="https://bubble.io/page?id=nativelyqa&name=healthkit_base&tab=tabs-1&test_plugin=1654595882459x381599056563798000_current&type=page" %}



### 2. Natively - HealthKit SLEEP

SLEEP element is used in combination with BASE. So basically, you need the BASE element to request permissions and SLEEP for requesting sleep analysis data.

#### Actions:

* Get Daily Sleep Analysis
  * limit (e.g. 100) - related to a count of data that will be fetched from HealthKit and calculated. You can use any value that works best for you. To remove a limit, set a value to 0.
  * end\_date - End date till which HealthKit will search and return a data
  * start\_date - The start date from which HealthKit will search and return a data

#### Events:

* Get Daily Sleep Analysis Updated

#### States:

* Latest Get Sleep Analysis Response - (SleepAnalysisObject)

{% hint style="warning" %}
IMPORTANT! Set SleepAnalysisObject type from a list in the element field.\
No need to create a new type for this. It's already defined.
{% endhint %}

Here is a small example of setup:

{% embed url="https://bubble.io/page?id=nativelyqa&name=healthkit_sleep&tab=tabs-1&test_plugin=1654595882459x381599056563798000_current&type=page" %}



### 3. Natively - HealthKit ACTIVITY

ACTIVITY element is used in combination with BASE. So basically, you need the BASE element to request permissions and ACTIVITY for requesting sleep analysis data.

#### Actions:

* Get Activity Summary
  * end\_date - End date till which HealthKit will search and return a data
  * start\_date - The start date from which HealthKit will search and return a data

#### Events:

* Get Activity Summary Updated - Get called once the state updated

#### States:

* Latest Get Activity Summary Response - (ActivitySummaryObject)

{% hint style="warning" %}
IMPORTANT! Set ActivitySummaryObject type from a list in the element field.\
No need to create a new type for this. It's already defined.
{% endhint %}

Here is a small example of setup:

{% embed url="https://bubble.io/page?id=nativelyqa&name=healthkit_activity&tab=tabs-1&test_plugin=1654595882459x381599056563798000_current&type=page" %}

### 4. Natively - HealthKit WORKOUT

WORKOUT element is used in combination with BASE. So basically, you need the BASE element to request permissions and WORKOUT for requesting workouts data.

#### Actions:

* Get Workouts
  * limit (e.g. 100) - related to a count of data that will be fetched from HealthKit and calculated. You can use any value that works best for you. To remove a limit, set a value to 0.
  * end\_date - End date till which HealthKit will search and return a data
  * start\_date - The start date from which HealthKit will search and return a data

#### Events:

* Get Workout Updated

#### States:

* Latest Get Workout Response - (WorkoutObject)

{% hint style="warning" %}
IMPORTANT! Set WorkoutObject type from a list in the element field.\
No need to create a new type for this. It's already defined.
{% endhint %}

Here is a small example of setup:

{% embed url="https://bubble.io/page?id=nativelyqa&name=healthkit_workout&tab=tabs-1&test_plugin=1654595882459x381599056563798000_current&type=page" %}

## Other websites

#### Refer for types, and values on Bubble Doc ^

For methods, name-check the NativelyHealth object interface by following this [URL](https://github.com/No-Code-No-Problem/natively-sdk/blob/2680e4f032b8cfde99090d5c557c00e39cc2bbbf/natively-frontend.js#L545-L590)



### 'Get Workouts' Example (SDK >=2.13.0)

```javascript
// 4. Natively HealthKit Workout
const health = NativelyHealth()
// 1. Check HealthKit availability
health.available((res, err) => {
    if (err) {
        alert(err)
        return;
    }
    if (res.status) {
        // 2. Request permission
        health.requestAuthorization([], ["WORKOUTS"], (res, err) => {
            if (err) {
                alert(err)
                return;
            }
            if (res.status) { // true/false
                const today = new Date();
                const weekAgo = new Date();
                weekAgo.setDate(today.getDate() - 7);
                
                // 3. Get workouts in date range
                health.getWorkouts(today, weekAgo, (res, err) = {
                    if (err) {
                        alert(err)
                        return;
                    }
                    const result = res.result;
                    console.log(result);
                    /*
                    {
                      "endDate": 1676945111,
                      "duration": 3000, // seconds
                      "startDate": 1676945291,
                      "workoutName": "workoutName", // https://stackoverflow.com/a/71454827
                      "activeBurned": 0, // kilocal >=iOS 16
                      "basalBurned": 0, // kilocal >=iOS 16
                      "totalBurned": 0, // kilocal
                      "heartRate": 0 // count/min >=iOS 16
                    }
                    */
                })
            }
        })
    }
})
```
