#import #import @interface HealthKitBridge : NSObject @end @implementation HealthKitBridge { HKHealthStore *_store; } RCT_EXPORT_MODULE(); - (instancetype)init { self = [super init]; if (self) { _store = [[HKHealthStore alloc] init]; } return self; } + (BOOL)requiresMainQueueSetup { return NO; } RCT_EXPORT_METHOD(requestAuthorization:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) { NSSet *readTypes = [NSSet setWithArray:@[ [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierHeartRate], [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierStepCount], [HKObjectType categoryTypeForIdentifier:HKCategoryTypeIdentifierSleepAnalysis], ]]; [_store requestAuthorizationToShareTypes:nil readTypes:readTypes completion:^(BOOL success, NSError *error) { if (success) resolve(@YES); else reject(@"healthkit", error.localizedDescription, error); }]; } RCT_EXPORT_METHOD(getLatestHeartRate:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) { HKQuantityType *type = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierHeartRate]; NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:HKSampleSortIdentifierEndDate ascending:NO]; HKSampleQuery *query = [[HKSampleQuery alloc] initWithSampleType:type predicate:nil limit:1 sortDescriptors:@[sort] resultsHandler:^(HKSampleQuery *q, NSArray *results, NSError *error) { if (error) { reject(@"healthkit", error.localizedDescription, error); return; } if (results.count == 0) { resolve(@{}); return; } HKQuantitySample *sample = results[0]; double bpm = [sample.quantity doubleValueForUnit:[HKUnit unitFromString:@"count/min"]]; resolve(@{@"bpm": @(bpm), @"time": @([sample.endDate timeIntervalSince1970] * 1000)}); }]; [_store executeQuery:query]; } RCT_EXPORT_METHOD(getTodaySteps:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) { HKQuantityType *type = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierStepCount]; NSCalendar *cal = [NSCalendar currentCalendar]; NSDate *start = [cal startOfDayForDate:[NSDate date]]; NSDate *end = [NSDate date]; NSPredicate *pred = [HKQuery predicateForSamplesWithStartDate:start endDate:end options:HKQueryOptionStrictStartDate]; HKStatisticsQuery *query = [[HKStatisticsQuery alloc] initWithQuantityType:type quantitySamplePredicate:pred options:HKStatisticsOptionCumulativeSum completionHandler:^(HKStatisticsQuery *q, HKStatistics *result, NSError *error) { if (error) { reject(@"healthkit", error.localizedDescription, error); return; } double steps = [result.sumQuantity doubleValueForUnit:[HKUnit countUnit]]; resolve(@{@"steps": @(steps)}); }]; [_store executeQuery:query]; } RCT_EXPORT_METHOD(getLastSleep:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) { HKCategoryType *type = [HKObjectType categoryTypeForIdentifier:HKCategoryTypeIdentifierSleepAnalysis]; NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:HKSampleSortIdentifierEndDate ascending:NO]; HKSampleQuery *query = [[HKSampleQuery alloc] initWithSampleType:type predicate:nil limit:1 sortDescriptors:@[sort] resultsHandler:^(HKSampleQuery *q, NSArray *results, NSError *error) { if (error) { reject(@"healthkit", error.localizedDescription, error); return; } if (results.count == 0) { resolve(@{}); return; } HKCategorySample *sample = results[0]; double hours = [sample.endDate timeIntervalSinceDate:sample.startDate] / 3600.0; resolve(@{@"hours": @(hours), @"start": @([sample.startDate timeIntervalSince1970] * 1000), @"end": @([sample.endDate timeIntervalSince1970] * 1000)}); }]; [_store executeQuery:query]; } @end