diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Activity.m b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Activity.m index eeb0d91d414aad76a6394296a1a520d13fb5f0a3..378413ea44949a59a50da7f271b5b89ff098fbd0 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Activity.m +++ b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Activity.m @@ -35,8 +35,7 @@ callback(@[[NSNull null], results]); return; } else { - NSLog(@"error getting active energy burned samples: %@", error); - callback(@[RCTMakeError(@"error getting active energy burned samples", nil, nil)]); + callback(@[RCTJSErrorFromNSError(error)]); return; } }]; @@ -65,8 +64,7 @@ callback(@[[NSNull null], results]); return; } else { - NSLog(@"error getting basal energy burned samples: %@", error); - callback(@[RCTMakeError(@"error getting basal energy burned samples", nil, nil)]); + callback(@[RCTJSErrorFromNSError(error)]); return; } }]; diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Body.h b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Body.h index 086797426969dc6bd3c069fdbb3cccfe2eefffe8..51b677164f95425856626796166d976036fe723d 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Body.h +++ b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Body.h @@ -23,6 +23,11 @@ - (void)body_saveHeight:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; - (void)body_getLatestBodyFatPercentage:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; +- (void)body_getBodyFatPercentageSamples:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; +- (void)body_saveBodyFatPercentage:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; + - (void)body_getLatestLeanBodyMass:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; +- (void)body_getLeanBodyMassSamples:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; +- (void)body_saveLeanBodyMass:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; @end diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Body.m b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Body.m index 34fd328837a07105f0872461669cc942ab2c3531..e3ba841eea59b09b0cca78469151f6ebef42cb0d 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Body.m +++ b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Body.m @@ -24,8 +24,7 @@ predicate:nil completion:^(HKQuantity *mostRecentQuantity, NSDate *startDate, NSDate *endDate, NSError *error) { if (!mostRecentQuantity) { - NSLog(@"error getting latest weight: %@", error); - callback(@[RCTMakeError(@"error getting latest weight", error, nil)]); + callback(@[RCTJSErrorFromNSError(error)]); } else { // Determine the weight in the required unit. @@ -67,8 +66,7 @@ callback(@[[NSNull null], results]); return; } else { - NSLog(@"error getting weight samples: %@", error); - callback(@[RCTMakeError(@"error getting weight samples", nil, nil)]); + callback(@[RCTJSErrorFromNSError(error)]); return; } }]; @@ -87,8 +85,7 @@ [self.healthStore saveObject:weightSample withCompletion:^(BOOL success, NSError *error) { if (!success) { - NSLog(@"error saving the weight sample: %@", error); - callback(@[RCTMakeError(@"error saving the weight sample", error, nil)]); + callback(@[RCTJSErrorFromNSError(error)]); return; } callback(@[[NSNull null], @(weight)]); @@ -104,8 +101,7 @@ predicate:nil completion:^(HKQuantity *mostRecentQuantity, NSDate *startDate, NSDate *endDate, NSError *error) { if (!mostRecentQuantity) { - NSLog(@"error getting latest BMI: %@", error); - callback(@[RCTMakeError(@"error getting latest BMI", error, nil)]); + callback(@[RCTJSErrorFromNSError(error)]); } else { // Determine the bmi in the required unit. @@ -136,8 +132,7 @@ [self.healthStore saveObject:bmiSample withCompletion:^(BOOL success, NSError *error) { if (!success) { - NSLog(@"error saving BMI sample: %@.", error); - callback(@[RCTMakeError(@"error saving BMI sample", error, nil)]); + callback(@[RCTJSErrorFromNSError(error)]); return; } callback(@[[NSNull null], @(bmi)]); @@ -198,8 +193,7 @@ callback(@[[NSNull null], results]); return; } else { - NSLog(@"error getting height samples: %@", error); - callback(@[RCTMakeError(@"error getting height samples", error, nil)]); + callback(@[RCTJSErrorFromNSError(error)]); return; } }]; @@ -218,8 +212,7 @@ [self.healthStore saveObject:heightSample withCompletion:^(BOOL success, NSError *error) { if (!success) { - NSLog(@"error saving height sample: %@", error); - callback(@[RCTMakeError(@"error saving height sample", error, nil)]); + callback(@[RCTJSErrorFromNSError(error)]); return; } callback(@[[NSNull null], @(height)]); @@ -235,8 +228,7 @@ predicate:nil completion:^(HKQuantity *mostRecentQuantity, NSDate *startDate, NSDate *endDate, NSError *error) { if (!mostRecentQuantity) { - NSLog(@"error getting latest body fat percentage: %@", error); - callback(@[RCTMakeError(@"error getting latest body fat percentage", error, nil)]); + callback(@[RCTJSErrorFromNSError(error)]); } else { // Determine the weight in the required unit. @@ -257,6 +249,62 @@ } +- (void)body_getBodyFatPercentageSamples:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback +{ + HKQuantityType *bodyFatPercentType = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierBodyFatPercentage]; + + HKUnit *unit = [HKUnit percentUnit]; + NSUInteger limit = [RCTAppleHealthKit uintFromOptions:input key:@"limit" withDefault:HKObjectQueryNoLimit]; + BOOL ascending = [RCTAppleHealthKit boolFromOptions:input key:@"ascending" withDefault:false]; + NSDate *startDate = [RCTAppleHealthKit dateFromOptions:input key:@"startDate" withDefault:nil]; + NSDate *endDate = [RCTAppleHealthKit dateFromOptions:input key:@"endDate" withDefault:[NSDate date]]; + if(startDate == nil){ + callback(@[RCTMakeError(@"startDate is required in options", nil, nil)]); + return; + } + NSPredicate * predicate = [RCTAppleHealthKit predicateForSamplesBetweenDates:startDate endDate:endDate]; + + [self fetchQuantitySamplesOfType:bodyFatPercentType + unit:unit + predicate:predicate + ascending:ascending + limit:limit + completion:^(NSArray *results, NSError *error) { + if(results){ + callback(@[[NSNull null], results]); + return; + } else { + NSLog(@"error getting body fat percentage samples: %@", error); + callback(@[RCTMakeError(@"error getting body fat percentage samples", nil, nil)]); + return; + } + }]; +} + + +- (void)body_saveBodyFatPercentage:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback +{ + double percentage = [RCTAppleHealthKit doubleValueFromOptions:input]; + NSDate *sampleDate = [RCTAppleHealthKit dateFromOptionsDefaultNow:input]; + HKUnit *unit = [HKUnit percentUnit]; + + percentage = percentage / 100; + + HKQuantity *bodyFatPercentQuantity = [HKQuantity quantityWithUnit:unit doubleValue:percentage]; + HKQuantityType *bodyFatPercentType = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierBodyFatPercentage]; + HKQuantitySample *bodyFatPercentSample = [HKQuantitySample quantitySampleWithType:bodyFatPercentType quantity:bodyFatPercentQuantity startDate:sampleDate endDate:sampleDate]; + + [self.healthStore saveObject:bodyFatPercentSample withCompletion:^(BOOL success, NSError *error) { + if (!success) { + NSLog(@"error saving body fat percent sample: %@", error); + callback(@[RCTMakeError(@"error saving body fat percent sample", error, nil)]); + return; + } + callback(@[[NSNull null], @(percentage)]); + }]; +} + + - (void)body_getLatestLeanBodyMass:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback { HKQuantityType *leanBodyMassType = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierLeanBodyMass]; @@ -265,8 +313,7 @@ predicate:nil completion:^(HKQuantity *mostRecentQuantity, NSDate *startDate, NSDate *endDate, NSError *error) { if (!mostRecentQuantity) { - NSLog(@"error getting latest lean body mass: %@", error); - callback(@[RCTMakeError(@"error getting latest lean body mass", error, nil)]); + callback(@[RCTJSErrorFromNSError(error)]); } else { HKUnit *weightUnit = [HKUnit poundUnit]; @@ -283,4 +330,58 @@ }]; } + +- (void)body_getLeanBodyMassSamples:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback +{ + HKQuantityType *leanBodyMassType = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierLeanBodyMass]; + + HKUnit *unit = [RCTAppleHealthKit hkUnitFromOptions:input key:@"unit" withDefault:[HKUnit poundUnit]]; + NSUInteger limit = [RCTAppleHealthKit uintFromOptions:input key:@"limit" withDefault:HKObjectQueryNoLimit]; + BOOL ascending = [RCTAppleHealthKit boolFromOptions:input key:@"ascending" withDefault:false]; + NSDate *startDate = [RCTAppleHealthKit dateFromOptions:input key:@"startDate" withDefault:nil]; + NSDate *endDate = [RCTAppleHealthKit dateFromOptions:input key:@"endDate" withDefault:[NSDate date]]; + if(startDate == nil){ + callback(@[RCTMakeError(@"startDate is required in options", nil, nil)]); + return; + } + NSPredicate * predicate = [RCTAppleHealthKit predicateForSamplesBetweenDates:startDate endDate:endDate]; + + [self fetchQuantitySamplesOfType:leanBodyMassType + unit:unit + predicate:predicate + ascending:ascending + limit:limit + completion:^(NSArray *results, NSError *error) { + if(results){ + callback(@[[NSNull null], results]); + return; + } else { + NSLog(@"error getting lean body mass samples: %@", error); + callback(@[RCTMakeError(@"error getting lean body mass samples", nil, nil)]); + return; + } + }]; +} + + +- (void)body_saveLeanBodyMass:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback +{ + double mass = [RCTAppleHealthKit doubleValueFromOptions:input]; + NSDate *sampleDate = [RCTAppleHealthKit dateFromOptions:input key:@"startDate" withDefault:[NSDate date]]; + HKUnit *unit = [RCTAppleHealthKit hkUnitFromOptions:input key:@"unit" withDefault:[HKUnit poundUnit]]; + + HKQuantity *massQuantity = [HKQuantity quantityWithUnit:unit doubleValue:mass]; + HKQuantityType *massType = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierLeanBodyMass]; + HKQuantitySample *massSample = [HKQuantitySample quantitySampleWithType:massType quantity:massQuantity startDate:sampleDate endDate:sampleDate]; + + [self.healthStore saveObject:massSample withCompletion:^(BOOL success, NSError *error) { + if (!success) { + NSLog(@"error saving lean body mass sample: %@", error); + callback(@[RCTMakeError(@"error saving lean body mass sample", error, nil)]); + return; + } + callback(@[[NSNull null], @(mass)]); + }]; +} + @end diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Characteristic.m b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Characteristic.m index e030b856567d5cb131769f438c87492062382d07..e6266a9325a3d6113f83999c8be36002a5ec118c 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Characteristic.m +++ b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Characteristic.m @@ -34,8 +34,7 @@ } if(value == nil){ - NSLog(@"error getting biological sex: %@", error); - callback(@[RCTMakeError(@"error getting biological sex", error, nil)]); + callback(@[RCTJSErrorFromNSError(error)]); return; } @@ -52,8 +51,7 @@ NSDate *dob = [self.healthStore dateOfBirthWithError:&error]; if(error != nil){ - NSLog(@"error getting date of birth: %@", error); - callback(@[RCTMakeError(@"error getting date of birth", error, nil)]); + callback(@[RCTJSErrorFromNSError(error)]); return; } if(dob == nil) { diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Fitness.m b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Fitness.m index bd8261bb9726e919f7ddd2fd21cb53edddb03074..6ca17408675c52085c8f43862799f9d10c05ae87 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Fitness.m +++ b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Fitness.m @@ -34,8 +34,7 @@ day:date completion:^(double value, NSDate *startDate, NSDate *endDate, NSError *error) { if (!value) { - NSLog(@"could not fetch step count for day: %@", error); - callback(@[RCTMakeError(@"could not fetch step count for day", error, nil)]); + callback(@[RCTJSErrorFromNSError(error)]); return; } @@ -123,8 +122,7 @@ includeManuallyAdded:includeManuallyAdded completion:^(NSArray *arr, NSError *err){ if (err != nil) { - NSLog(@"error with fetchCumulativeSumStatisticsCollection: %@", err); - callback(@[RCTMakeError(@"error with fetchCumulativeSumStatisticsCollection", err, nil)]); + callback(@[RCTJSErrorFromNSError(err)]); return; } callback(@[[NSNull null], arr]); @@ -150,8 +148,7 @@ [self.healthStore saveObject:sample withCompletion:^(BOOL success, NSError *error) { if (!success) { - NSLog(@"An error occured saving the step count sample %@. The error was: %@.", sample, error); - callback(@[RCTMakeError(@"An error occured saving the step count sample", error, nil)]); + callback(@[RCTJSErrorFromNSError(error)]); return; } callback(@[[NSNull null], @(value)]); @@ -173,9 +170,7 @@ NSError *error) { if (error) { - // Perform Proper Error Handling Here... - NSLog(@"*** An error occured while setting up the stepCount observer. %@ ***", error.localizedDescription); - callback(@[RCTMakeError(@"An error occured while setting up the stepCount observer", error, nil)]); + callback(@[RCTJSErrorFromNSError(error)]); return; } @@ -200,8 +195,7 @@ [self fetchSumOfSamplesOnDayForType:quantityType unit:unit day:date completion:^(double distance, NSDate *startDate, NSDate *endDate, NSError *error) { if (!distance) { - NSLog(@"ERROR getting DistanceWalkingRunning: %@", error); - callback(@[RCTMakeError(@"ERROR getting DistanceWalkingRunning", error, nil)]); + callback(@[RCTJSErrorFromNSError(error)]); return; } @@ -276,8 +270,7 @@ includeManuallyAdded:includeManuallyAdded completion:^(NSArray *arr, NSError *err){ if (err != nil) { - NSLog(@"error with fetchCumulativeSumStatisticsCollection: %@", err); - callback(@[RCTMakeError(@"error with fetchCumulativeSumStatisticsCollection", err, nil)]); + callback(@[RCTJSErrorFromNSError(err)]); return; } callback(@[[NSNull null], arr]); @@ -293,8 +286,7 @@ [self fetchSumOfSamplesOnDayForType:quantityType unit:unit day:date completion:^(double distance, NSDate *startDate, NSDate *endDate, NSError *error) { if (!distance) { - NSLog(@"ERROR getting DistanceCycling: %@", error); - callback(@[RCTMakeError(@"ERROR getting DistanceCycling", error, nil)]); + callback(@[RCTJSErrorFromNSError(error)]); return; } @@ -334,8 +326,7 @@ includeManuallyAdded:includeManuallyAdded completion:^(NSArray *arr, NSError *err){ if (err != nil) { - NSLog(@"error with fetchCumulativeSumStatisticsCollection: %@", err); - callback(@[RCTMakeError(@"error with fetchCumulativeSumStatisticsCollection", err, nil)]); + callback(@[RCTJSErrorFromNSError(err)]); return; } callback(@[[NSNull null], arr]); @@ -351,8 +342,7 @@ [self fetchSumOfSamplesOnDayForType:quantityType unit:unit day:date completion:^(double count, NSDate *startDate, NSDate *endDate, NSError *error) { if (!count) { - NSLog(@"ERROR getting FlightsClimbed: %@", error); - callback(@[RCTMakeError(@"ERROR getting FlightsClimbed", error, nil), @(count)]); + callback(@[RCTJSErrorFromNSError(error)]); return; } @@ -388,8 +378,7 @@ limit:limit completion:^(NSArray *arr, NSError *err){ if (err != nil) { - NSLog(@"error with fetchCumulativeSumStatisticsCollection: %@", err); - callback(@[RCTMakeError(@"error with fetchCumulativeSumStatisticsCollection", err, nil)]); + callback(@[RCTJSErrorFromNSError(err)]); return; } callback(@[[NSNull null], arr]); diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Mindfulness.m b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Mindfulness.m index b14ef8137a7bc7618f8de087aaf906137d3a0a46..1dc6dca911494dd8dbed44a365ae6e14617bcfc7 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Mindfulness.m +++ b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Mindfulness.m @@ -29,8 +29,7 @@ [self.healthStore saveObject:sample withCompletion:^(BOOL success, NSError *error) { if (!success) { - NSLog(@"An error occured saving the mindful session sample %@. The error was: %@.", sample, error); - callback(@[RCTMakeError(@"An error occured saving the mindful session sample", error, nil)]); + callback(@[RCTJSErrorFromNSError(error)]); return; } callback(@[[NSNull null], @(value)]); diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Results.m b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Results.m index fd5d0345ceb2278a59782f10b15913de0f3dc434..a1c1cdea6e96786add9f59ca7e190f3e6a18a7b5 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Results.m +++ b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Results.m @@ -32,8 +32,7 @@ callback(@[[NSNull null], results]); return; } else { - NSLog(@"error getting blood glucose samples: %@", error); - callback(@[RCTMakeError(@"error getting blood glucose samples", nil, nil)]); + callback(@[RCTJSErrorFromNSError(error)]); return; } }]; diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Sleep.m b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Sleep.m index faba4ed1739c4367fddc4158937ac85ad7a2c1ff..0894624e47c329825d8c3474df11ae933d4e0406 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Sleep.m +++ b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Sleep.m @@ -36,8 +36,7 @@ callback(@[[NSNull null], results]); return; } else { - NSLog(@"error getting sleep samples: %@", error); - callback(@[RCTMakeError(@"error getting sleep samples", nil, nil)]); + callback(@[RCTJSErrorFromNSError(error)]); return; } }]; diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Vitals.m b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Vitals.m index 74c53cb74cdab407ada69d6ca2e4bc4326fc31db..698a1b25b825d010a3017a2fafd3429dd1839137 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Vitals.m +++ b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Vitals.m @@ -33,8 +33,7 @@ callback(@[[NSNull null], results]); return; } else { - NSLog(@"error getting heart rate samples: %@", error); - callback(@[RCTMakeError(@"error getting heart rate samples", nil, nil)]); + callback(@[RCTJSErrorFromNSError(error)]); return; } }]; diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+TypesAndPermissions.h b/RCTAppleHealthKit/RCTAppleHealthKit+TypesAndPermissions.h index d69b7e956a6376bd2fea3d26128bdfc0ed97f908..c6668c69654043f6727b54f1df1c457d82e85caf 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit+TypesAndPermissions.h +++ b/RCTAppleHealthKit/RCTAppleHealthKit+TypesAndPermissions.h @@ -15,5 +15,7 @@ - (NSDictionary *)writePermsDict; - (NSSet *)getReadPermsFromOptions:(NSArray *)options; - (NSSet *)getWritePermsFromOptions:(NSArray *)options; +- (HKObjectType *)getWritePermFromString:(NSString *)string; +- (NSString *)getAuthorizationStatusString:(HKAuthorizationStatus)status; @end diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+TypesAndPermissions.m b/RCTAppleHealthKit/RCTAppleHealthKit+TypesAndPermissions.m index 8d0c930173529ed23da75e4ef4627fe38540f13d..a54f03fb80a47d3030312b714e74f225ecefdcd1 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit+TypesAndPermissions.m +++ b/RCTAppleHealthKit/RCTAppleHealthKit+TypesAndPermissions.m @@ -153,4 +153,18 @@ return writePermSet; } +- (HKObjectType *)getWritePermFromString:(NSString *)writePerm { + return [[self writePermsDict] objectForKey:writePerm]; +} +- (NSString *)getAuthorizationStatusString:(HKAuthorizationStatus)status { + switch (status) { + case HKAuthorizationStatusNotDetermined: + return @"NotDetermined"; + case HKAuthorizationStatusSharingDenied: + return @"SharingDenied"; + case HKAuthorizationStatusSharingAuthorized: + return @"SharingAuthorized"; + } +} + @end diff --git a/RCTAppleHealthKit/RCTAppleHealthKit.m b/RCTAppleHealthKit/RCTAppleHealthKit.m index df459c43b1630cc391bf37f5c91e3d8178f3b635..e2b13587d65be4f5e3c593811f52ed70e3c70a8c 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit.m +++ b/RCTAppleHealthKit/RCTAppleHealthKit.m @@ -99,11 +99,31 @@ RCT_EXPORT_METHOD(getLatestBodyFatPercentage:(NSDictionary *)input callback:(RCT [self body_getLatestBodyFatPercentage:input callback:callback]; } +RCT_EXPORT_METHOD(getBodyFatPercentageSamples:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback) +{ + [self body_getBodyFatPercentageSamples:input callback:callback]; +} + +RCT_EXPORT_METHOD(saveBodyFatPercentage:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback) +{ + [self body_saveBodyFatPercentage:input callback:callback]; +} + RCT_EXPORT_METHOD(getLatestLeanBodyMass:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback) { [self body_getLatestLeanBodyMass:input callback:callback]; } +RCT_EXPORT_METHOD(getLeanBodyMassSamples:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback) +{ + [self body_getLeanBodyMassSamples:input callback:callback]; +} + +RCT_EXPORT_METHOD(saveLeanBodyMass:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback) +{ + [self body_saveLeanBodyMass:input callback:callback]; +} + RCT_EXPORT_METHOD(getStepCount:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback) { [self fitness_getStepCountOnDay:input callback:callback]; @@ -271,9 +291,7 @@ RCT_EXPORT_METHOD(saveMindfulSession:(NSDictionary *)input callback:(RCTResponse [self.healthStore requestAuthorizationToShareTypes:writeDataTypes readTypes:readDataTypes completion:^(BOOL success, NSError *error) { if (!success) { - NSString *errMsg = [NSString stringWithFormat:@"Error with HealthKit authorization: %@", error]; - NSLog(errMsg); - callback(@[RCTMakeError(errMsg, nil, nil)]); + callback(@[RCTJSErrorFromNSError(error)]); return; } else { dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ @@ -286,6 +304,28 @@ RCT_EXPORT_METHOD(saveMindfulSession:(NSDictionary *)input callback:(RCTResponse } } +RCT_EXPORT_METHOD(authorizationStatusForType:(NSString *)type + resolver:(RCTPromiseResolveBlock)resolve + rejecter:(RCTPromiseRejectBlock)reject +{ + if (self.healthStore == nil) { + self.healthStore = [[HKHealthStore alloc] init]; + } + + if ([HKHealthStore isHealthDataAvailable]) { + HKObjectType *objectType = [self getWritePermFromString:type]; + if (objectType == nil) { + reject(@"unknown write permission", nil, nil); + return; + } + + NSString *status = [self getAuthorizationStatusString:[self.healthStore authorizationStatusForType:objectType]]; + resolve(status); + } else { + reject(@"HealthKit data is not available", nil, nil); + } +}) + - (void)getModuleInfo:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback { NSDictionary *info = @{ diff --git a/README.md b/README.md index c0df2ee1f56c9506f6c3c7e100d1835ab047672b..6ad3ead0b94a3ba6b0b69298479f6a2b39a8495c 100644 --- a/README.md +++ b/README.md @@ -106,6 +106,7 @@ AppleHealthKit.initHealthKit(options: Object, (err: string, results: Object) => * Base Methods * [isAvailable](/docs/isAvailable().md) * [initHealthKit](/docs/initHealthKit().md) + * [authorizationStatusForType](/docs/authorizationStatusForType().md) * Realtime Methods * [initStepCountObserver](/docs/initStepCountObserver().md) * [setObserver](/docs/setObserver().md) @@ -129,8 +130,10 @@ AppleHealthKit.initHealthKit(options: Object, (err: string, results: Object) => * [getHeightSamples](/docs/getHeightSamples().md) * [getLatestBmi](/docs/getLatestBmi().md) * [getLatestBodyFatPercentage](/docs/getLatestBodyFatPercentage().md) + * [getBodyFatPercentageSamples](/docs/getBodyFatPercentageSamples().md) * [getLatestHeight](/docs/getLatestHeight().md) * [getLatestLeanBodyMass](/docs/getLatestLeanBodyMass().md) + * [getLeanBodyMassSamples](/docs/getLeanBodyMassSamples().md) * [getLatestWeight](/docs/getLatestWeight().md) * [getRespiratoryRateSamples](/docs/getRespiratoryRateSamples().md) * [getSleepSamples](/docs/getSleepSamples().md) @@ -143,6 +146,8 @@ AppleHealthKit.initHealthKit(options: Object, (err: string, results: Object) => * [saveMindfulSession](/docs/saveMindfulSession().md) * [saveWeight](/docs/saveWeight().md) * [saveSteps](/docs/saveSteps().md) + * [saveBodyFatPercentage](/docs/saveBodyFatPercentage().md) + * [saveLeanBodyMass](/docs/saveLeanBodyMass().md) * [References](#references) ## Supported Apple Permissions @@ -172,6 +177,7 @@ The available Healthkit permissions to use with `initHealthKit` | StepCount | [HKQuantityTypeIdentifierStepCount](https://developer.apple.com/reference/Healthkit/hkquantitytypeidentifierstepcount?language=objc) | ✓ | ✓ | | Steps | [HKQuantityTypeIdentifierSteps](https://developer.apple.com/reference/Healthkit/hkquantitytypeidentifiersteps?language=objc) | ✓ | ✓ | | Weight | [HKQuantityTypeIdentifierBodyMass](https://developer.apple.com/reference/Healthkit/hkquantitytypeidentifierbodymass?language=objc) | ✓ | ✓ | +| BodyFatPercentage | [HKQuantityTypeIdentifierBodyFatPercentage](https://developer.apple.com/reference/Healthkit/hkquantitytypeidentifierbodyfatpercentage?language=objc) | ✓ | ✓ | These permissions are exported as constants of the `rn-apple-healthkit` module. diff --git a/docs/authorizationStatusForType().md b/docs/authorizationStatusForType().md new file mode 100644 index 0000000000000000000000000000000000000000..8687b89b926df11f8348d2f46bbd5d2587454d30 --- /dev/null +++ b/docs/authorizationStatusForType().md @@ -0,0 +1,16 @@ +Check the authorization status for sharing (writing) the specified data type. + +Status will be one of `"NotDetermined"`, `"SharingDenied"`, `"SharingAuthorized"`. + +```javascript +try { +const status = await AppleHealthKit.authorizationStatusForType("StepCount") +if (status) { + console.log("status is", status) +} +} catch (error) { + console.warn(error) +} +``` + +There is no way to check authorization status for read permission, [see this](https://developer.apple.com/documentation/healthkit/hkhealthstore/1614154-authorizationstatusfortype?language=objc). diff --git a/docs/getBodyFatPercentageSamples().md b/docs/getBodyFatPercentageSamples().md new file mode 100644 index 0000000000000000000000000000000000000000..8e3e872296efed719e906f9938445d2f0c0de77d --- /dev/null +++ b/docs/getBodyFatPercentageSamples().md @@ -0,0 +1,27 @@ +Query for body fat percentage samples. the options object is used to setup a query to retrieve relevant samples. + +```javascript +let options = { + startDate: (new Date(2016,4,27)).toISOString(), // required + endDate: (new Date()).toISOString(), // optional; default now + ascending: false, // optional; default false + limit:10, // optional; default no limit +}; +``` + +```javascript +AppleHealthKit.getBodyFatPercentageSamples(options, (err: Object, results: Array) => { + if (err) { + return; + } + console.log(results) +}); +``` + +```javascript +[ + { value: 16.5, startDate: '2016-07-09T00:00:00.000-0400', endDate: '2016-07-10T00:00:00.000-0400' }, + { value: 16.1, startDate: '2016-07-08T00:00:00.000-0400', endDate: '2016-07-09T00:00:00.000-0400' }, + { value: 15.9, startDate: '2016-07-07T00:00:00.000-0400', endDate: '2016-07-08T00:00:00.000-0400' }, +] +``` diff --git a/docs/getLeanBodyMassSamples().md b/docs/getLeanBodyMassSamples().md new file mode 100644 index 0000000000000000000000000000000000000000..93a0af87b066ad9222e84b35b8bcca365a9d5b04 --- /dev/null +++ b/docs/getLeanBodyMassSamples().md @@ -0,0 +1,28 @@ +Query for lean body mass samples. the options object is used to setup a query to retrieve relevant samples. + +```javascript +let options = { + unit: 'pound', // optional; default 'pound' + startDate: (new Date(2016,4,27)).toISOString(), // required + endDate: (new Date()).toISOString(), // optional; default now + ascending: false, // optional; default false + limit:10, // optional; default no limit +}; +``` + +```javascript +AppleHealthKit.getLeanBodyMassSamples(options, (err: Object, results: Array) => { + if (err) { + return; + } + console.log(results) +}); +``` + +```javascript +[ + { value: 160, startDate: '2016-07-09T00:00:00.000-0400', endDate: '2016-07-10T00:00:00.000-0400' }, + { value: 161, startDate: '2016-07-08T00:00:00.000-0400', endDate: '2016-07-09T00:00:00.000-0400' }, + { value: 165, startDate: '2016-07-07T00:00:00.000-0400', endDate: '2016-07-08T00:00:00.000-0400' }, +] +``` diff --git a/docs/saveBodyFatPercentage().md b/docs/saveBodyFatPercentage().md new file mode 100644 index 0000000000000000000000000000000000000000..e5f2bc39e36855e1c3a5e6673842f6cc2e5cbb30 --- /dev/null +++ b/docs/saveBodyFatPercentage().md @@ -0,0 +1,17 @@ +save a percentage body fat value to Healthkit + +`saveBodyFatPercentage` accepts an options object containing a percent value: +```javascript +let options = { + value: 16.7 // 16.7% +} +``` + +```javascript +AppleHealthKit.saveBodyFatPercentage(options: Object, (err: Object, results: Object) => { + if (err) { + return; + } + // body fat percentage successfully saved +}); +``` diff --git a/docs/saveLeanBodyMass().md b/docs/saveLeanBodyMass().md new file mode 100644 index 0000000000000000000000000000000000000000..44b7a317f29c0d905c21a6dfd2e949ee43e15c3d --- /dev/null +++ b/docs/saveLeanBodyMass().md @@ -0,0 +1,18 @@ +save a numeric lean body mass value to Healthkit + +`saveLeanBodyMass` accepts an options object containing a numeric weight value: +```javascript +let options = { + value: 155.6 // lbs +} +``` + +```javascript +AppleHealthKit.saveLeanBodyMass(options: Object, (err: Object, results: Object) => { + if (err) { + console.log("error saving lean body mass to Healthkit: ", err); + return; + } + // Done +}); +```