Coder Social home page Coder Social logo

kingstinct / react-native-healthkit Goto Github PK

View Code? Open in Web Editor NEW
179.0 7.0 41.0 28.02 MB

HealthKit bindings for React Native with TypeScript

Home Page: https://kingstinct.com/react-native-healthkit/

License: MIT License

JavaScript 2.54% TypeScript 64.68% Swift 28.36% Ruby 0.65% Objective-C 3.25% Shell 0.08% C 0.04% Objective-C++ 0.41%
reactnative healthkit typescript ios react-hooks

react-native-healthkit's People

Contributors

burivuhster avatar deep108 avatar dependabot[bot] avatar jonstuebe avatar josh- avatar jurgenvdwardt avatar kalvin807 avatar kevinroehl avatar monder avatar mphill avatar oldratip avatar plahteenlahti avatar robertherber avatar robrechtme avatar thomasmoran avatar veritypowell avatar vladyslavroom4 avatar walterholohan avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

react-native-healthkit's Issues

Incorrect metadata key name for deduplicating records

https://github.com/Kingstinct/react-native-healthkit/blob/49c81d7fcf75e7e970c6841696c858a5d0e73ce5/src/native-types.ts#L328-L329

According to Apple, the correct names are HKMetadataKeySyncIdentifier and HKMetadataKeySyncVersion. I actually tried both key names, but only the HKMetadataKeyXXX key correctly deduplicated the data.

Thanks for this amazing library; it's the most comprehensive react native bridge for HealthKit ❤️

EDIT: I now notice other keys missing the MetadataKey prefix, such as HKMetadataKeyReferenceRangeLowerLimit

Check Health app installed on device

Hi team,
Is there any way to check if user device installed Health app or not? It's as like as the method

isAvailable(callback); // Checks is GoogleFit available for current account / installed on device

in react-native-google-fit?
Thanks in advanced.

Check if protected files are available in background

When the device is locked, health data becomes inaccessible and the following error is thrown in background.

Fatal error: 'try!' expression unexpectedly raised an error: Error Domain=com.apple.healthkit Code=6 "Protected health data is inaccessible" UserInfo={NSLocalizedDescription=Protected health data is inaccessible}

One solution could be to return the value of isProtectedDataAvailable or listen to applicationProtectedDataWillBecomeUnavailable / applicationProtectedDataDidBecomeAvailable or protectedDataDidBecomeAvailableNotification / protectedDataWillBecomeUnavailableNotification to check that protected files are available.

Deleting workouts

Hello, thank you for the great work with this library. It's been really helpful having such a close mapping to the native APIs.

I am trying to access a method to delete a workout by uuid. I see the delete samples methods, however I'm not seeing an option type for workouts. Any direction here would be great.

Thanks.

Health data generation

Thanks for the nice modern lib in TypeScript!

How do you handle testing on the simulator, given that it has no health data? Would it make sense to have an ability to generate test data?

Migrating from agencyenterprise/react-native-health

This is not really an issue, just a thread for those who are looking to move away from agencyenterprise/react-native-health.

I was looking for an alternative that doesn't hide functionality, uses non-deprecated solutions and comes with proper type definition. Even though this package doesn't have extensive documentation I think it's still a pretty good alternative. (Also, It's in swift which is a bonus over objc)

I've spent some time on creating a simple 1-way workout sync and I ended up using the following snippet:

import HealthKit, {
  HKQuantityTypeIdentifier,
  HKWorkoutActivityType,
  HKWorkoutTypeIdentifier,
} from '@kingstinct/react-native-healthkit';
import { v4 as uuid } from 'uuid';

const main = async () => {
  const isAuthed = await HealthKit.requestAuthorization(
    [HKWorkoutTypeIdentifier, HKQuantityTypeIdentifier.activeEnergyBurned],
    [HKWorkoutTypeIdentifier, HKQuantityTypeIdentifier.activeEnergyBurned],
  );

  if (!isAuthed) {
    return -1;
  }

  // This data comes from our API
  const externalId = uuid();
  const startDate = new Date('2022-01-01T00:00:00.000Z');
  const endDate = new Date('2022-01-01T00:13:00.000Z');

  await HealthKit.saveWorkoutSample(
    HKWorkoutActivityType.highIntensityIntervalTraining,
    [
      {
        quantityType: HKQuantityTypeIdentifier.activeEnergyBurned,
        unit: 'kcal',
        quantity: 666,
      },
    ],
    startDate,
    {
      end: endDate,
      metadata: {
        HKExternalUUID: externalId,
      },
    },
  );
}

Unable to access VO2max data

Hi,

I'm trying to access vo2Max data on healthkit by requesting authorization to the HKQuantityTypeIdentifier.vo2Max quantity type, which is available in the library. I'm requesting the authorization along with other quantity type identifiers such as heart rate, body mass, etc.

When launching the app for the first time, the iOS screen to request the user to authorize those scopes is coming up normally, however I get to see all the scopes I'm requesting EXCEPT for vo2Max. If I then try to access the vo2Max data using the queryQuantitySamples method I am obviously getting an error as the user has not authorized access to it.

Has anybody else experience this issue and are there any known workarounds to get VO2Max to work?

Thanks

App Store rejection for having references to the Clinical Health Records API without using it.

Hi guys,

Thanks for your great work here, react native really needs a good healthkit lib. After I implemented this library into my app and submitted a release Apple rejected the app.
Screen Shot 2021-01-10 at 7 45 56 AM

I thought it was because of the example app in this repo (Clinical API permission in the plist) so I removed that from my code and resubmitted it to the app store but it was still rejected.
Screen Shot 2021-01-10 at 7 51 21 AM

I'm happy to contribute a PR but I'm not really sure how to go about fixing this (my native iOS knowledge is subpar to say the least) so I would need some direction.

Add a disconnect function

In case I want to revoke the connection and remove all existing permissions to apple health.

SCENARIO:
I requested reading permissions - Heartrate, and stepCount but only allowed permission for Heartrate.
I have no indication i didn't give permission to stepCount and (the requestAuthorization returns 1) and no way to reask for permissions (no disconnect)

HKAnchoredObjectQuery is not sortable

I just noticed that queryQuantitySamples, queryCategorySamples, and queryHeartbeatSeriesSamples still have the ascending parameter, but HKAnchoredObjectQuery has no way of sorting the samples. The result is also that the getMostRecentQuantitySample and getMostRecentCategorySample return the wrong samples (unexpected by the ascending parameter).

I guess the best way to deal with this is to have both query<type>Samples and query<type>SamplesWithAnchor methods as both have their uses?

Possible type mismatch on the ascending property

the types have ascending as a boolean but the Swift code has ascending as an NSNumber. When I try to pass true, it throws an error in some code that looks to be related to converting code in the RN bridge

sorry, I can't provide an exact error message. I was using the library for a hackathon project and the hackathon is now over and I've been moved to other work

my company may end up going forward with my hackathon project so it's possible I'll be back in that code at some point and I can help fix

Add Clinical Records support again - opt-in with the Expo Config Plugin

We have an old branch with health record implemented, but it was removed because it can be a blocker for app submissions if not actually using it.

I think it'd now be possible to lift this back in again - by extending the Expo Config Plugin to support opt-in to use this API. As part of this we need to make sure the Swift code referring to this is only included if the developer opts-in to use it.

The most natural way to include it would probably be to support setting the following info.plist entries in the config plugin, and only if these properties are set include the needed Swift code in the binary:

{
  "expo": {
    "plugins": [
      ["@kingstinct/react-native-healthkit", {
        "NSHealthClinicalHealthRecordsShareUsageDescription": "Your own custom usage description",
        "NSHealthRequiredReadAuthorizationTypeIdentifiers": ["allergyRecord"]
      }]
    ]
  }
}

HealthKit crashes with _validateForCreation

I'm saving sleep records using this library (among other data), but in the XCode organizer it shows up many users are having crashes which I cannot explain. I was not able to reproduce it myself. Can you please point me in the right direction here?

Let me know if you need more information. Thanks!

Date/Time:           2023-02-07 06:29:13.1467 -0600
Launch Time:         2023-02-06 21:42:01.6785 -0600
OS Version:          iPhone OS 15.6.1 (19G82)
Release Type:        User
Baseband Version:    4.04.02
Report Version:      104

Exception Type:  EXC_CRASH (SIGABRT)
Exception Codes: 0x0000000000000000, 0x0000000000000000
Exception Note:  EXC_CORPSE_NOTIFY
Triggered by Thread:  10

Last Exception Backtrace:
0   CoreFoundation                	0x1813e1288 __exceptionPreprocess + 220 (NSException.m:200)
1   libobjc.A.dylib               	0x19a111744 objc_exception_throw + 60 (objc-exception.mm:565)
2   CoreFoundation                	0x181438390 +[NSException raise:format:] + 112 (NSException.m:156)
3   HealthKit                     	0x18e2494f4 -[HKObject _validateForCreation] + 144 (HKObject.m:127)
4   HealthKit                     	0x18e249260 +[HKObject _newDataObjectWithMetadata:device:config:] + 276 (HKObject.m:112)
5   HealthKit                     	0x18e249108 +[HKSample _newSampleWithType:startDate:endDate:device:metadata:config:] + 204 (HKSample.m:42)
6   HealthKit                     	0x18e24aa9c +[HKCategorySample categorySampleWithType:value:startDate:endDate:device:metadata:] + 296 (HKCategorySample.m:42)
7   AuraTrack                     	0x10040cfbc @nonobjc HKCategorySample.__allocating_init(type:value:start:end:metadata:) + 48 (<compiler-generated>:0)
8   AuraTrack                     	0x10040cfbc ReactNativeHealthkit.saveCategorySample(typeIdentifier:value:start:end:metadata:resolve:reject:) + 664 (ReactNativeHealthkit.swift:573)
9   AuraTrack                     	0x10040d268 @objc ReactNativeHealthkit.saveCategorySample(typeIdentifier:value:start:end:metadata:resolve:reject:) + 368 (<compiler-generated>:0)
10  CoreFoundation                	0x181369b24 __invoking___ + 148 (:-1)
11  CoreFoundation                	0x181387610 -[NSInvocation invoke] + 468 (NSForwarding.m:3378)
12  CoreFoundation                	0x1813be5fc -[NSInvocation invokeWithTarget:] + 80 (NSForwarding.m:3475)
13  AuraTrack                     	0x1002c0728 -[RCTModuleMethod invokeWithBridge:module:arguments:] + 388 (RCTModuleMethod.mm:584)
14  AuraTrack                     	0x1002c28a0 facebook::react::invokeInner(RCTBridge*, RCTModuleData*, unsigned int, folly::dynamic const&, int, (anonymous namespace)::SchedulingContext) + 1190048 (RCTNativeModule.mm:183)
15  AuraTrack                     	0x1002c2528 invocation function for block in facebook::react::RCTNativeModule::invoke(unsigned int, folly::dynamic&&, int) + 1189160 (RCTNativeModule.mm:95)
16  libdispatch.dylib             	0x181046e6c _dispatch_call_block_and_release + 32 (init.c:1517)
17  libdispatch.dylib             	0x181048a30 _dispatch_client_callout + 20 (object.m:560)
18  libdispatch.dylib             	0x181050124 _dispatch_lane_serial_drain + 668 (inline_internal.h:2622)
19  libdispatch.dylib             	0x181050c80 _dispatch_lane_invoke + 392 (queue.c:3944)
20  libdispatch.dylib             	0x18105b500 _dispatch_workloop_worker_thread + 648 (queue.c:6732)
21  libsystem_pthread.dylib       	0x1f25a10bc _pthread_wqthread + 288 (pthread.c:2599)
22  libsystem_pthread.dylib       	0x1f25a0e5c start_wqthread + 8 (:-1)

HealthKit.requestAuthorization works once only

Hi,

I believe there is a bug when calling HealthKit.requestAuthorization([]) where the requestAuth modal only shows once when the app is running?
Steps to reproduce are as follows:

  1. Currently calling await HealthKit.authorizationStatusFor(HKCategoryTypeIdentifier.sleepAnalysis) to check if we have access to sleepAnalysis
  2. This is returning as 0 (false)
  3. We then check HealthKit.isHealthDataAvailable() which is true.
  4. We then render the request UI via await HealthKit.requestAuthorization([HKCategoryTypeIdentifier.sleepAnalysis])
  5. In the first instance, this shows.
  6. Image if use doesn't give permission and doesn't click Don't Allow. User kills app.
  7. User re-opens app and the above logic runs but the HealthKit.requestAuthorization doesn't render the UI

Any thoughts on working around this?

Way to get all the quantity for each record.

I was able to get the underwater depth and water temperature records of the Apple Watch Ultra through this library. But I couldn't find a way to get all the quantity for each record. how can i get them?

Not able to request write permissions

Hi, I'm trying to run useHealthkitAuthorization to be able to write data. I'm able to enable read permissions just fine, but I get an error when I try to request a write permission.

Screenshot 2024-02-22 at 6 47 27 PM

unrecognized selector sent to instance ... was thrown while invoking requestAuthorization on target ReactNativeHealthkit.

I'm running this on an Expo Dev Client.

Here are my plugins:

"plugins": [
      "expo-router",
      ["@kingstinct/react-native-healthkit", {
        "NSHealthShareUsageDescription": "my app uses Apple Health to read and write data.",
        "NSHealthUpdateUsageDescription": true,
        "background": true
      }]
    ],

The code I'm using looks like this:

export default function Home() {
  const [authorizationStatus, requestAuthorization] = useHealthkitAuthorization(
    [
      HKQuantityTypeIdentifier.bodyMass,
      HKQuantityTypeIdentifier.appleMoveTime,
      HKQuantityTypeIdentifier.appleStandTime,
      HKQuantityTypeIdentifier.heartRate,
      HKQuantityTypeIdentifier.height,
      HKQuantityTypeIdentifier.vo2Max,
      HKQuantityTypeIdentifier.basalEnergyBurned,
      HKQuantityTypeIdentifier.activeEnergyBurned,
      HKQuantityTypeIdentifier.appleExerciseTime,
      HKQuantityTypeIdentifier.restingHeartRate,
      HKQuantityTypeIdentifier.timeInDaylight,
      HKQuantityTypeIdentifier.stepCount,
      HKQuantityTypeIdentifier.headphoneAudioExposure,
      HKCategoryTypeIdentifier.sleepAnalysis,
      HKCategoryTypeIdentifier.sexualActivity,
      HKCategoryTypeIdentifier.mindfulSession,
      HKActivitySummaryTypeIdentifier,
      HKWorkoutTypeIdentifier,
      HKWorkoutRouteTypeIdentifier,
      HKCharacteristicTypeIdentifier.dateOfBirth,
      HKCharacteristicTypeIdentifier.biologicalSex,
      HKCharacteristicTypeIdentifier.activityMoveMode,
    ], [HKQuantityTypeIdentifier.bodyMass]
  );

Thanks for the help!

EAS builds fail after integrating via expo plugin

After adding the module to my Expo SDK48 project, EAS builds started to fail. Simulator builds worked as they are more relaxed with provisioning profiles.

The error that occurred was:
doesn't match the entitlements file's value for the com.apple.developer.healthkit.background-delivery entitlement

    "plugins": [
      "expo-build-properties",
      [
        "@kingstinct/react-native-healthkit",
        {
          "NSHealthShareUsageDescription": false,
          "NSHealthUpdateUsageDescription": "Write workout information to HealthKit",
          "background": false
        }
      ]
    ],

To fix the issue, and get EAS working again I had to change background to true

Just taking a guess here, but it could be related to:
https://github.com/Kingstinct/react-native-healthkit/blob/1585007848e0ffeed9ae4f767aac881082475dec/app.plugin.js#L43

Should it be wrapped in an if statement to avoid it being added at all?

Or perhaps the EAS build is removing com.apple.developer.healthkit.background-delivery when the value is false?

One more note, the App Store will reject your app if you have "NSHealthShareUsageDescription": false

Thanks for this incredible library!

Build failing on fastlane in EAS

I'm using the 7.0.0 version and getting a build error. Here are the relevant lines from the build logs:

The following build commands failed:
CompileSwift normal arm64 (in target 'kingstinct-react-native-healthkit' from project 'Pods')
CompileSwiftSources normal arm64 com.apple.xcode.tools.swift.compiler (in target 'kingstinct-react-native-healthkit' from project 'Pods')
(2 failures)
Exit status: 65

I can build a local simulator version and it works fine, but can't build for ad-hoc distribution.

Any idea why it would fail to compile?

authorizationStatusFor has incorrect return type

Problem

Official documentation shows it should return an enum that evaluates to numbers (DOCS):

  • notDetermined [0]
  • sharingDenied [1]
  • sharingAuthorized [2]

The function in the lib returns a boolean instead.

Use case

When I first grant access in the app, it shows the permission sheet because it results in notDetermined (0). After that, when testing and disabling/enabling access through settings -> health -> data for my app, it always results in 1.

Now:

  1. It is typed to return a boolean so why is it a number? I guess it's because JS converts somehow 1 and 2 to true and then converts that to a 1 but not sure.
  2. Nevertheless, sharingDenied (1) and sharingAuthorized (2) SHOULD differ so that's false info. But Apple says they don't show if the user denied access so it's weird it's there in the first place

Is there any way to solve this and differentiate between denied and authorized?

Permission error for getWorkoutRoutes()

I have noticed a strange issue with the Apple Health permissions for when trying to use the Native.getWorkoutRoutes(currentRun.uuid)

What happens is the user accepts permissions to access
"HKWorkoutTypeIdentifier" and "HKWorkoutRouteTypeIdentifier"

the getWorkoutRoutes works for a few days but then it just returns null after that for some users.
I have been able to reproduce this on my device as well and when I navigate to Apple Health app and go to the workouts section and scroll to the bottom and view the following permissions:
Data Sources and Access
Workout Route Data Sources & Access

They are both turned on for my app.

The strange thing is if I unselect the permission and turn it back on again then when I try and call getWorkoutRoutes again it begins to work again. Long term though this isn't really a viable solution to expect the user to turn off and turn on the permission each time so maybe theres an issue with how this function checks the permission as it is already enabled in Apple Health but only works when you toggle it off and on again.

I don't really have any logs to help debug this issue so apologies for that but hopefully that is enough to investigate.

Background mode not working on iOS simulator

Hi @robertherber !

Fist of all, thanks for this super cool library! I've seen since I updated the xcode version to the v15 that the background refresh has stopped working. Well, I first saw this issue in the useStatisticsForQuantity hook, but also in useSubscribeChange which makes sense as it is used in the first one! I'm using expo v50, in case it helps you to know it. Can it be that we are missing a commit like 7ecfd9b for Xcode15?

I attach here a chunk of code using the hook mentioned above

  const energy = useStatisticsForQuantity(
    HKQuantityTypeIdentifier.activeEnergyBurned,
    [HKStatisticsOptions.cumulativeSum],
    from,
    undefined,
    UnitOfEnergy.Kilocalories
  )

Thanks!!

Couple of questions

Hi,

Couple of questions:

Q1: I am trying to save blood pressure values (sys/dia) and I am using iOS device, I tried this but it seems the values are not persisted:

   Healthkit.saveQuantitySample(
            HKQuantityTypeIdentifier.bloodPressureSystolic,
            HKUnit.MillimetersOfMercury,
            120, {
            start: new Date()
        }
        );

   Healthkit.saveQuantitySample(
            HKQuantityTypeIdentifier.bloodPressureDiastolic,
            HKUnit.MillimetersOfMercury,
            70, {
            start: new Date()
        }
        );

Q2: I am trying to save the heart rate measurement and I am using this code, but it seems there is a problem in the "Count" unit, I think the code expects "count/min" but it seems the value is not mapped:

 Healthkit.saveQuantitySample(
            HKQuantityTypeIdentifier.heartRate,
            HKUnit.Count,
            68,
            {
                start: new Date(),
                 }
        );

Appreciate any help on this, thanks!

Cannot find module useHealthkitAuthorization?

Hello there!

I was trying to walk thru some of the examples on the README, but am getting errors when trying to use the hooks.

For example when I add this line to my project:

import { HKQuantityTypeIdentifier, useHealthkitAuthorization } from '@kingstinct/react-native-healthkit';

VSCode shows the following error:

'"@kingstinct/react-native-healthkit"' has no exported member named 'useHealthkitAuthorization'. Did you mean 'HealthkitReadAuthorization'?ts(2724)

Is there something else I have to configure here? I did notice in the example app we're doing it a bit differently:

import useHealthkitAuthorization from '@kingstinct/react-native-healthkit/hooks/useHealthkitAuthorization'

However this also resulted in the same issue on my side.

Feature: Apple HealthKit Sharing

In iOS 16 Apple has introduced a sharing option in which you can share data with friends/family. I was looking through the docs to see if it's an accessible from the API side but didn't see it. Do you know if it's around? I'd love to implement it if so.

Crash when using data

Hi! I'm having this problem and I don't know if it is a bug or I'm just not understanding how I should manage it.

I coded two hooks in the imperative way, one to request permissions and other to read the data that I have requested.

So I first request these permissions in the onboarding (first hook) and then consulting them when the user makes some update of his data like changing his username or nutritional goals (here is where the crash occurs).

I don't know if I'm doing wrong by use the hooks separately or what, thanks in advance for your cooperation.

Here's my code:

  • 1st hook
    `import { useEffect } from "react";
    import HealthKit, {
    HKQuantityTypeIdentifier,
    HKCategoryTypeIdentifier,
    HKCharacteristicTypeIdentifier,
    } from "@kingstinct/react-native-healthkit";
    import { logEventAsync } from "expo-analytics-amplitude";
    import { useNavigation } from "@react-navigation/native";

const useAppleRequest = (request: boolean) => {
const navigation = useNavigation();
const routes = navigation.getState()?.routes;
const prevRoute = routes[routes.length - 2];

useEffect(() => {
try {
if (request) {
const read = async () => {
const isAvailable = await HealthKit.isHealthDataAvailable();

      if (!isAvailable) {
        return;
      }

      const permissionStatus = await HealthKit.requestAuthorization([
        HKQuantityTypeIdentifier.stepCount,
        HKCategoryTypeIdentifier.sleepAnalysis,
        HKCharacteristicTypeIdentifier.biologicalSex,
        HKCharacteristicTypeIdentifier.bloodType,
        HKCharacteristicTypeIdentifier.dateOfBirth,
        HKQuantityTypeIdentifier.height,
        HKQuantityTypeIdentifier.bodyMass,
        HKCategoryTypeIdentifier.pregnancy,
        HKCategoryTypeIdentifier.diarrhea,
      ]);
      return permissionStatus;
    };

    read();
    // I could cut this lines but just in case I don't take it out
    if (prevRoute === "AllowApple") {
      navigation.navigate("Name");
    } else if (prevRoute === "Father") {
      navigation.goBack();
    }
  }
} catch (error) {
  logEventAsync(JSON.stringify(error));
}

}, [request]);
};

export default useAppleRequest;
`

  • 2nd hook
    `import { useEffect } from "react";

import HealthKit, {
HKQuantityTypeIdentifier,
HKCategoryTypeIdentifier,
HKUnits,
HKCharacteristicTypeIdentifier,
} from "@kingstinct/react-native-healthkit";
import { customAxios } from "../../App";
import { useAppSelector } from "./hooks";

const useAppleRead = (use: boolean) => {
const userId = useAppSelector((state) => state.user.id);

useEffect(() => {
if (use) {
const read = async () => {
const sleepAuth = await HealthKit.authorizationStatusFor(
HKCategoryTypeIdentifier.sleepAnalysis
);
const stepsAuth = await HealthKit.authorizationStatusFor(
HKQuantityTypeIdentifier.stepCount
);
const heightAuth = await HealthKit.authorizationStatusFor(
HKQuantityTypeIdentifier.height
);
const bodyMassAuth = await HealthKit.authorizationStatusFor(
HKQuantityTypeIdentifier.bodyMass
);
const pregnancyAuth = await HealthKit.authorizationStatusFor(
HKCategoryTypeIdentifier.pregnancy
);
const diarrheaAuth = await HealthKit.authorizationStatusFor(
HKCategoryTypeIdentifier.diarrhea
);
const genderAuth = await HealthKit.authorizationStatusFor(
HKCharacteristicTypeIdentifier.biologicalSex
);
const bloodTypeAuth = await HealthKit.authorizationStatusFor(
HKCharacteristicTypeIdentifier.bloodType
);
const ageAuth = await HealthKit.authorizationStatusFor(
HKCharacteristicTypeIdentifier.dateOfBirth
);

    const sleep = sleepAuth
      ? await HealthKit.getMostRecentCategorySample(
          HKCategoryTypeIdentifier.sleepAnalysis
        )
      : null;

    const steps = stepsAuth
      ? await HealthKit.getMostRecentQuantitySample(
          HKQuantityTypeIdentifier.stepCount,
          HKUnits.Count
        )
      : null;

    const height = heightAuth
      ? await HealthKit.getMostRecentQuantitySample(
          HKQuantityTypeIdentifier.height,
          HKUnits.Count
        )
      : null;

    const bodyMass = bodyMassAuth
      ? await HealthKit.getMostRecentQuantitySample(
          HKQuantityTypeIdentifier.bodyMass,
          HKUnits.Count
        )
      : null;

    const pregnancy = pregnancyAuth
      ? await HealthKit.getMostRecentCategorySample(
          HKCategoryTypeIdentifier.pregnancy
        )
      : null;

    const diarrhea = diarrheaAuth
      ? await HealthKit.getMostRecentCategorySample(
          HKCategoryTypeIdentifier.diarrhea
        )
      : null;

    const gender = genderAuth ? await HealthKit.getBiologicalSex() : null;
    const bloodType = bloodTypeAuth ? await HealthKit.getBloodType() : null;
    const age = ageAuth ? await HealthKit.getDateOfBirth() : null;

    await customAxios.post("MY_ROUTE", {
      steps,
      sleep,
      gender,
      bloodType,
      age,
      height,
      bodyMass,
      pregnancy,
      diarrhea,
      userId,
    });
  };
  read();
}

}, [use]);
};

export default useAppleRead;`

Clarification of Expo plugin usage

Hi there, we're attempting to use the Expo plugin, however we're seeing the following when running the app:

> [email protected] ios
> expo start --ios

Starting project at /Users/josh/Desktop/rn-health-test-app
PluginError: Package "@kingstinct/react-native-healthkit" does not contain a valid config plugin.
Learn more: https://docs.expo.dev/guides/config-plugins/#creating-a-plugin

Cannot use import statement outside a module
/Users/josh/Desktop/rn-health-test-app/node_modules/@kingstinct/react-native-healthkit/lib/module/index.js:1
import { Platform } from 'react-native';
^^^^^^

SyntaxError: Cannot use import statement outside a module
    at internalCompileFunction (node:internal/vm:73:18)
    at wrapSafe (node:internal/modules/cjs/loader:1176:20)
    at Module._compile (node:internal/modules/cjs/loader:1218:27)
    at Module._extensions..js (node:internal/modules/cjs/loader:1308:10)
    at Module.load (node:internal/modules/cjs/loader:1117:32)
    at Module._load (node:internal/modules/cjs/loader:958:12)
    at Module.require (node:internal/modules/cjs/loader:1141:19)
    at require (node:internal/modules/cjs/helpers:110:18)
    at requirePluginFile (/Users/josh/Desktop/rn-health-test-app/node_modules/@expo/config-plugins/build/utils/plugin-resolver.js:214:12)
    at resolveConfigPluginFunctionWithInfo (/Users/josh/Desktop/rn-health-test-app/node_modules/@expo/config-plugins/build/utils/plugin-resolver.js:155:14)

Is this what is meant by the comment in the repo "just keep in mind it will not work in Expo Go"? I note there's an open discussion in the Expo repo about supporting ESM for expo plugins: expo/expo#19359

Steps to reproduce

  1. Create a new expo app: npx create-expo-app rn-health-test-app
  2. In the repo install this package: npm i @kingstinct/react-native-healthkit
  3. Build and run: npm run ios

Observe error message.

requestAuthorization gives error on newly installed build

I'm figuring this is a problem not everybody is having, just me missing a step or so.
I've just installed the package, updated app.json with infoPlist and entitlements.
After opening the app in a dev-build in my physical phone the app crashes immediately when requesting for authorization.

import HealthKit, { HKQuantityTypeIdentifier } from "@kingstinct/react-native-healthkit";

const authResult = await HealthKit.requestAuthorization([
	Healthkit.useMostRecentQuantitySample(HKQuantityTypeIdentifier.walkingStepLength),
]);

console.log("authResult: ", authResult);

Image of error showing

Got same result when using the examples in readme of package

Add HKStatisticsCollectionQuery

HI @robertherber - I'm building an app where I'd like to show step counts by day for the last 30 days (or year etc.)

I think the right way to do this is using a HKStatisticsCollectionQuery where interval is something like day = 1. I haven't tested against a real user with lots of step data but I'm guessing calculating it via step samples will be too slow.

Curious if you agree with the above statement? If so, I'm happy to work on adding that API to the library.

Thanks again for putting this library together, very well designed and I've learned a lot about Swift, HealthKit and native module dev from it!

Authorization issues

  • When requesting authorization to read/write data types, the promise returns always a true value:
HealthKit.requestAuthorization(
          [
            HKQuantityTypeIdentifier.heartRate,
            HKQuantityTypeIdentifier.stepCount,
            HKQuantityTypeIdentifier.height,
          ]
        )
          .then(r => {
            console.log(r); // always returns true
          })
          .catch(e => {
            console.log('error: ', e);
          });

Can it return the list of allowed permissions instead?



  • Using a hook or imperative method to get if a specific permission (or list) is allowed or not after requesting authorization using the above doesnt seem to return the correct value:
HealthKit.getRequestStatusForAuthorization([
        HKQuantityTypeIdentifier.heartRate,
      ]).then(r => {
        console.log(r); //returns 2 => corresponding to `unnecessary`
      });

The issue persists even when I enable manually the permission in phone settings->health

The above method accepts an array of data type authorizations, but always return just 1 HKAuthorizationRequestStatus. Shouldnt it return a value for each of the data types in the request array?



HealthKit.authorizationStatusFor(HKQuantityTypeIdentifier.heartRate).then(
      permissionStatus => {
        console.log('Permission Status', 'appleMoveTime', permissionStatus);
        if (permissionStatus === 0) {
          HealthKit.requestAuthorization([
            HKQuantityTypeIdentifier.heartRate,
          ]).then(r => {
            console.log(r); //returns 1 =>  HKAuthorizationStatus = `sharindDenied`
          });
        }
      },
    );

The above method doesnt work as expected as well, returning a value of 1 after the permissions were requested for all, even for those that the user has accepted in the first step



I cannot request a specific authorization if it was asked before in a previous step using both imperative methods and hooks.

Is there another way to get the list of authorized data types or revoke and ask for the authorizations again?

Feature: exposing HKHeartbeatSeriesQuery for Heartbeat series data

First of all, thanks for the great and modern library in TypeScript and Swift! Fantastic work.

One thing that seems to be missing is the ability to obtaining raw heartbeat data by first querying HKHeartbeatSeriesSample, which can be done with a normal anchored query, and then obtaining the underlying heartbeat data of each sample with a HKHeartbeatSeriesQuery.

I went ahead and implemented it myself, exposing the queryHeartbeatSeriesSamples method that returns the serialized samples comprising the heartbeat data as described above.

However, before submitting any PR, I wanted to be sure that there is no other way to do it with the already existing implementation that I might have missed.

Cheers!

HealthKit.queryStatisticsForQuantity()'s Promise (and other functions too) stuck in Pending

HealthKit.queryStatisticsForQuantity()'s Promise (and other functions too) is stuck in the Pending state if there are no samples for the time frame specified. In other words, it never resolves. Meaning:

  • If you try to use .then() to capture a successful Promise, .catch() to capture a failed Promise or .finally() to capture either, you will never be able to have code in either of these functions execute.
  • If you use await before the function, then the code after the function will never execute because it is indefinitely waiting for the promise to resolve which never happens.

I think the correct way of doing things is if there are no samples for the specified period instead of having a non-resolved promised we should have either a failed Promise that we're able to capture with .catch() or a successful Promise with the response being undefined or something like that that we're able to capture with .then(). This is so that we're able to handle this situation ourselves in the code.

Exception when calling enableBackgroundDelivery

I tried to enable background delivery by calling:

HealthKit.enableBackgroundDelivery(HKQuantityTypeIdentifier.bodyMass, HKUpdateFrequency.immediate)

and got an exception:

enabledBackgroundDelivery:updateFrequency:withResolver:withRejector: is not a recognized Objective-C method

I investigated a little and found that the method signatures in ios/ReactNativeHealthkit.m and ios/ReactNativeHealthkit.swift don't match.

I'm putting together a pull request that fixes this and a few other methods.

Get the Swimming Stroke Style from workout metadata

I am using this package to query swimming data.

I got most of the information, but I couldn't get the Swimming Stroke Style.

My Code

export async function querySwimming(from?: Date, to?: Date) {
  if (!from || !to) {
    from = getFirstDayOfMonth()
    to = getLastDayOfMonth()
  }

  const workouts = (
    await HealthKit.queryWorkouts({
      energyUnit: UnitOfEnergy.Kilocalories,
      distanceUnit: UnitOfLength.Meter,
      from,
      to,
    })
  )
    .filter(v => v.workoutActivityType === HKWorkoutActivityType.swimming)
    .map(async v => {
      const [bpm] = await HealthKit.queryQuantitySamples(
        HKQuantityTypeIdentifier.heartRate,
        {
          from: new Date(v.startDate.getTime() - 1000),
          to: new Date(v.endDate.getTime() + 1000),
        },
      )
      Object.assign(v, {
        bpm: bpm,
      })
      return v as HKWorkout<UnitOfEnergy.Kilocalories, UnitOfLength.Meter> & {
        bpm: HKQuantitySample<HKQuantityTypeIdentifier.heartRate, 'count/min'>
      }
    })

  return Promise.all(workouts)
}

Since HKWorkoutSwimmingLocationType is present in the queried metadata, I think HKSwimmingStrokeStyle should also be present in the metadata.

But I can't find that data at all. Can I get some advice on this part?

The official reference address for the part I am looking for is
https://developer.apple.com/documentation/healthkit/hkswimmingstrokestyle

IMG_9987

IMG_0263

react native ios build crashes when calling Native.getWorkoutRoutes()

I want to try and get the GPS location data for a users run from healthkit so thought I would call this method:
import Native from '@kingstinct/react-native-healthkit/src/native-types'
const gpsMarkers = await Native.getWorkoutRoutes("XXXXXXX-6485-48A4-BA19-XXXXXXXXXXX") // uuid redacted
However right after that code runs the app just goes to the apple home page and there are no crash logs or anything indicating that it broke, it just exits the app. I would provide a minimal reproduction but there isn't really any helpful logs or anything to see.

I only make that call once I have gotten the permissions
`const [status, request] = useHealthkitAuthorization(readPermissions, [
HKQuantityTypeIdentifier.bodyMass,
...saveableCountTypes,
...saveableMassTypes,
...saveableWorkoutStuff,
]);

const [canAccessProtectedData, setAccessProtectedData] =
useState(false);

useEffect(() => {
if(Platform.OS=="ios") {
Healthkit.canAccessProtectedData()
.then(setAccessProtectedData)
.catch(() => setAccessProtectedData(false));
}
}, []);`

and I have called other methods like queryWorkouts fine which is where I got the uuid from in the first place.

import queryWorkouts from "@kingstinct/react-native-healthkit/src/utils/queryWorkouts";
const data = await queryWorkouts({ from: start, to: end, } );

I have tried wrapping the getWorkoutRoutes in a try catch block but that doesn't help either.

Background observing with this library

I am making use of activity mappings when the user has our react native app open but I'm wondering if it is possible to sync activities in the background (app in closed or background state) with this library.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.