From dda3ea9553d694b527afa56670eda5309d33a053 Mon Sep 17 00:00:00 2001 From: EEvgeniiF Date: Tue, 30 Jan 2018 23:55:40 +0100 Subject: [PATCH 01/24] isTracked step samples --- .../RCTAppleHealthKit+Methods_Body.h | 3 +- .../RCTAppleHealthKit+Methods_Body.m | 3 +- ...RCTAppleHealthKit+Methods_Characteristic.h | 3 +- ...RCTAppleHealthKit+Methods_Characteristic.m | 3 +- .../RCTAppleHealthKit+Methods_Fitness.h | 4 +- .../RCTAppleHealthKit+Methods_Fitness.m | 52 +++++++++++++++- .../RCTAppleHealthKit+Methods_Sleep.h | 3 +- .../RCTAppleHealthKit+Methods_Sleep.m | 3 +- RCTAppleHealthKit/RCTAppleHealthKit+Queries.h | 11 +++- RCTAppleHealthKit/RCTAppleHealthKit+Queries.m | 62 ++++++++++++++++++- .../RCTAppleHealthKit+TypesAndPermissions.h | 3 +- .../RCTAppleHealthKit+TypesAndPermissions.m | 3 +- RCTAppleHealthKit/RCTAppleHealthKit+Utils.h | 3 +- RCTAppleHealthKit/RCTAppleHealthKit+Utils.m | 3 +- RCTAppleHealthKit/RCTAppleHealthKit.h | 3 +- RCTAppleHealthKit/RCTAppleHealthKit.m | 8 ++- 16 files changed, 137 insertions(+), 33 deletions(-) diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Body.h b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Body.h index 08679742..472829ca 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Body.h +++ b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Body.h @@ -3,8 +3,7 @@ // RCTAppleHealthKit // // Created by Greg Wilson on 2016-06-26. -// This source code is licensed under the MIT-style license found in the -// LICENSE file in the root directory of this source tree. +// Copyright © 2016 Greg Wilson. All rights reserved. // #import "RCTAppleHealthKit.h" diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Body.m b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Body.m index 8fec38d4..f29f7f84 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Body.m +++ b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Body.m @@ -3,8 +3,7 @@ // RCTAppleHealthKit // // Created by Greg Wilson on 2016-06-26. -// This source code is licensed under the MIT-style license found in the -// LICENSE file in the root directory of this source tree. +// Copyright © 2016 Greg Wilson. All rights reserved. // #import "RCTAppleHealthKit+Methods_Body.h" diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Characteristic.h b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Characteristic.h index 0909ebef..6c0adcce 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Characteristic.h +++ b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Characteristic.h @@ -3,8 +3,7 @@ // RCTAppleHealthKit // // Created by Greg Wilson on 2016-06-29. -// This source code is licensed under the MIT-style license found in the -// LICENSE file in the root directory of this source tree. +// Copyright © 2016 Greg Wilson. All rights reserved. // #import "RCTAppleHealthKit.h" diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Characteristic.m b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Characteristic.m index e030b856..b7fb4f42 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Characteristic.m +++ b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Characteristic.m @@ -3,8 +3,7 @@ // RCTAppleHealthKit // // Created by Greg Wilson on 2016-06-29. -// This source code is licensed under the MIT-style license found in the -// LICENSE file in the root directory of this source tree. +// Copyright © 2016 Greg Wilson. All rights reserved. // #import "RCTAppleHealthKit+Methods_Characteristic.h" diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Fitness.h b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Fitness.h index 4172e3e8..5a38559f 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Fitness.h +++ b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Fitness.h @@ -3,8 +3,7 @@ // RCTAppleHealthKit // // Created by Greg Wilson on 2016-06-26. -// This source code is licensed under the MIT-style license found in the -// LICENSE file in the root directory of this source tree. +// Copyright © 2016 Greg Wilson. All rights reserved. // #import "RCTAppleHealthKit.h" @@ -12,6 +11,7 @@ @interface RCTAppleHealthKit (Methods_Fitness) - (void)fitness_getStepCountOnDay:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; +- (void)fitness_getStepCountSamples:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; - (void)fitness_getDailyStepSamples:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; - (void)fitness_saveSteps:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; - (void)fitness_initializeStepEventObserver:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Fitness.m b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Fitness.m index 10ef07b2..9decba15 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Fitness.m +++ b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Fitness.m @@ -3,8 +3,7 @@ // RCTAppleHealthKit // // Created by Greg Wilson on 2016-06-26. -// This source code is licensed under the MIT-style license found in the -// LICENSE file in the root directory of this source tree. +// Copyright © 2016 Greg Wilson. All rights reserved. // #import "RCTAppleHealthKit+Methods_Fitness.h" @@ -49,6 +48,55 @@ - (void)fitness_getStepCountOnDay:(NSDictionary *)input callback:(RCTResponseSen }]; } +- (void)fitness_getStepCountSamples:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback +{ + HKUnit *unit = [RCTAppleHealthKit hkUnitFromOptions:input key:@"unit" withDefault:[HKUnit countUnit]]; + NSUInteger limit = [RCTAppleHealthKit uintFromOptions:input key:@"limit" withDefault:HKObjectQueryNoLimit]; + BOOL ascending = [RCTAppleHealthKit boolFromOptions:input key:@"ascending" withDefault:false]; + BOOL isTracked = [RCTAppleHealthKit boolFromOptions:input key:@"isTracked" withDefault:true]; + 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; + } + NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; + [formatter setDateFormat:@"YYYY-MM-dd-hh-mm-ss"]; + NSLog(@"samples interval: %@ %@",[formatter stringFromDate:startDate], [formatter stringFromDate:endDate]); + + // no isTracked + NSArray *subPredicates = [[NSArray alloc] init]; + NSMutableArray *subPredicatesAux = [[NSMutableArray alloc] init]; + NSPredicate *predicateDate = [HKQuery predicateForSamplesWithStartDate:startDate endDate:endDate options:HKQueryOptionStrictStartDate]; + NSPredicate *predicateType = isTracked ? [NSPredicate predicateWithFormat:@"metadata.%K != YES", HKMetadataKeyWasUserEntered] : [NSPredicate predicateWithFormat:@"metadata.%K == YES", HKMetadataKeyWasUserEntered]; + [subPredicatesAux addObject:predicateDate]; + [subPredicatesAux addObject:predicateType]; + subPredicates = [subPredicatesAux copy]; + NSPredicate *predicate = [NSCompoundPredicate andPredicateWithSubpredicates:subPredicates]; + + HKQuantityType *stepCountType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierStepCount]; + + NSString * paramName = @"isTracked"; + + [self fetchQuantitySamplesOfType:stepCountType + unit:unit + predicate:predicate + ascending:ascending + limit:limit + additionalParamName:paramName + additionalParam:isTracked + completion:^(NSArray *results, NSError *error) { + if(results){ + callback(@[[NSNull null], results]); + return; + } else { + NSLog(@"error getting active energy burned samples: %@", error); + callback(@[RCTMakeError(@"error getting active energy burned samples", nil, nil)]); + return; + } + }]; +} + - (void)fitness_getDailyStepSamples:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback { diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Sleep.h b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Sleep.h index cb71012d..3afd6d9f 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Sleep.h +++ b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Sleep.h @@ -3,8 +3,7 @@ // RCTAppleHealthKit // // Created by Greg Wilson on 2016-11-06. -// This source code is licensed under the MIT-style license found in the -// LICENSE file in the root directory of this source tree. +// Copyright © 2016 Greg Wilson. All rights reserved. // #import "RCTAppleHealthKit.h" diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Sleep.m b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Sleep.m index faba4ed1..4b1898f8 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Sleep.m +++ b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Sleep.m @@ -3,8 +3,7 @@ // RCTAppleHealthKit // // Created by Greg Wilson on 2016-11-06. -// This source code is licensed under the MIT-style license found in the -// LICENSE file in the root directory of this source tree. +// Copyright © 2016 Greg Wilson. All rights reserved. // diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Queries.h b/RCTAppleHealthKit/RCTAppleHealthKit+Queries.h index 8ca43a77..d04e9436 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit+Queries.h +++ b/RCTAppleHealthKit/RCTAppleHealthKit+Queries.h @@ -3,8 +3,7 @@ // RCTAppleHealthKit // // Created by Greg Wilson on 2016-06-26. -// This source code is licensed under the MIT-style license found in the -// LICENSE file in the root directory of this source tree. +// Copyright © 2016 Greg Wilson. All rights reserved. // #import "RCTAppleHealthKit.h" @@ -25,6 +24,14 @@ ascending:(BOOL)asc limit:(NSUInteger)lim completion:(void (^)(NSArray *, NSError *))completion; +- (void)fetchQuantitySamplesOfType:(HKQuantityType *)quantityType + unit:(HKUnit *)unit + predicate:(NSPredicate *)predicate + ascending:(BOOL)asc + limit:(NSUInteger)lim + additionalParamName:(NSString *)paramName + additionalParam:(BOOL)param + completion:(void (^)(NSArray *, NSError *))completion; - (void)fetchCorrelationSamplesOfType:(HKQuantityType *)quantityType unit:(HKUnit *)unit predicate:(NSPredicate *)predicate diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Queries.m b/RCTAppleHealthKit/RCTAppleHealthKit+Queries.m index 6ca460cd..fab08e2f 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit+Queries.m +++ b/RCTAppleHealthKit/RCTAppleHealthKit+Queries.m @@ -3,8 +3,7 @@ // RCTAppleHealthKit // // Created by Greg Wilson on 2016-06-26. -// This source code is licensed under the MIT-style license found in the -// LICENSE file in the root directory of this source tree. +// Copyright © 2016 Greg Wilson. All rights reserved. // #import "RCTAppleHealthKit+Queries.h" @@ -106,7 +105,64 @@ - (void)fetchQuantitySamplesOfType:(HKQuantityType *)quantityType [self.healthStore executeQuery:query]; } - +- (void)fetchQuantitySamplesOfType:(HKQuantityType *)quantityType + unit:(HKUnit *)unit + predicate:(NSPredicate *)predicate + ascending:(BOOL)asc + limit:(NSUInteger)lim + additionalParamName:(NSString *)paramName + additionalParam:(BOOL)param + completion:(void (^)(NSArray *, NSError *))completion { + + NSSortDescriptor *timeSortDescriptor = [[NSSortDescriptor alloc] initWithKey:HKSampleSortIdentifierEndDate + ascending:asc]; + + // declare the block + void (^handlerBlock)(HKSampleQuery *query, NSArray *results, NSError *error); + // create and assign the block + handlerBlock = ^(HKSampleQuery *query, NSArray *results, NSError *error) { + if (!results) { + if (completion) { + completion(nil, error); + } + return; + } + + if (completion) { + NSMutableArray *data = [NSMutableArray arrayWithCapacity:1]; + + dispatch_async(dispatch_get_main_queue(), ^{ + + for (HKQuantitySample *sample in results) { + HKQuantity *quantity = sample.quantity; + double value = [quantity doubleValueForUnit:unit]; + + NSString *startDateString = [RCTAppleHealthKit buildISO8601StringFromDate:sample.startDate]; + NSString *endDateString = [RCTAppleHealthKit buildISO8601StringFromDate:sample.endDate]; + + NSDictionary *elem = @{ + @"value" : @(value), + @"startDate" : startDateString, + @"endDate" : endDateString, + paramName : @(param), + }; + + [data addObject:elem]; + } + + completion(data, error); + }); + } + }; + + HKSampleQuery *query = [[HKSampleQuery alloc] initWithSampleType:quantityType + predicate:predicate + limit:lim + sortDescriptors:@[timeSortDescriptor] + resultsHandler:handlerBlock]; + + [self.healthStore executeQuery:query]; +} diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+TypesAndPermissions.h b/RCTAppleHealthKit/RCTAppleHealthKit+TypesAndPermissions.h index 5cb0891b..73438fe4 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit+TypesAndPermissions.h +++ b/RCTAppleHealthKit/RCTAppleHealthKit+TypesAndPermissions.h @@ -3,8 +3,7 @@ // RCTAppleHealthKit // // Created by Greg Wilson on 2016-06-26. -// This source code is licensed under the MIT-style license found in the -// LICENSE file in the root directory of this source tree. +// Copyright © 2016 Greg Wilson. All rights reserved. // #import "RCTAppleHealthKit.h" diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+TypesAndPermissions.m b/RCTAppleHealthKit/RCTAppleHealthKit+TypesAndPermissions.m index 356accb0..b22e6f34 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit+TypesAndPermissions.m +++ b/RCTAppleHealthKit/RCTAppleHealthKit+TypesAndPermissions.m @@ -3,8 +3,7 @@ // RCTAppleHealthKit // // Created by Greg Wilson on 2016-06-26. -// This source code is licensed under the MIT-style license found in the -// LICENSE file in the root directory of this source tree. +// Copyright © 2016 Greg Wilson. All rights reserved. // #import "RCTAppleHealthKit+TypesAndPermissions.h" diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Utils.h b/RCTAppleHealthKit/RCTAppleHealthKit+Utils.h index 4501675e..f5d33f38 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit+Utils.h +++ b/RCTAppleHealthKit/RCTAppleHealthKit+Utils.h @@ -3,8 +3,7 @@ // RCTAppleHealthKit // // Created by Greg Wilson on 2016-06-26. -// This source code is licensed under the MIT-style license found in the -// LICENSE file in the root directory of this source tree. +// Copyright © 2016 Greg Wilson. All rights reserved. // #import "RCTAppleHealthKit.h" diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Utils.m b/RCTAppleHealthKit/RCTAppleHealthKit+Utils.m index 7e0a834c..9ffb0967 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit+Utils.m +++ b/RCTAppleHealthKit/RCTAppleHealthKit+Utils.m @@ -3,8 +3,7 @@ // RCTAppleHealthKit // // Created by Greg Wilson on 2016-06-26. -// This source code is licensed under the MIT-style license found in the -// LICENSE file in the root directory of this source tree. +// Copyright © 2016 Greg Wilson. All rights reserved. // #import "RCTAppleHealthKit+Utils.h" diff --git a/RCTAppleHealthKit/RCTAppleHealthKit.h b/RCTAppleHealthKit/RCTAppleHealthKit.h index 27b8c036..39b60341 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit.h +++ b/RCTAppleHealthKit/RCTAppleHealthKit.h @@ -3,8 +3,7 @@ // RCTAppleHealthKit // // Created by Greg Wilson on 2016-06-26. -// This source code is licensed under the MIT-style license found in the -// LICENSE file in the root directory of this source tree. +// Copyright © 2016 Greg Wilson. All rights reserved. // #import diff --git a/RCTAppleHealthKit/RCTAppleHealthKit.m b/RCTAppleHealthKit/RCTAppleHealthKit.m index bb8ac703..35a2823d 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit.m +++ b/RCTAppleHealthKit/RCTAppleHealthKit.m @@ -3,8 +3,7 @@ // RCTAppleHealthKit // // Created by Greg Wilson on 2016-06-26. -// This source code is licensed under the MIT-style license found in the -// LICENSE file in the root directory of this source tree. +// Copyright © 2016 Greg Wilson. All rights reserved. // #import "RCTAppleHealthKit.h" @@ -107,6 +106,11 @@ @implementation RCTAppleHealthKit [self fitness_getStepCountOnDay:input callback:callback]; } +RCT_EXPORT_METHOD(getStepCountSamples:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback) +{ + [self fitness_getStepCountSamples:input callback:callback]; +} + RCT_EXPORT_METHOD(getDailyStepCountSamples:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback) { [self fitness_getDailyStepSamples:input callback:callback]; From fd433d53f568a4215fdb9175d6f94d9ca3ba5847 Mon Sep 17 00:00:00 2001 From: Evgenii Evstropov Date: Sun, 4 Feb 2018 00:44:26 +0100 Subject: [PATCH 02/24] support multiple types of retrieving samples (just names confusing) --- .../RCTAppleHealthKit+Methods_Fitness.m | 17 ++++++++++++++--- RCTAppleHealthKit/RCTAppleHealthKit+Queries.m | 1 - 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Fitness.m b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Fitness.m index 9decba15..09994bda 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Fitness.m +++ b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Fitness.m @@ -54,6 +54,7 @@ - (void)fitness_getStepCountSamples:(NSDictionary *)input callback:(RCTResponseS NSUInteger limit = [RCTAppleHealthKit uintFromOptions:input key:@"limit" withDefault:HKObjectQueryNoLimit]; BOOL ascending = [RCTAppleHealthKit boolFromOptions:input key:@"ascending" withDefault:false]; BOOL isTracked = [RCTAppleHealthKit boolFromOptions:input key:@"isTracked" withDefault:true]; + NSString *type = [RCTAppleHealthKit stringFromOptions:input key:@"type" withDefault:@"Walking"]; NSDate *startDate = [RCTAppleHealthKit dateFromOptions:input key:@"startDate" withDefault:nil]; NSDate *endDate = [RCTAppleHealthKit dateFromOptions:input key:@"endDate" withDefault:[NSDate date]]; if(startDate == nil){ @@ -62,7 +63,6 @@ - (void)fitness_getStepCountSamples:(NSDictionary *)input callback:(RCTResponseS } NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; [formatter setDateFormat:@"YYYY-MM-dd-hh-mm-ss"]; - NSLog(@"samples interval: %@ %@",[formatter stringFromDate:startDate], [formatter stringFromDate:endDate]); // no isTracked NSArray *subPredicates = [[NSArray alloc] init]; @@ -74,11 +74,22 @@ - (void)fitness_getStepCountSamples:(NSDictionary *)input callback:(RCTResponseS subPredicates = [subPredicatesAux copy]; NSPredicate *predicate = [NSCompoundPredicate andPredicateWithSubpredicates:subPredicates]; - HKQuantityType *stepCountType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierStepCount]; + HKQuantityType *samplesType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierStepCount]; + if ([type isEqual:@"Walking"]) { + samplesType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierStepCount]; + } else if ([type isEqual:@"StairClimbing"]) { + samplesType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierFlightsClimbed]; + } else if ([type isEqual:@"Running"]){ + samplesType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierDistanceWalkingRunning]; + unit = [HKUnit mileUnit]; + } else if ([type isEqual:@"Cycling"]){ + samplesType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierDistanceCycling]; + unit = [HKUnit mileUnit]; + } NSString * paramName = @"isTracked"; - [self fetchQuantitySamplesOfType:stepCountType + [self fetchQuantitySamplesOfType:samplesType unit:unit predicate:predicate ascending:ascending diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Queries.m b/RCTAppleHealthKit/RCTAppleHealthKit+Queries.m index fab08e2f..a0c04864 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit+Queries.m +++ b/RCTAppleHealthKit/RCTAppleHealthKit+Queries.m @@ -113,7 +113,6 @@ - (void)fetchQuantitySamplesOfType:(HKQuantityType *)quantityType additionalParamName:(NSString *)paramName additionalParam:(BOOL)param completion:(void (^)(NSArray *, NSError *))completion { - NSSortDescriptor *timeSortDescriptor = [[NSSortDescriptor alloc] initWithKey:HKSampleSortIdentifierEndDate ascending:asc]; From 22894714311c81b05a0dce4a408ab239562c017b Mon Sep 17 00:00:00 2001 From: Evgenii Evstropov Date: Sun, 4 Feb 2018 18:59:13 +0100 Subject: [PATCH 03/24] add simple (only to console output) support for Workouts retrieving --- Constants/Permissions.js | 3 +- .../RCTAppleHealthKit+Methods_Fitness.h | 2 +- .../RCTAppleHealthKit+Methods_Fitness.m | 9 ++- RCTAppleHealthKit/RCTAppleHealthKit+Queries.m | 59 +++++++++++++------ .../RCTAppleHealthKit+TypesAndPermissions.m | 2 + RCTAppleHealthKit/RCTAppleHealthKit.m | 4 +- 6 files changed, 53 insertions(+), 26 deletions(-) diff --git a/Constants/Permissions.js b/Constants/Permissions.js index 927fe4b3..9d44aec5 100644 --- a/Constants/Permissions.js +++ b/Constants/Permissions.js @@ -29,5 +29,6 @@ export const Permissions = { SleepAnalysis: "SleepAnalysis", StepCount: "StepCount", Steps: "Steps", - Weight: "Weight" + Weight: "Weight", + Workout: "Workout" } diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Fitness.h b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Fitness.h index 5a38559f..9f201735 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Fitness.h +++ b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Fitness.h @@ -11,7 +11,7 @@ @interface RCTAppleHealthKit (Methods_Fitness) - (void)fitness_getStepCountOnDay:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; -- (void)fitness_getStepCountSamples:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; +- (void)fitness_getSamples:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; - (void)fitness_getDailyStepSamples:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; - (void)fitness_saveSteps:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; - (void)fitness_initializeStepEventObserver:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Fitness.m b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Fitness.m index 09994bda..23c8ea36 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Fitness.m +++ b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Fitness.m @@ -48,7 +48,7 @@ - (void)fitness_getStepCountOnDay:(NSDictionary *)input callback:(RCTResponseSen }]; } -- (void)fitness_getStepCountSamples:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback +- (void)fitness_getSamples:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback { HKUnit *unit = [RCTAppleHealthKit hkUnitFromOptions:input key:@"unit" withDefault:[HKUnit countUnit]]; NSUInteger limit = [RCTAppleHealthKit uintFromOptions:input key:@"limit" withDefault:HKObjectQueryNoLimit]; @@ -72,9 +72,10 @@ - (void)fitness_getStepCountSamples:(NSDictionary *)input callback:(RCTResponseS [subPredicatesAux addObject:predicateDate]; [subPredicatesAux addObject:predicateType]; subPredicates = [subPredicatesAux copy]; - NSPredicate *predicate = [NSCompoundPredicate andPredicateWithSubpredicates:subPredicates]; + + NSPredicate *predicate = [NSCompoundPredicate andPredicateWithSubpredicates:[NSArray arrayWithObjects:predicateType, predicateDate, nil]]; - HKQuantityType *samplesType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierStepCount]; + HKSampleType *samplesType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierStepCount]; if ([type isEqual:@"Walking"]) { samplesType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierStepCount]; } else if ([type isEqual:@"StairClimbing"]) { @@ -85,6 +86,8 @@ - (void)fitness_getStepCountSamples:(NSDictionary *)input callback:(RCTResponseS } else if ([type isEqual:@"Cycling"]){ samplesType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierDistanceCycling]; unit = [HKUnit mileUnit]; + } else if ([type isEqual:@"Workout"]){ + samplesType = [HKObjectType workoutType]; } NSString * paramName = @"isTracked"; diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Queries.m b/RCTAppleHealthKit/RCTAppleHealthKit+Queries.m index a0c04864..d296a67b 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit+Queries.m +++ b/RCTAppleHealthKit/RCTAppleHealthKit+Queries.m @@ -105,7 +105,7 @@ - (void)fetchQuantitySamplesOfType:(HKQuantityType *)quantityType [self.healthStore executeQuery:query]; } -- (void)fetchQuantitySamplesOfType:(HKQuantityType *)quantityType +- (void)fetchQuantitySamplesOfType:(HKSampleType *)type unit:(HKUnit *)unit predicate:(NSPredicate *)predicate ascending:(BOOL)asc @@ -131,22 +131,44 @@ - (void)fetchQuantitySamplesOfType:(HKQuantityType *)quantityType NSMutableArray *data = [NSMutableArray arrayWithCapacity:1]; dispatch_async(dispatch_get_main_queue(), ^{ - - for (HKQuantitySample *sample in results) { - HKQuantity *quantity = sample.quantity; - double value = [quantity doubleValueForUnit:unit]; - - NSString *startDateString = [RCTAppleHealthKit buildISO8601StringFromDate:sample.startDate]; - NSString *endDateString = [RCTAppleHealthKit buildISO8601StringFromDate:sample.endDate]; - - NSDictionary *elem = @{ - @"value" : @(value), - @"startDate" : startDateString, - @"endDate" : endDateString, - paramName : @(param), - }; - - [data addObject:elem]; + if (type == [HKObjectType workoutType]) { + for (HKWorkout *sample in results) { + HKQuantity *quantity = sample.quantity; + double value = [quantity doubleValueForUnit:unit]; + + NSString *startDateString = [RCTAppleHealthKit buildISO8601StringFromDate:sample.startDate]; + NSString *endDateString = [RCTAppleHealthKit buildISO8601StringFromDate:sample.endDate]; + + NSDictionary *elem = @{ + @"value" : @(value), + @"startDate" : startDateString, + @"endDate" : endDateString, + paramName : @(param), + }; + + [data addObject:elem]; + + NSLog(@"%lu", (unsigned long)[sample workoutActivityType]); + NSLog(@"energy burned %f", [[sample totalEnergyBurned] doubleValueForUnit:[HKUnit kilocalorieUnit]]); + NSLog(@"total distance %f", [[sample totalDistance] doubleValueForUnit:[HKUnit mileUnit]]); + } + } else { + for (HKQuantitySample *sample in results) { + HKQuantity *quantity = sample.quantity; + double value = [quantity doubleValueForUnit:unit]; + + NSString *startDateString = [RCTAppleHealthKit buildISO8601StringFromDate:sample.startDate]; + NSString *endDateString = [RCTAppleHealthKit buildISO8601StringFromDate:sample.endDate]; + + NSDictionary *elem = @{ + @"value" : @(value), + @"startDate" : startDateString, + @"endDate" : endDateString, + paramName : @(param), + }; + + [data addObject:elem]; + } } completion(data, error); @@ -154,7 +176,7 @@ - (void)fetchQuantitySamplesOfType:(HKQuantityType *)quantityType } }; - HKSampleQuery *query = [[HKSampleQuery alloc] initWithSampleType:quantityType + HKSampleQuery *query = [[HKSampleQuery alloc] initWithSampleType:type predicate:predicate limit:lim sortDescriptors:@[timeSortDescriptor] @@ -168,7 +190,6 @@ - (void)fetchQuantitySamplesOfType:(HKQuantityType *)quantityType - - (void)fetchSleepCategorySamplesForPredicate:(NSPredicate *)predicate limit:(NSUInteger)lim completion:(void (^)(NSArray *, NSError *))completion { diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+TypesAndPermissions.m b/RCTAppleHealthKit/RCTAppleHealthKit+TypesAndPermissions.m index b22e6f34..70220812 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit+TypesAndPermissions.m +++ b/RCTAppleHealthKit/RCTAppleHealthKit+TypesAndPermissions.m @@ -49,6 +49,8 @@ - (NSDictionary *)readPermsDict { @"SleepAnalysis" : [HKObjectType categoryTypeForIdentifier:HKCategoryTypeIdentifierSleepAnalysis], // Mindfulness @"MindfulSession" : [HKObjectType categoryTypeForIdentifier:HKCategoryTypeIdentifierMindfulSession], + //workouts + @"Workout" : [HKObjectType workoutType], }; return readPerms; } diff --git a/RCTAppleHealthKit/RCTAppleHealthKit.m b/RCTAppleHealthKit/RCTAppleHealthKit.m index 35a2823d..04e3d575 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit.m +++ b/RCTAppleHealthKit/RCTAppleHealthKit.m @@ -106,9 +106,9 @@ @implementation RCTAppleHealthKit [self fitness_getStepCountOnDay:input callback:callback]; } -RCT_EXPORT_METHOD(getStepCountSamples:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback) +RCT_EXPORT_METHOD(getSamples:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback) { - [self fitness_getStepCountSamples:input callback:callback]; + [self fitness_getSamples:input callback:callback]; } RCT_EXPORT_METHOD(getDailyStepCountSamples:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback) From dd643582b94546bad09ae18d72e3a8fa1998f377 Mon Sep 17 00:00:00 2001 From: Evgenii Evstropov Date: Sun, 4 Feb 2018 19:25:30 +0100 Subject: [PATCH 04/24] extended support for workouts --- RCTAppleHealthKit/RCTAppleHealthKit+Queries.m | 13 +- RCTAppleHealthKit/RCTAppleHealthKit+Utils.h | 1 + RCTAppleHealthKit/RCTAppleHealthKit+Utils.m | 128 ++++++++++++++++++ 3 files changed, 135 insertions(+), 7 deletions(-) diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Queries.m b/RCTAppleHealthKit/RCTAppleHealthKit+Queries.m index d296a67b..4200a06a 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit+Queries.m +++ b/RCTAppleHealthKit/RCTAppleHealthKit+Queries.m @@ -133,24 +133,23 @@ - (void)fetchQuantitySamplesOfType:(HKSampleType *)type dispatch_async(dispatch_get_main_queue(), ^{ if (type == [HKObjectType workoutType]) { for (HKWorkout *sample in results) { - HKQuantity *quantity = sample.quantity; - double value = [quantity doubleValueForUnit:unit]; + double energy = [[sample totalEnergyBurned] doubleValueForUnit:[HKUnit kilocalorieUnit]]; + double distance = [[sample totalDistance] doubleValueForUnit:[HKUnit mileUnit]]; + NSString *type = [RCTAppleHealthKit stringForHKWorkoutActivityType:[sample workoutActivityType]]; NSString *startDateString = [RCTAppleHealthKit buildISO8601StringFromDate:sample.startDate]; NSString *endDateString = [RCTAppleHealthKit buildISO8601StringFromDate:sample.endDate]; NSDictionary *elem = @{ - @"value" : @(value), + @"type" : type, + @"energy" : @(energy), + @"distance" : @(distance), @"startDate" : startDateString, @"endDate" : endDateString, paramName : @(param), }; [data addObject:elem]; - - NSLog(@"%lu", (unsigned long)[sample workoutActivityType]); - NSLog(@"energy burned %f", [[sample totalEnergyBurned] doubleValueForUnit:[HKUnit kilocalorieUnit]]); - NSLog(@"total distance %f", [[sample totalDistance] doubleValueForUnit:[HKUnit mileUnit]]); } } else { for (HKQuantitySample *sample in results) { diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Utils.h b/RCTAppleHealthKit/RCTAppleHealthKit+Utils.h index f5d33f38..a78acc54 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit+Utils.h +++ b/RCTAppleHealthKit/RCTAppleHealthKit+Utils.h @@ -32,5 +32,6 @@ + (bool)boolFromOptions:(NSDictionary *)options key:(NSString *)key withDefault:(bool)defaultValue; + (NSMutableArray *)reverseNSMutableArray:(NSMutableArray *)array; ++ (NSString*) stringForHKWorkoutActivityType:(int) enumValue; @end diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Utils.m b/RCTAppleHealthKit/RCTAppleHealthKit+Utils.m index 9ffb0967..1c54e6d2 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit+Utils.m +++ b/RCTAppleHealthKit/RCTAppleHealthKit+Utils.m @@ -320,4 +320,132 @@ + (NSMutableArray *)reverseNSMutableArray:(NSMutableArray *)array { return array; } ++ (NSString*)stringForHKWorkoutActivityType:(int) enumValue{ + switch( enumValue ){ + case HKWorkoutActivityTypeAmericanFootball: + return @"AmericanFootball"; + case HKWorkoutActivityTypeArchery: + return @"Archery"; + case HKWorkoutActivityTypeAustralianFootball: + return @"AustralianFootball"; + case HKWorkoutActivityTypeBadminton: + return @"Badminton"; + case HKWorkoutActivityTypeBaseball: + return @"Baseball"; + case HKWorkoutActivityTypeBasketball: + return @"Basketball"; + case HKWorkoutActivityTypeBowling: + return @"Bowling"; + case HKWorkoutActivityTypeBoxing: + return @"Boxing"; + case HKWorkoutActivityTypeClimbing: + return @"Climbing"; + case HKWorkoutActivityTypeCricket: + return @"Cricket"; + case HKWorkoutActivityTypeCrossTraining: + return @"CrossTraining"; + case HKWorkoutActivityTypeCurling: + return @"Curling"; + case HKWorkoutActivityTypeCycling: + return @"Cycling"; + case HKWorkoutActivityTypeDance: + return @"Dance"; + case HKWorkoutActivityTypeDanceInspiredTraining: + return @"DanceInspiredTraining"; + case HKWorkoutActivityTypeElliptical: + return @"Elliptical"; + case HKWorkoutActivityTypeEquestrianSports: + return @"EquestrianSports"; + case HKWorkoutActivityTypeFencing: + return @"Fencing"; + case HKWorkoutActivityTypeFishing: + return @"Fishing"; + case HKWorkoutActivityTypeFunctionalStrengthTraining: + return @"FunctionalStrengthTraining"; + case HKWorkoutActivityTypeGolf: + return @"Golf"; + case HKWorkoutActivityTypeGymnastics: + return @"Gymnastics"; + case HKWorkoutActivityTypeHandball: + return @"Handball"; + case HKWorkoutActivityTypeHiking: + return @"Hiking"; + case HKWorkoutActivityTypeHockey: + return @"Hockey"; + case HKWorkoutActivityTypeHunting: + return @"Hunting"; + case HKWorkoutActivityTypeLacrosse: + return @"Lacrosse"; + case HKWorkoutActivityTypeMartialArts: + return @"MartialArts"; + case HKWorkoutActivityTypeMindAndBody: + return @"MindAndBody"; + case HKWorkoutActivityTypeMixedMetabolicCardioTraining: + return @"MixedMetabolicCardioTraining"; + case HKWorkoutActivityTypePaddleSports: + return @"PaddleSports"; + case HKWorkoutActivityTypePlay: + return @"Play"; + case HKWorkoutActivityTypePreparationAndRecovery: + return @"PreparationAndRecovery"; + case HKWorkoutActivityTypeRacquetball: + return @"Racquetball"; + case HKWorkoutActivityTypeRowing: + return @"Rowing"; + case HKWorkoutActivityTypeRugby: + return @"Rugby"; + case HKWorkoutActivityTypeRunning: + return @"Running"; + case HKWorkoutActivityTypeSailing: + return @"Sailing"; + case HKWorkoutActivityTypeSkatingSports: + return @"SkatingSports"; + case HKWorkoutActivityTypeSnowSports: + return @"SnowSports"; + case HKWorkoutActivityTypeSoccer: + return @"Soccer"; + case HKWorkoutActivityTypeSoftball: + return @"Softball"; + case HKWorkoutActivityTypeSquash: + return @"Squash"; + case HKWorkoutActivityTypeStairClimbing: + return @"StairClimbing"; + case HKWorkoutActivityTypeSurfingSports: + return @"SurfingSports"; + case HKWorkoutActivityTypeSwimming: + return @"Swimming"; + case HKWorkoutActivityTypeTableTennis: + return @"TableTennis"; + case HKWorkoutActivityTypeTennis: + return @"Tennis"; + case HKWorkoutActivityTypeTrackAndField: + return @"TrackAndField"; + case HKWorkoutActivityTypeTraditionalStrengthTraining: + return @"TraditionalStrengthTraining"; + case HKWorkoutActivityTypeVolleyball: + return @"Volleyball"; + case HKWorkoutActivityTypeWalking: + return @"Walking"; + case HKWorkoutActivityTypeWaterFitness: + return @"WaterFitness"; + case HKWorkoutActivityTypeWaterPolo: + return @"WaterPolo"; + case HKWorkoutActivityTypeWaterSports: + return @"WaterSports"; + case HKWorkoutActivityTypeWrestling: + return @"Wrestling"; + case HKWorkoutActivityTypeYoga: + return @"Yoga"; + case HKWorkoutActivityTypeOther: + return @"Other"; + default:{ + NSException *e = [NSException + exceptionWithName:@"HKWorkoutActivityType InvalidValue" + reason:@"HKWorkoutActivityType can only have a value from the HKWorkoutActivityType enum" + userInfo:nil]; + @throw e; + } + } +} + @end From c3b532436ea7b2094dc570f1c7597b60bbb14074 Mon Sep 17 00:00:00 2001 From: Evgenii Evstropov Date: Sun, 4 Feb 2018 19:47:35 +0100 Subject: [PATCH 05/24] update work around isTracked flag, to perfom only one quert for tracked and non-tracked samples --- .../RCTAppleHealthKit+Methods_Fitness.m | 26 +-------- RCTAppleHealthKit/RCTAppleHealthKit+Queries.h | 4 +- RCTAppleHealthKit/RCTAppleHealthKit+Queries.m | 56 +++++++++++-------- 3 files changed, 37 insertions(+), 49 deletions(-) diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Fitness.m b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Fitness.m index 23c8ea36..08226a5a 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Fitness.m +++ b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Fitness.m @@ -53,27 +53,11 @@ - (void)fitness_getSamples:(NSDictionary *)input callback:(RCTResponseSenderBloc HKUnit *unit = [RCTAppleHealthKit hkUnitFromOptions:input key:@"unit" withDefault:[HKUnit countUnit]]; NSUInteger limit = [RCTAppleHealthKit uintFromOptions:input key:@"limit" withDefault:HKObjectQueryNoLimit]; BOOL ascending = [RCTAppleHealthKit boolFromOptions:input key:@"ascending" withDefault:false]; - BOOL isTracked = [RCTAppleHealthKit boolFromOptions:input key:@"isTracked" withDefault:true]; NSString *type = [RCTAppleHealthKit stringFromOptions:input key:@"type" withDefault:@"Walking"]; - NSDate *startDate = [RCTAppleHealthKit dateFromOptions:input key:@"startDate" withDefault:nil]; + NSDate *startDate = [RCTAppleHealthKit dateFromOptions:input key:@"startDate" withDefault:[NSDate date]]; NSDate *endDate = [RCTAppleHealthKit dateFromOptions:input key:@"endDate" withDefault:[NSDate date]]; - if(startDate == nil){ - callback(@[RCTMakeError(@"startDate is required in options", nil, nil)]); - return; - } - NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; - [formatter setDateFormat:@"YYYY-MM-dd-hh-mm-ss"]; - // no isTracked - NSArray *subPredicates = [[NSArray alloc] init]; - NSMutableArray *subPredicatesAux = [[NSMutableArray alloc] init]; - NSPredicate *predicateDate = [HKQuery predicateForSamplesWithStartDate:startDate endDate:endDate options:HKQueryOptionStrictStartDate]; - NSPredicate *predicateType = isTracked ? [NSPredicate predicateWithFormat:@"metadata.%K != YES", HKMetadataKeyWasUserEntered] : [NSPredicate predicateWithFormat:@"metadata.%K == YES", HKMetadataKeyWasUserEntered]; - [subPredicatesAux addObject:predicateDate]; - [subPredicatesAux addObject:predicateType]; - subPredicates = [subPredicatesAux copy]; - - NSPredicate *predicate = [NSCompoundPredicate andPredicateWithSubpredicates:[NSArray arrayWithObjects:predicateType, predicateDate, nil]]; + NSPredicate *predicate = [HKQuery predicateForSamplesWithStartDate:startDate endDate:endDate options:HKQueryOptionStrictStartDate]; HKSampleType *samplesType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierStepCount]; if ([type isEqual:@"Walking"]) { @@ -90,15 +74,11 @@ - (void)fitness_getSamples:(NSDictionary *)input callback:(RCTResponseSenderBloc samplesType = [HKObjectType workoutType]; } - NSString * paramName = @"isTracked"; - - [self fetchQuantitySamplesOfType:samplesType + [self fetchSamplesOfType:samplesType unit:unit predicate:predicate ascending:ascending limit:limit - additionalParamName:paramName - additionalParam:isTracked completion:^(NSArray *results, NSError *error) { if(results){ callback(@[[NSNull null], results]); diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Queries.h b/RCTAppleHealthKit/RCTAppleHealthKit+Queries.h index d04e9436..39dc12cb 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit+Queries.h +++ b/RCTAppleHealthKit/RCTAppleHealthKit+Queries.h @@ -18,7 +18,7 @@ startDate:(NSDate *)startDate endDate:(NSDate *)endDate completion:(void (^)(NSArray *, NSError *))completionHandler; -- (void)fetchQuantitySamplesOfType:(HKQuantityType *)quantityType +- (void)fetchSamplesOfType:(HKSampleType *)quantityType unit:(HKUnit *)unit predicate:(NSPredicate *)predicate ascending:(BOOL)asc @@ -29,8 +29,6 @@ predicate:(NSPredicate *)predicate ascending:(BOOL)asc limit:(NSUInteger)lim - additionalParamName:(NSString *)paramName - additionalParam:(BOOL)param completion:(void (^)(NSArray *, NSError *))completion; - (void)fetchCorrelationSamplesOfType:(HKQuantityType *)quantityType unit:(HKUnit *)unit diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Queries.m b/RCTAppleHealthKit/RCTAppleHealthKit+Queries.m index 4200a06a..d8aa95af 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit+Queries.m +++ b/RCTAppleHealthKit/RCTAppleHealthKit+Queries.m @@ -48,17 +48,16 @@ - (void)fetchMostRecentQuantitySampleOfType:(HKQuantityType *)quantityType [self.healthStore executeQuery:query]; } - - (void)fetchQuantitySamplesOfType:(HKQuantityType *)quantityType unit:(HKUnit *)unit predicate:(NSPredicate *)predicate ascending:(BOOL)asc limit:(NSUInteger)lim completion:(void (^)(NSArray *, NSError *))completion { - + NSSortDescriptor *timeSortDescriptor = [[NSSortDescriptor alloc] initWithKey:HKSampleSortIdentifierEndDate ascending:asc]; - + // declare the block void (^handlerBlock)(HKSampleQuery *query, NSArray *results, NSError *error); // create and assign the block @@ -69,49 +68,49 @@ - (void)fetchQuantitySamplesOfType:(HKQuantityType *)quantityType } return; } - + if (completion) { NSMutableArray *data = [NSMutableArray arrayWithCapacity:1]; - + dispatch_async(dispatch_get_main_queue(), ^{ - + for (HKQuantitySample *sample in results) { HKQuantity *quantity = sample.quantity; double value = [quantity doubleValueForUnit:unit]; - + NSString *startDateString = [RCTAppleHealthKit buildISO8601StringFromDate:sample.startDate]; NSString *endDateString = [RCTAppleHealthKit buildISO8601StringFromDate:sample.endDate]; - + NSDictionary *elem = @{ - @"value" : @(value), - @"startDate" : startDateString, - @"endDate" : endDateString, - }; - + @"value" : @(value), + @"startDate" : startDateString, + @"endDate" : endDateString, + }; + [data addObject:elem]; } - + completion(data, error); }); } }; - + HKSampleQuery *query = [[HKSampleQuery alloc] initWithSampleType:quantityType predicate:predicate limit:lim sortDescriptors:@[timeSortDescriptor] resultsHandler:handlerBlock]; - + [self.healthStore executeQuery:query]; } -- (void)fetchQuantitySamplesOfType:(HKSampleType *)type + + +- (void)fetchSamplesOfType:(HKSampleType *)type unit:(HKUnit *)unit predicate:(NSPredicate *)predicate ascending:(BOOL)asc limit:(NSUInteger)lim - additionalParamName:(NSString *)paramName - additionalParam:(BOOL)param completion:(void (^)(NSArray *, NSError *))completion { NSSortDescriptor *timeSortDescriptor = [[NSSortDescriptor alloc] initWithKey:HKSampleSortIdentifierEndDate ascending:asc]; @@ -139,14 +138,19 @@ - (void)fetchQuantitySamplesOfType:(HKSampleType *)type NSString *startDateString = [RCTAppleHealthKit buildISO8601StringFromDate:sample.startDate]; NSString *endDateString = [RCTAppleHealthKit buildISO8601StringFromDate:sample.endDate]; + bool isTracked = true; + for(id key in [sample metadata]) + if (key == HKMetadataKeyWasUserEntered ) { + isTracked = false; + } NSDictionary *elem = @{ @"type" : type, @"energy" : @(energy), + @"isTracked" : @(isTracked), @"distance" : @(distance), @"startDate" : startDateString, - @"endDate" : endDateString, - paramName : @(param), + @"endDate" : endDateString }; [data addObject:elem]; @@ -159,11 +163,17 @@ - (void)fetchQuantitySamplesOfType:(HKSampleType *)type NSString *startDateString = [RCTAppleHealthKit buildISO8601StringFromDate:sample.startDate]; NSString *endDateString = [RCTAppleHealthKit buildISO8601StringFromDate:sample.endDate]; + bool isTracked = true; + for(id key in [sample metadata]) + if (key == HKMetadataKeyWasUserEntered ) { + isTracked = false; + } + NSDictionary *elem = @{ @"value" : @(value), + @"isTracked" : @(isTracked), @"startDate" : startDateString, - @"endDate" : endDateString, - paramName : @(param), + @"endDate" : endDateString }; [data addObject:elem]; From d2a9ce057fd53a128b280f3d10e9f44b94e4a287 Mon Sep 17 00:00:00 2001 From: Evgenii Evstropov Date: Sun, 4 Feb 2018 20:44:29 +0100 Subject: [PATCH 06/24] add support for more information and fix isTracked flag --- RCTAppleHealthKit/RCTAppleHealthKit+Queries.m | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Queries.m b/RCTAppleHealthKit/RCTAppleHealthKit+Queries.m index d8aa95af..d28cb4be 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit+Queries.m +++ b/RCTAppleHealthKit/RCTAppleHealthKit+Queries.m @@ -138,16 +138,19 @@ - (void)fetchSamplesOfType:(HKSampleType *)type NSString *startDateString = [RCTAppleHealthKit buildISO8601StringFromDate:sample.startDate]; NSString *endDateString = [RCTAppleHealthKit buildISO8601StringFromDate:sample.endDate]; + bool isTracked = true; - for(id key in [sample metadata]) - if (key == HKMetadataKeyWasUserEntered ) { - isTracked = false; - } + if ([[sample metadata][HKMetadataKeyWasUserEntered] intValue] == 1) { + isTracked = false; + } NSDictionary *elem = @{ @"type" : type, @"energy" : @(energy), @"isTracked" : @(isTracked), + @"sourceName" : [[[sample sourceRevision] source] name], + @"sourceBundleId" : [[[sample sourceRevision] source] bundleIdentifier], + @"device": [[sample sourceRevision] productType], @"distance" : @(distance), @"startDate" : startDateString, @"endDate" : endDateString @@ -164,14 +167,16 @@ - (void)fetchSamplesOfType:(HKSampleType *)type NSString *endDateString = [RCTAppleHealthKit buildISO8601StringFromDate:sample.endDate]; bool isTracked = true; - for(id key in [sample metadata]) - if (key == HKMetadataKeyWasUserEntered ) { - isTracked = false; - } + if ([[sample metadata][HKMetadataKeyWasUserEntered] intValue] == 1) { + isTracked = false; + } NSDictionary *elem = @{ @"value" : @(value), @"isTracked" : @(isTracked), + @"sourceName" : [[[sample sourceRevision] source] name], + @"sourceBundleId" : [[[sample sourceRevision] source] bundleIdentifier], + @"device": [[sample sourceRevision] productType], @"startDate" : startDateString, @"endDate" : endDateString }; From 34b3320ff58cc704b2caa74504fc1367109e6770 Mon Sep 17 00:00:00 2001 From: Evgenii Evstropov Date: Tue, 6 Feb 2018 12:12:59 +0100 Subject: [PATCH 07/24] add ios10 and ios11 workout activities types --- RCTAppleHealthKit/RCTAppleHealthKit+Utils.m | 34 +++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Utils.m b/RCTAppleHealthKit/RCTAppleHealthKit+Utils.m index 1c54e6d2..93b042a7 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit+Utils.m +++ b/RCTAppleHealthKit/RCTAppleHealthKit+Utils.m @@ -438,6 +438,40 @@ + (NSString*)stringForHKWorkoutActivityType:(int) enumValue{ return @"Yoga"; case HKWorkoutActivityTypeOther: return @"Other"; + case HKWorkoutActivityTypeBarre: + return @"TypeBarre"; + case HKWorkoutActivityTypeCoreTraining: + return @"TypeCoreTraining"; + case HKWorkoutActivityTypeCrossCountrySkiing: + return @"TypeCrossCountrySkiing"; + case HKWorkoutActivityTypeDownhillSkiing: + return @"TypeDownhillSkiing"; + case HKWorkoutActivityTypeFlexibility: + return @"TypeFlexibility"; + case HKWorkoutActivityTypeHighIntensityIntervalTraining: + return @"TypeHighIntensityIntervalTraining"; + case HKWorkoutActivityTypeJumpRope: + return @"TypeJumpRope"; + case HKWorkoutActivityTypeKickboxing: + return @"TypeKickboxing"; + case HKWorkoutActivityTypePilates: + return @"TypePilates"; + case HKWorkoutActivityTypeSnowboarding: + return @"TypeSnowboarding"; + case HKWorkoutActivityTypeStairs: + return @"TypeStairs"; + case HKWorkoutActivityTypeStepTraining: + return @"TypeStepTraining"; + case HKWorkoutActivityTypeWheelchairWalkPace: + return @"TypeWheelchairWalkPace"; + case HKWorkoutActivityTypeWheelchairRunPace: + return @"TypeWheelchairRunPace"; + case HKWorkoutActivityTypeTaiChi: + return @"TypeTaiChi"; + case HKWorkoutActivityTypeMixedCardio: + return @"TypeMixedCardio"; + case HKWorkoutActivityTypeHandCycling: + return @"TypeHandCycling"; default:{ NSException *e = [NSException exceptionWithName:@"HKWorkoutActivityType InvalidValue" From e2aa87df976cf740f72e0ebec2644ba6446d3e5a Mon Sep 17 00:00:00 2001 From: Evgenii Evstropov Date: Tue, 6 Feb 2018 12:17:51 +0100 Subject: [PATCH 08/24] fix type naming --- RCTAppleHealthKit/RCTAppleHealthKit+Utils.m | 34 ++++++++++----------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Utils.m b/RCTAppleHealthKit/RCTAppleHealthKit+Utils.m index 93b042a7..e1619800 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit+Utils.m +++ b/RCTAppleHealthKit/RCTAppleHealthKit+Utils.m @@ -439,39 +439,39 @@ + (NSString*)stringForHKWorkoutActivityType:(int) enumValue{ case HKWorkoutActivityTypeOther: return @"Other"; case HKWorkoutActivityTypeBarre: - return @"TypeBarre"; + return @"Barre"; case HKWorkoutActivityTypeCoreTraining: - return @"TypeCoreTraining"; + return @"CoreTraining"; case HKWorkoutActivityTypeCrossCountrySkiing: - return @"TypeCrossCountrySkiing"; + return @"CrossCountrySkiing"; case HKWorkoutActivityTypeDownhillSkiing: - return @"TypeDownhillSkiing"; + return @"DownhillSkiing"; case HKWorkoutActivityTypeFlexibility: - return @"TypeFlexibility"; + return @"Flexibility"; case HKWorkoutActivityTypeHighIntensityIntervalTraining: - return @"TypeHighIntensityIntervalTraining"; + return @"HighIntensityIntervalTraining"; case HKWorkoutActivityTypeJumpRope: - return @"TypeJumpRope"; + return @"JumpRope"; case HKWorkoutActivityTypeKickboxing: - return @"TypeKickboxing"; + return @"Kickboxing"; case HKWorkoutActivityTypePilates: - return @"TypePilates"; + return @"Pilates"; case HKWorkoutActivityTypeSnowboarding: - return @"TypeSnowboarding"; + return @"Snowboarding"; case HKWorkoutActivityTypeStairs: - return @"TypeStairs"; + return @"Stairs"; case HKWorkoutActivityTypeStepTraining: - return @"TypeStepTraining"; + return @"StepTraining"; case HKWorkoutActivityTypeWheelchairWalkPace: - return @"TypeWheelchairWalkPace"; + return @"WheelchairWalkPace"; case HKWorkoutActivityTypeWheelchairRunPace: - return @"TypeWheelchairRunPace"; + return @"WheelchairRunPace"; case HKWorkoutActivityTypeTaiChi: - return @"TypeTaiChi"; + return @"TaiChi"; case HKWorkoutActivityTypeMixedCardio: - return @"TypeMixedCardio"; + return @"MixedCardio"; case HKWorkoutActivityTypeHandCycling: - return @"TypeHandCycling"; + return @"HandCycling"; default:{ NSException *e = [NSException exceptionWithName:@"HKWorkoutActivityType InvalidValue" From f51978cc77a57d3e51c2487800c5898a0401b4ae Mon Sep 17 00:00:00 2001 From: Evgenii Evstropov Date: Thu, 8 Feb 2018 20:37:47 +0100 Subject: [PATCH 09/24] raw version of observers --- .../RCTAppleHealthKit+Methods_Fitness.h | 1 + .../RCTAppleHealthKit+Methods_Fitness.m | 25 ++++++++ RCTAppleHealthKit/RCTAppleHealthKit+Queries.h | 7 +++ RCTAppleHealthKit/RCTAppleHealthKit+Queries.m | 63 ++++++++++++++++++- RCTAppleHealthKit/RCTAppleHealthKit.h | 1 + RCTAppleHealthKit/RCTAppleHealthKit.m | 6 ++ 6 files changed, 102 insertions(+), 1 deletion(-) diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Fitness.h b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Fitness.h index 9f201735..bf37c55c 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Fitness.h +++ b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Fitness.h @@ -12,6 +12,7 @@ - (void)fitness_getStepCountOnDay:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; - (void)fitness_getSamples:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; +- (void)fitness_setObserver:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; - (void)fitness_getDailyStepSamples:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; - (void)fitness_saveSteps:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; - (void)fitness_initializeStepEventObserver:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Fitness.m b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Fitness.m index 08226a5a..5e6fc0d7 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Fitness.m +++ b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Fitness.m @@ -91,6 +91,31 @@ - (void)fitness_getSamples:(NSDictionary *)input callback:(RCTResponseSenderBloc }]; } +- (void)fitness_setObserver:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback +{ + HKUnit *unit = [RCTAppleHealthKit hkUnitFromOptions:input key:@"unit" withDefault:[HKUnit countUnit]]; + NSString *type = [RCTAppleHealthKit stringFromOptions:input key:@"type" withDefault:@"Walking"]; + + HKSampleType *samplesType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierStepCount]; + if ([type isEqual:@"Walking"]) { + samplesType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierStepCount]; + } else if ([type isEqual:@"StairClimbing"]) { + samplesType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierFlightsClimbed]; + } else if ([type isEqual:@"Running"]){ + samplesType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierDistanceWalkingRunning]; + unit = [HKUnit mileUnit]; + } else if ([type isEqual:@"Cycling"]){ + samplesType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierDistanceCycling]; + unit = [HKUnit mileUnit]; + } else if ([type isEqual:@"Workout"]){ + samplesType = [HKObjectType workoutType]; + } + + [self setObserverForType:samplesType unit:unit completion:^(NSArray *results, NSError * error) { + callback(@[[NSNull null], results]); + }]; +} + - (void)fitness_getDailyStepSamples:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback { diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Queries.h b/RCTAppleHealthKit/RCTAppleHealthKit+Queries.h index 39dc12cb..8eec34b4 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit+Queries.h +++ b/RCTAppleHealthKit/RCTAppleHealthKit+Queries.h @@ -18,12 +18,19 @@ startDate:(NSDate *)startDate endDate:(NSDate *)endDate completion:(void (^)(NSArray *, NSError *))completionHandler; + + - (void)fetchSamplesOfType:(HKSampleType *)quantityType unit:(HKUnit *)unit predicate:(NSPredicate *)predicate ascending:(BOOL)asc limit:(NSUInteger)lim completion:(void (^)(NSArray *, NSError *))completion; +- (void)setObserverForType:(HKSampleType *)quantityType + unit:(HKUnit *)unit + completion:(void (^)(NSArray *, NSError *))completion; + + - (void)fetchQuantitySamplesOfType:(HKQuantityType *)quantityType unit:(HKUnit *)unit predicate:(NSPredicate *)predicate diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Queries.m b/RCTAppleHealthKit/RCTAppleHealthKit+Queries.m index d28cb4be..d84600ae 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit+Queries.m +++ b/RCTAppleHealthKit/RCTAppleHealthKit+Queries.m @@ -9,6 +9,9 @@ #import "RCTAppleHealthKit+Queries.h" #import "RCTAppleHealthKit+Utils.h" +#import +#import + @implementation RCTAppleHealthKit (Queries) @@ -199,7 +202,65 @@ - (void)fetchSamplesOfType:(HKSampleType *)type [self.healthStore executeQuery:query]; } - +- (void)setObserverForType:(HKSampleType *)type + unit:(HKUnit *)unit + completion:(void (^)(NSArray *, NSError *))completion { + NSLog(@"set observer"); + void(^handler)(HKObserverQuery *query, HKObserverQueryCompletionHandler completionHandler, NSError * _Nullable error); + handler = ^(HKObserverQuery *query, HKObserverQueryCompletionHandler completionHandler, NSError * _Nullable error) { + NSLog(@"enter to a handler %@", [error localizedDescription]); + UIApplication *app = [UIApplication sharedApplication]; + UIApplicationState appState = [app applicationState]; + + if (!self.isSync){ +// switch (appState) { +// case UIApplicationStateActive: +// NSLog(@"app Active try to make sync"); +// break; +// case UIApplicationStateInactive: +// { +// NSLog(@"enter to inactive case"); +// break; +// } +// case UIApplicationStateBackground: +// { +// NSLog(@"enter to background case"); +// self.isSync = true; +// __block UIBackgroundTaskIdentifier backgroundTaskIdentifier = [app beginBackgroundTaskWithExpirationHandler:^{ +// +// NSLog(@"call event background"); +//// [self.bridge.eventDispatcher sendAppEventWithName:@"change:steps" +//// body:@{@"name": @"change:steps"}]; +// [self fetchSamplesOfType:type unit:unit predicate:nil ascending:true limit:1 completion:completion]; +// [app endBackgroundTask:backgroundTaskIdentifier]; +// self.isSync = false; +// }]; +// } +// +// }; + + NSLog(@"enter to background case"); + self.isSync = true; + __block UIBackgroundTaskIdentifier backgroundTaskIdentifier = [app beginBackgroundTaskWithExpirationHandler:^{ + + NSLog(@"call event background"); + [self.bridge.eventDispatcher sendAppEventWithName:@"change:steps" + body:@{@"name": @"change:steps"}]; + [self fetchSamplesOfType:type unit:unit predicate:nil ascending:true limit:1 completion:completion]; + [app endBackgroundTask:backgroundTaskIdentifier]; + completionHandler(); + self.isSync = false; + }]; + } + + }; + HKObserverQuery *query = [[HKObserverQuery alloc] initWithSampleType:type predicate:nil updateHandler:handler]; + + [self.healthStore executeQuery:query]; + [self.healthStore enableBackgroundDeliveryForType:type frequency:HKUpdateFrequencyImmediate withCompletion:^(BOOL success, NSError * _Nullable error) { + NSLog(@"success %s print some error %@", success ? "true" : "false", [error localizedDescription]); + }]; +} diff --git a/RCTAppleHealthKit/RCTAppleHealthKit.h b/RCTAppleHealthKit/RCTAppleHealthKit.h index 39b60341..900c6e39 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit.h +++ b/RCTAppleHealthKit/RCTAppleHealthKit.h @@ -15,6 +15,7 @@ @interface RCTAppleHealthKit : NSObject @property (nonatomic) HKHealthStore *healthStore; +@property BOOL isSync; - (void)isHealthKitAvailable:(RCTResponseSenderBlock)callback; - (void)initializeHealthKit:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; diff --git a/RCTAppleHealthKit/RCTAppleHealthKit.m b/RCTAppleHealthKit/RCTAppleHealthKit.m index 04e3d575..2d1fa49e 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit.m +++ b/RCTAppleHealthKit/RCTAppleHealthKit.m @@ -111,6 +111,12 @@ @implementation RCTAppleHealthKit [self fitness_getSamples:input callback:callback]; } +RCT_EXPORT_METHOD(setObserver:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback) +{ + [self fitness_setObserver:input callback:callback]; +} + + RCT_EXPORT_METHOD(getDailyStepCountSamples:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback) { [self fitness_getDailyStepSamples:input callback:callback]; From f4fb1a9ca89f3ad4f949a50483609080245d3251 Mon Sep 17 00:00:00 2001 From: Adam Ivancza Date: Fri, 9 Feb 2018 19:19:13 +0100 Subject: [PATCH 10/24] Slight updates for HealthKit observer --- .../RCTAppleHealthKit+Methods_Fitness.h | 2 +- .../RCTAppleHealthKit+Methods_Fitness.m | 6 +- RCTAppleHealthKit/RCTAppleHealthKit+Queries.h | 3 +- RCTAppleHealthKit/RCTAppleHealthKit+Queries.m | 67 +++++-------------- RCTAppleHealthKit/RCTAppleHealthKit.m | 4 +- 5 files changed, 21 insertions(+), 61 deletions(-) diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Fitness.h b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Fitness.h index bf37c55c..32fb563c 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Fitness.h +++ b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Fitness.h @@ -12,7 +12,7 @@ - (void)fitness_getStepCountOnDay:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; - (void)fitness_getSamples:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; -- (void)fitness_setObserver:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; +- (void)fitness_setObserver:(NSDictionary *)input; - (void)fitness_getDailyStepSamples:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; - (void)fitness_saveSteps:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; - (void)fitness_initializeStepEventObserver:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Fitness.m b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Fitness.m index 5e6fc0d7..294c9f16 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Fitness.m +++ b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Fitness.m @@ -91,7 +91,7 @@ - (void)fitness_getSamples:(NSDictionary *)input callback:(RCTResponseSenderBloc }]; } -- (void)fitness_setObserver:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback +- (void)fitness_setObserver:(NSDictionary *)input { HKUnit *unit = [RCTAppleHealthKit hkUnitFromOptions:input key:@"unit" withDefault:[HKUnit countUnit]]; NSString *type = [RCTAppleHealthKit stringFromOptions:input key:@"type" withDefault:@"Walking"]; @@ -111,9 +111,7 @@ - (void)fitness_setObserver:(NSDictionary *)input callback:(RCTResponseSenderBlo samplesType = [HKObjectType workoutType]; } - [self setObserverForType:samplesType unit:unit completion:^(NSArray *results, NSError * error) { - callback(@[[NSNull null], results]); - }]; + [self setObserverForType:samplesType unit:unit]; } diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Queries.h b/RCTAppleHealthKit/RCTAppleHealthKit+Queries.h index 8eec34b4..381a82c5 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit+Queries.h +++ b/RCTAppleHealthKit/RCTAppleHealthKit+Queries.h @@ -27,8 +27,7 @@ limit:(NSUInteger)lim completion:(void (^)(NSArray *, NSError *))completion; - (void)setObserverForType:(HKSampleType *)quantityType - unit:(HKUnit *)unit - completion:(void (^)(NSArray *, NSError *))completion; + unit:(HKUnit *)unit; - (void)fetchQuantitySamplesOfType:(HKQuantityType *)quantityType diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Queries.m b/RCTAppleHealthKit/RCTAppleHealthKit+Queries.m index d84600ae..7e73b656 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit+Queries.m +++ b/RCTAppleHealthKit/RCTAppleHealthKit+Queries.m @@ -14,7 +14,6 @@ @implementation RCTAppleHealthKit (Queries) - - (void)fetchMostRecentQuantitySampleOfType:(HKQuantityType *)quantityType predicate:(NSPredicate *)predicate completion:(void (^)(HKQuantity *, NSDate *, NSDate *, NSError *))completion { @@ -203,58 +202,25 @@ - (void)fetchSamplesOfType:(HKSampleType *)type } - (void)setObserverForType:(HKSampleType *)type - unit:(HKUnit *)unit - completion:(void (^)(NSArray *, NSError *))completion { + unit:(HKUnit *)unit { NSLog(@"set observer"); - void(^handler)(HKObserverQuery *query, HKObserverQueryCompletionHandler completionHandler, NSError * _Nullable error); - handler = ^(HKObserverQuery *query, HKObserverQueryCompletionHandler completionHandler, NSError * _Nullable error) { - NSLog(@"enter to a handler %@", [error localizedDescription]); + HKObserverQuery *query = [[HKObserverQuery alloc] initWithSampleType:type predicate:nil updateHandler:^(HKObserverQuery *query, HKObserverQueryCompletionHandler completionHandler, NSError * _Nullable error){ UIApplication *app = [UIApplication sharedApplication]; - UIApplicationState appState = [app applicationState]; - - if (!self.isSync){ -// switch (appState) { -// case UIApplicationStateActive: -// NSLog(@"app Active try to make sync"); -// break; -// case UIApplicationStateInactive: -// { -// NSLog(@"enter to inactive case"); -// break; -// } -// case UIApplicationStateBackground: -// { -// NSLog(@"enter to background case"); -// self.isSync = true; -// __block UIBackgroundTaskIdentifier backgroundTaskIdentifier = [app beginBackgroundTaskWithExpirationHandler:^{ + NSLog(@"observer fired"); + [self.bridge.eventDispatcher sendAppEventWithName:@"observer" body:@""]; + completionHandler(); +// self.isSync = true; +// __block UIBackgroundTaskIdentifier backgroundTaskIdentifier = [app beginBackgroundTaskWithExpirationHandler:^{ // -// NSLog(@"call event background"); -//// [self.bridge.eventDispatcher sendAppEventWithName:@"change:steps" -//// body:@{@"name": @"change:steps"}]; -// [self fetchSamplesOfType:type unit:unit predicate:nil ascending:true limit:1 completion:completion]; -// [app endBackgroundTask:backgroundTaskIdentifier]; -// self.isSync = false; -// }]; -// } +// NSLog(@"observer fired from bg"); +// [self.bridge.eventDispatcher sendAppEventWithName:@"observer" +// body:@""]; // -// }; - - NSLog(@"enter to background case"); - self.isSync = true; - __block UIBackgroundTaskIdentifier backgroundTaskIdentifier = [app beginBackgroundTaskWithExpirationHandler:^{ - - NSLog(@"call event background"); - [self.bridge.eventDispatcher sendAppEventWithName:@"change:steps" - body:@{@"name": @"change:steps"}]; - [self fetchSamplesOfType:type unit:unit predicate:nil ascending:true limit:1 completion:completion]; - [app endBackgroundTask:backgroundTaskIdentifier]; - completionHandler(); - self.isSync = false; - }]; - } - - }; - HKObserverQuery *query = [[HKObserverQuery alloc] initWithSampleType:type predicate:nil updateHandler:handler]; +// [app endBackgroundTask:backgroundTaskIdentifier]; +// completionHandler(); +// self.isSync = false; +// }]; + }]; [self.healthStore executeQuery:query]; [self.healthStore enableBackgroundDeliveryForType:type frequency:HKUpdateFrequencyImmediate withCompletion:^(BOOL success, NSError * _Nullable error) { @@ -262,9 +228,6 @@ - (void)setObserverForType:(HKSampleType *)type }]; } - - - - (void)fetchSleepCategorySamplesForPredicate:(NSPredicate *)predicate limit:(NSUInteger)lim completion:(void (^)(NSArray *, NSError *))completion { diff --git a/RCTAppleHealthKit/RCTAppleHealthKit.m b/RCTAppleHealthKit/RCTAppleHealthKit.m index 2d1fa49e..bbc9c171 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit.m +++ b/RCTAppleHealthKit/RCTAppleHealthKit.m @@ -111,9 +111,9 @@ @implementation RCTAppleHealthKit [self fitness_getSamples:input callback:callback]; } -RCT_EXPORT_METHOD(setObserver:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback) +RCT_EXPORT_METHOD(setObserver:(NSDictionary *)input) { - [self fitness_setObserver:input callback:callback]; + [self fitness_setObserver:input]; } From 482edada5495ebf6ba169b7584e48368823cca5c Mon Sep 17 00:00:00 2001 From: Evgenii Evstropov Date: Wed, 14 Feb 2018 14:40:51 +0100 Subject: [PATCH 11/24] fields renaming --- RCTAppleHealthKit/RCTAppleHealthKit+Queries.m | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Queries.m b/RCTAppleHealthKit/RCTAppleHealthKit+Queries.m index 7e73b656..857d3bfb 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit+Queries.m +++ b/RCTAppleHealthKit/RCTAppleHealthKit+Queries.m @@ -147,15 +147,15 @@ - (void)fetchSamplesOfType:(HKSampleType *)type } NSDictionary *elem = @{ - @"type" : type, - @"energy" : @(energy), - @"isTracked" : @(isTracked), + @"activityName" : type, + @"calories" : @(energy), + @"tracked" : @(isTracked), @"sourceName" : [[[sample sourceRevision] source] name], - @"sourceBundleId" : [[[sample sourceRevision] source] bundleIdentifier], + @"sourceId" : [[[sample sourceRevision] source] bundleIdentifier], @"device": [[sample sourceRevision] productType], @"distance" : @(distance), - @"startDate" : startDateString, - @"endDate" : endDateString + @"start" : startDateString, + @"end" : endDateString }; [data addObject:elem]; @@ -174,13 +174,13 @@ - (void)fetchSamplesOfType:(HKSampleType *)type } NSDictionary *elem = @{ - @"value" : @(value), - @"isTracked" : @(isTracked), + @"quantity" : @(value), + @"tracked" : @(isTracked), @"sourceName" : [[[sample sourceRevision] source] name], - @"sourceBundleId" : [[[sample sourceRevision] source] bundleIdentifier], + @"sourceId" : [[[sample sourceRevision] source] bundleIdentifier], @"device": [[sample sourceRevision] productType], - @"startDate" : startDateString, - @"endDate" : endDateString + @"start" : startDateString, + @"end" : endDateString }; [data addObject:elem]; From 7108de7ae12f25b7ce3aecfe2c0f3ec8d08a313e Mon Sep 17 00:00:00 2001 From: Evgenii Evstropov Date: Wed, 14 Feb 2018 16:29:36 +0100 Subject: [PATCH 12/24] change activityName from string to int --- RCTAppleHealthKit/RCTAppleHealthKit+Queries.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Queries.m b/RCTAppleHealthKit/RCTAppleHealthKit+Queries.m index 857d3bfb..42d41e77 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit+Queries.m +++ b/RCTAppleHealthKit/RCTAppleHealthKit+Queries.m @@ -147,7 +147,7 @@ - (void)fetchSamplesOfType:(HKSampleType *)type } NSDictionary *elem = @{ - @"activityName" : type, + @"activityName" : [NSNumber numberWithInt:[sample workoutActivityType]], @"calories" : @(energy), @"tracked" : @(isTracked), @"sourceName" : [[[sample sourceRevision] source] name], From c4a2d59d0ed1777c34e63d0721c53410161cdc00 Mon Sep 17 00:00:00 2001 From: Evgenii Evstropov Date: Tue, 20 Feb 2018 12:12:50 +0100 Subject: [PATCH 13/24] detect if quantity type is mile that write it as a distance field --- RCTAppleHealthKit/RCTAppleHealthKit+Queries.m | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Queries.m b/RCTAppleHealthKit/RCTAppleHealthKit+Queries.m index 42d41e77..45f8720a 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit+Queries.m +++ b/RCTAppleHealthKit/RCTAppleHealthKit+Queries.m @@ -165,6 +165,11 @@ - (void)fetchSamplesOfType:(HKSampleType *)type HKQuantity *quantity = sample.quantity; double value = [quantity doubleValueForUnit:unit]; + NSString * valueType = @"quantity"; + if (unit == [HKUnit mileUnit]) { + valueType = @"distance"; + } + NSString *startDateString = [RCTAppleHealthKit buildISO8601StringFromDate:sample.startDate]; NSString *endDateString = [RCTAppleHealthKit buildISO8601StringFromDate:sample.endDate]; @@ -174,7 +179,7 @@ - (void)fetchSamplesOfType:(HKSampleType *)type } NSDictionary *elem = @{ - @"quantity" : @(value), + valueType : @(value), @"tracked" : @(isTracked), @"sourceName" : [[[sample sourceRevision] source] name], @"sourceId" : [[[sample sourceRevision] source] bundleIdentifier], From a28741e485fca2f1efbd4518b1a68bcbe13373a5 Mon Sep 17 00:00:00 2001 From: Evgenii Evstropov Date: Mon, 23 Apr 2018 22:52:57 +0200 Subject: [PATCH 14/24] change default units to metrics system --- RCTAppleHealthKit/RCTAppleHealthKit+Methods_Body.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Body.m b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Body.m index f29f7f84..49f826fa 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Body.m +++ b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Body.m @@ -19,7 +19,7 @@ - (void)body_getLatestWeight:(NSDictionary *)input callback:(RCTResponseSenderBl HKUnit *unit = [RCTAppleHealthKit hkUnitFromOptions:input]; if(unit == nil){ - unit = [HKUnit poundUnit]; + unit = [HKUnit gramUnit]; } [self fetchMostRecentQuantitySampleOfType:weightType @@ -154,7 +154,7 @@ - (void)body_getLatestHeight:(NSDictionary *)input callback:(RCTResponseSenderBl HKUnit *unit = [RCTAppleHealthKit hkUnitFromOptions:input]; if(unit == nil){ - unit = [HKUnit inchUnit]; + unit = [HKUnit meterUnit]; } [self fetchMostRecentQuantitySampleOfType:heightType From 836ee64fd73fefac259b5cd31fabb59532762204 Mon Sep 17 00:00:00 2001 From: Evgenii Evstropov Date: Tue, 24 Apr 2018 21:30:40 +0200 Subject: [PATCH 15/24] add more units --- .../RCTAppleHealthKit+Methods_Body.m | 1 - RCTAppleHealthKit/RCTAppleHealthKit+Utils.h | 1 - RCTAppleHealthKit/RCTAppleHealthKit+Utils.m | 61 +++---------------- 3 files changed, 9 insertions(+), 54 deletions(-) diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Body.m b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Body.m index 49f826fa..a64e3961 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Body.m +++ b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Body.m @@ -32,7 +32,6 @@ - (void)body_getLatestWeight:(NSDictionary *)input callback:(RCTResponseSenderBl else { // Determine the weight in the required unit. double usersWeight = [mostRecentQuantity doubleValueForUnit:unit]; - NSDictionary *response = @{ @"value" : @(usersWeight), @"startDate" : [RCTAppleHealthKit buildISO8601StringFromDate:startDate], diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Utils.h b/RCTAppleHealthKit/RCTAppleHealthKit+Utils.h index a78acc54..1f2df839 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit+Utils.h +++ b/RCTAppleHealthKit/RCTAppleHealthKit+Utils.h @@ -22,7 +22,6 @@ + (NSDate *)startDateFromOptions:(NSDictionary *)options; + (NSDate *)endDateFromOptions:(NSDictionary *)options; + (NSDate *)endDateFromOptionsDefaultNow:(NSDictionary *)options; -+ (HKUnit *)hkUnitFromOptions:(NSDictionary *)options; + (HKUnit *)hkUnitFromOptions:(NSDictionary *)options key:(NSString *)key withDefault:(HKUnit *)defaultValue; + (NSUInteger)uintFromOptions:(NSDictionary *)options key:(NSString *)key withDefault:(NSUInteger)defaultValue; diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Utils.m b/RCTAppleHealthKit/RCTAppleHealthKit+Utils.m index e1619800..505e9abe 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit+Utils.m +++ b/RCTAppleHealthKit/RCTAppleHealthKit+Utils.m @@ -123,58 +123,6 @@ + (NSDate *)endDateFromOptionsDefaultNow:(NSDictionary *)options { return date; } -// ========== -// DEPRECATED -// ========== -+ (HKUnit *)hkUnitFromOptions:(NSDictionary *)options { - NSString *unitString = [options objectForKey:@"unit"]; - HKUnit *theUnit; - - if([unitString isEqualToString:@"gram"]){ - theUnit = [HKUnit gramUnit]; - } - if([unitString isEqualToString:@"pound"]){ - theUnit = [HKUnit poundUnit]; - } - if([unitString isEqualToString:@"meter"]){ - theUnit = [HKUnit meterUnit]; - } - if([unitString isEqualToString:@"mile"]){ - theUnit = [HKUnit mileUnit]; - } - if([unitString isEqualToString:@"inch"]){ - theUnit = [HKUnit inchUnit]; - } - if([unitString isEqualToString:@"foot"]){ - theUnit = [HKUnit footUnit]; - } - if([unitString isEqualToString:@"second"]){ - theUnit = [HKUnit secondUnit]; - } - if([unitString isEqualToString:@"minute"]){ - theUnit = [HKUnit minuteUnit]; - } - if([unitString isEqualToString:@"hour"]){ - theUnit = [HKUnit hourUnit]; - } - if([unitString isEqualToString:@"day"]){ - theUnit = [HKUnit dayUnit]; - } - if([unitString isEqualToString:@"joule"]){ - theUnit = [HKUnit jouleUnit]; - } - if([unitString isEqualToString:@"calorie"]){ - theUnit = [HKUnit calorieUnit]; - } - if([unitString isEqualToString:@"count"]){ - theUnit = [HKUnit countUnit]; - } - if([unitString isEqualToString:@"percent"]){ - theUnit = [HKUnit percentUnit]; - } - return theUnit; -} - + (HKUnit *)hkUnitFromOptions:(NSDictionary *)options key:(NSString *)key withDefault:(HKUnit *)defaultValue { NSString *unitString = [options objectForKey:key]; @@ -183,12 +131,21 @@ + (HKUnit *)hkUnitFromOptions:(NSDictionary *)options key:(NSString *)key withDe if([unitString isEqualToString:@"gram"]){ theUnit = [HKUnit gramUnit]; } + if([unitString isEqualToString:@"kg"]){ + theUnit = [HKUnit gramUnitWithMetricPrefix:HKMetricPrefixKilo]; + } + if([unitString isEqualToString:@"stone"]){ + theUnit = [HKUnit stoneUnit]; + } if([unitString isEqualToString:@"pound"]){ theUnit = [HKUnit poundUnit]; } if([unitString isEqualToString:@"meter"]){ theUnit = [HKUnit meterUnit]; } + if([unitString isEqualToString:@"cm"]){ + theUnit = [HKUnit meterUnitWithMetricPrefix:HKMetricPrefixCenti]; + } if([unitString isEqualToString:@"inch"]){ theUnit = [HKUnit inchUnit]; } From 9c5f2734a008301b86f54b3ca07b89acf0c4ddcf Mon Sep 17 00:00:00 2001 From: Evgenii Evstropov Date: Tue, 24 Apr 2018 21:38:14 +0200 Subject: [PATCH 16/24] remove depricated usage --- RCTAppleHealthKit/RCTAppleHealthKit+Methods_Body.m | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Body.m b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Body.m index a64e3961..30788ab2 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Body.m +++ b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Body.m @@ -17,7 +17,7 @@ - (void)body_getLatestWeight:(NSDictionary *)input callback:(RCTResponseSenderBl { HKQuantityType *weightType = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierBodyMass]; - HKUnit *unit = [RCTAppleHealthKit hkUnitFromOptions:input]; + HKUnit *unit = [RCTAppleHealthKit hkUnitFromOptions:input key:@"unit" withDefault:[HKUnit gramUnitWithMetricPrefix:HKMetricPrefixKilo]]; if(unit == nil){ unit = [HKUnit gramUnit]; } @@ -151,7 +151,7 @@ - (void)body_getLatestHeight:(NSDictionary *)input callback:(RCTResponseSenderBl { HKQuantityType *heightType = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierHeight]; - HKUnit *unit = [RCTAppleHealthKit hkUnitFromOptions:input]; + HKUnit *unit = [RCTAppleHealthKit hkUnitFromOptions:input key:@"unit" withDefault:[HKUnit meterUnitWithMetricPrefix:HKMetricPrefixCenti]];; if(unit == nil){ unit = [HKUnit meterUnit]; } @@ -217,7 +217,7 @@ - (void)body_saveHeight:(NSDictionary *)input callback:(RCTResponseSenderBlock)c double height = [RCTAppleHealthKit doubleValueFromOptions:input]; NSDate *sampleDate = [RCTAppleHealthKit dateFromOptionsDefaultNow:input]; - HKUnit *heightUnit = [RCTAppleHealthKit hkUnitFromOptions:input]; + HKUnit *heightUnit = [RCTAppleHealthKit hkUnitFromOptions:input key:@"unit" withDefault:[HKUnit inchUnit]];; if(heightUnit == nil){ heightUnit = [HKUnit inchUnit]; } From 2178a8ed09eada555de35855d68144aa37e30263 Mon Sep 17 00:00:00 2001 From: Evgenii Evstropov Date: Fri, 11 May 2018 22:06:20 +0200 Subject: [PATCH 17/24] add function to check share(write) permissions authorisation --- .../RCTAppleHealthKit+TypesAndPermissions.h | 2 ++ .../RCTAppleHealthKit+TypesAndPermissions.m | 1 - RCTAppleHealthKit/RCTAppleHealthKit.h | 1 + RCTAppleHealthKit/RCTAppleHealthKit.m | 22 +++++++++++++++++++ 4 files changed, 25 insertions(+), 1 deletion(-) diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+TypesAndPermissions.h b/RCTAppleHealthKit/RCTAppleHealthKit+TypesAndPermissions.h index 73438fe4..f8e30475 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit+TypesAndPermissions.h +++ b/RCTAppleHealthKit/RCTAppleHealthKit+TypesAndPermissions.h @@ -10,6 +10,8 @@ @interface RCTAppleHealthKit (TypesAndPermissions) +- (NSDictionary *)readPermsDict; +- (NSDictionary *)writePermsDict; - (NSSet *)getReadPermsFromOptions:(NSArray *)options; - (NSSet *)getWritePermsFromOptions:(NSArray *)options; diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+TypesAndPermissions.m b/RCTAppleHealthKit/RCTAppleHealthKit+TypesAndPermissions.m index 70220812..3d43badb 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit+TypesAndPermissions.m +++ b/RCTAppleHealthKit/RCTAppleHealthKit+TypesAndPermissions.m @@ -83,7 +83,6 @@ - (NSDictionary *)writePermsDict { return writePerms; } - // Returns HealthKit read permissions from options array - (NSSet *)getReadPermsFromOptions:(NSArray *)options { NSDictionary *readPermDict = [self readPermsDict]; diff --git a/RCTAppleHealthKit/RCTAppleHealthKit.h b/RCTAppleHealthKit/RCTAppleHealthKit.h index 900c6e39..eadffd31 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit.h +++ b/RCTAppleHealthKit/RCTAppleHealthKit.h @@ -19,6 +19,7 @@ - (void)isHealthKitAvailable:(RCTResponseSenderBlock)callback; - (void)initializeHealthKit:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; +- (void)checkPermission:(NSString *)input callback:(RCTResponseSenderBlock)callback; - (void)getModuleInfo:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; @end diff --git a/RCTAppleHealthKit/RCTAppleHealthKit.m b/RCTAppleHealthKit/RCTAppleHealthKit.m index bbc9c171..d26a7080 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit.m +++ b/RCTAppleHealthKit/RCTAppleHealthKit.m @@ -36,6 +36,11 @@ @implementation RCTAppleHealthKit [self initializeHealthKit:input callback:callback]; } +RCT_EXPORT_METHOD(checkSharePermission:(NSString *)input callback:(RCTResponseSenderBlock)callback) +{ + [self checkPermission:input callback:callback]; +} + RCT_EXPORT_METHOD(initStepCountObserver:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback) { [self fitness_initializeStepEventObserver:input callback:callback]; @@ -248,6 +253,23 @@ - (void)initializeHealthKit:(NSDictionary *)input callback:(RCTResponseSenderBlo } } +- (void)checkPermission:(NSString *)input callback:(RCTResponseSenderBlock)callback +{ + self.healthStore = [[HKHealthStore alloc] init]; + if ([HKHealthStore isHealthDataAvailable]) { + + HKObjectType *val = [[self writePermsDict] objectForKey:input]; + + if ([self.healthStore authorizationStatusForType:val] == HKAuthorizationStatusSharingAuthorized) { + callback(@[[NSNull null], @true]); + } else { + callback(@[[NSNull null], @false]); + } + } else { + callback(@[RCTMakeError(@"HealthKit data is not available", nil, nil)]); + } +} + - (void)getModuleInfo:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback { NSDictionary *info = @{ From e3725593771f68deeaf701afef2b06aeb7c4bc47 Mon Sep 17 00:00:00 2001 From: Evgenii Evstropov Date: Fri, 18 May 2018 22:23:01 +0200 Subject: [PATCH 18/24] fix background workouts observer --- RCTAppleHealthKit/RCTAppleHealthKit+Queries.m | 27 +++++++++---------- RCTAppleHealthKit/RCTAppleHealthKit.m | 1 + 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Queries.m b/RCTAppleHealthKit/RCTAppleHealthKit+Queries.m index 45f8720a..b1d0e4ae 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit+Queries.m +++ b/RCTAppleHealthKit/RCTAppleHealthKit+Queries.m @@ -208,23 +208,20 @@ - (void)fetchSamplesOfType:(HKSampleType *)type - (void)setObserverForType:(HKSampleType *)type unit:(HKUnit *)unit { - NSLog(@"set observer"); HKObserverQuery *query = [[HKObserverQuery alloc] initWithSampleType:type predicate:nil updateHandler:^(HKObserverQuery *query, HKObserverQueryCompletionHandler completionHandler, NSError * _Nullable error){ - UIApplication *app = [UIApplication sharedApplication]; - NSLog(@"observer fired"); - [self.bridge.eventDispatcher sendAppEventWithName:@"observer" body:@""]; - completionHandler(); -// self.isSync = true; -// __block UIBackgroundTaskIdentifier backgroundTaskIdentifier = [app beginBackgroundTaskWithExpirationHandler:^{ -// -// NSLog(@"observer fired from bg"); -// [self.bridge.eventDispatcher sendAppEventWithName:@"observer" -// body:@""]; -// -// [app endBackgroundTask:backgroundTaskIdentifier]; + if (error) { + NSLog(@"*** An error occured while setting up the stepCount observer. %@ ***", error.localizedDescription); + return; + } + [self.bridge.eventDispatcher sendAppEventWithName:@"observer" body:@""]; + + // Theoretically, HealthKit expect that copletionHandler would be called at the end of query process, + // but it's unclear how to do in in event paradigm + +// dispatch_time_t delay = dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC * 5); +// dispatch_after(delay, dispatch_get_main_queue(), ^(void){ // completionHandler(); -// self.isSync = false; -// }]; +// }); }]; [self.healthStore executeQuery:query]; diff --git a/RCTAppleHealthKit/RCTAppleHealthKit.m b/RCTAppleHealthKit/RCTAppleHealthKit.m index d26a7080..41cd34e1 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit.m +++ b/RCTAppleHealthKit/RCTAppleHealthKit.m @@ -22,6 +22,7 @@ #import @implementation RCTAppleHealthKit + @synthesize bridge = _bridge; RCT_EXPORT_MODULE(); From 8365a5620ea08be9fde93b35f485a5c69b632136 Mon Sep 17 00:00:00 2001 From: Adam Ivancza Date: Tue, 2 Oct 2018 16:38:58 +0200 Subject: [PATCH 19/24] Fix for iOS 10 --- RCTAppleHealthKit/RCTAppleHealthKit+Queries.m | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Queries.m b/RCTAppleHealthKit/RCTAppleHealthKit+Queries.m index b1d0e4ae..dc4b572c 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit+Queries.m +++ b/RCTAppleHealthKit/RCTAppleHealthKit+Queries.m @@ -178,12 +178,22 @@ - (void)fetchSamplesOfType:(HKSampleType *)type isTracked = false; } + NSString* device = @""; + if (@available(iOS 11.0, *)) { + device = [[sample sourceRevision] productType]; + } else { + device = [[sample device] name]; + if (!device) { + device = @"iPhone"; + } + } + NSDictionary *elem = @{ valueType : @(value), @"tracked" : @(isTracked), @"sourceName" : [[[sample sourceRevision] source] name], @"sourceId" : [[[sample sourceRevision] source] bundleIdentifier], - @"device": [[sample sourceRevision] productType], + @"device": device, @"start" : startDateString, @"end" : endDateString }; From 0b536cff6d393b4805beaa2d4275173f58f487f0 Mon Sep 17 00:00:00 2001 From: Evgeny Evstropov Date: Sun, 23 Dec 2018 12:12:25 +0300 Subject: [PATCH 20/24] copy-right corrects. Decomposition. Fix error message. Fix difference between ios 11 and 10 --- .../RCTAppleHealthKit+Methods_Activity.h | 4 +- .../RCTAppleHealthKit+Methods_Activity.m | 4 +- .../RCTAppleHealthKit+Methods_Body.h | 3 +- .../RCTAppleHealthKit+Methods_Body.m | 3 +- ...RCTAppleHealthKit+Methods_Characteristic.h | 3 +- ...RCTAppleHealthKit+Methods_Characteristic.m | 3 +- .../RCTAppleHealthKit+Methods_Fitness.h | 3 +- .../RCTAppleHealthKit+Methods_Fitness.m | 37 ++++---------- .../RCTAppleHealthKit+Methods_Sleep.h | 3 +- .../RCTAppleHealthKit+Methods_Sleep.m | 3 +- RCTAppleHealthKit/RCTAppleHealthKit+Queries.h | 3 +- RCTAppleHealthKit/RCTAppleHealthKit+Queries.m | 48 +++++++++++-------- .../RCTAppleHealthKit+TypesAndPermissions.h | 3 +- .../RCTAppleHealthKit+TypesAndPermissions.m | 3 +- RCTAppleHealthKit/RCTAppleHealthKit+Utils.h | 4 +- RCTAppleHealthKit/RCTAppleHealthKit+Utils.m | 17 ++++++- RCTAppleHealthKit/RCTAppleHealthKit.h | 3 +- RCTAppleHealthKit/RCTAppleHealthKit.m | 3 +- 18 files changed, 85 insertions(+), 65 deletions(-) diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Activity.h b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Activity.h index 235e9c6b..5bdecf42 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Activity.h +++ b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Activity.h @@ -3,8 +3,10 @@ // RCTAppleHealthKit // // Created by Alexander Vallorosi on 4/27/17. -// Copyright © 2017 Alexander Vallorosi. All rights reserved. +// This source code is licensed under the MIT-style license found in the +// LICENSE file in the root directory of this source tree. // + #import "RCTAppleHealthKit.h" @interface RCTAppleHealthKit (Methods_Activity) diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Activity.m b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Activity.m index 03b2724c..eeb0d91d 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Activity.m +++ b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Activity.m @@ -3,8 +3,8 @@ // RCTAppleHealthKit // // Created by Alexander Vallorosi on 4/27/17. -// Copyright © 2017 Alexander Vallorosi. All rights reserved. -// +// This source code is licensed under the MIT-style license found in the +// LICENSE file in the root directory of this source tree. #import "RCTAppleHealthKit+Methods_Activity.h" #import "RCTAppleHealthKit+Queries.h" diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Body.h b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Body.h index 472829ca..08679742 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Body.h +++ b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Body.h @@ -3,7 +3,8 @@ // RCTAppleHealthKit // // Created by Greg Wilson on 2016-06-26. -// Copyright © 2016 Greg Wilson. All rights reserved. +// This source code is licensed under the MIT-style license found in the +// LICENSE file in the root directory of this source tree. // #import "RCTAppleHealthKit.h" diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Body.m b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Body.m index 7e8b7c69..5a29a898 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Body.m +++ b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Body.m @@ -3,7 +3,8 @@ // RCTAppleHealthKit // // Created by Greg Wilson on 2016-06-26. -// Copyright © 2016 Greg Wilson. All rights reserved. +// This source code is licensed under the MIT-style license found in the +// LICENSE file in the root directory of this source tree. // #import "RCTAppleHealthKit+Methods_Body.h" diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Characteristic.h b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Characteristic.h index 6c0adcce..0909ebef 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Characteristic.h +++ b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Characteristic.h @@ -3,7 +3,8 @@ // RCTAppleHealthKit // // Created by Greg Wilson on 2016-06-29. -// Copyright © 2016 Greg Wilson. All rights reserved. +// This source code is licensed under the MIT-style license found in the +// LICENSE file in the root directory of this source tree. // #import "RCTAppleHealthKit.h" diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Characteristic.m b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Characteristic.m index b7fb4f42..e030b856 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Characteristic.m +++ b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Characteristic.m @@ -3,7 +3,8 @@ // RCTAppleHealthKit // // Created by Greg Wilson on 2016-06-29. -// Copyright © 2016 Greg Wilson. All rights reserved. +// This source code is licensed under the MIT-style license found in the +// LICENSE file in the root directory of this source tree. // #import "RCTAppleHealthKit+Methods_Characteristic.h" diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Fitness.h b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Fitness.h index dcc0238f..51449f86 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Fitness.h +++ b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Fitness.h @@ -3,7 +3,8 @@ // RCTAppleHealthKit // // Created by Greg Wilson on 2016-06-26. -// Copyright © 2016 Greg Wilson. All rights reserved. +// This source code is licensed under the MIT-style license found in the +// LICENSE file in the root directory of this source tree. // #import "RCTAppleHealthKit.h" diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Fitness.m b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Fitness.m index 8fd935ca..9f0e5e24 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Fitness.m +++ b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Fitness.m @@ -3,7 +3,8 @@ // RCTAppleHealthKit // // Created by Greg Wilson on 2016-06-26. -// Copyright © 2016 Greg Wilson. All rights reserved. +// This source code is licensed under the MIT-style license found in the +// LICENSE file in the root directory of this source tree. // #import "RCTAppleHealthKit+Methods_Fitness.h" @@ -59,21 +60,11 @@ - (void)fitness_getSamples:(NSDictionary *)input callback:(RCTResponseSenderBloc NSPredicate *predicate = [HKQuery predicateForSamplesWithStartDate:startDate endDate:endDate options:HKQueryOptionStrictStartDate]; - HKSampleType *samplesType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierStepCount]; - if ([type isEqual:@"Walking"]) { - samplesType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierStepCount]; - } else if ([type isEqual:@"StairClimbing"]) { - samplesType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierFlightsClimbed]; - } else if ([type isEqual:@"Running"]){ - samplesType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierDistanceWalkingRunning]; + HKSampleType *samplesType = [RCTAppleHealthKit hkQuantityTypeFromString:type]; + if ([type isEqual:@"Running"] || [type isEqual:@"Cycling"]) { unit = [HKUnit mileUnit]; - } else if ([type isEqual:@"Cycling"]){ - samplesType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierDistanceCycling]; - unit = [HKUnit mileUnit]; - } else if ([type isEqual:@"Workout"]){ - samplesType = [HKObjectType workoutType]; } - + NSLog(@"error getting samples: %@", [samplesType identifier]); [self fetchSamplesOfType:samplesType unit:unit predicate:predicate @@ -84,8 +75,8 @@ - (void)fitness_getSamples:(NSDictionary *)input callback:(RCTResponseSenderBloc callback(@[[NSNull null], results]); return; } else { - NSLog(@"error getting active energy burned samples: %@", error); - callback(@[RCTMakeError(@"error getting active energy burned samples", nil, nil)]); + NSLog(@"error getting samples: %@", error); + callback(@[RCTMakeError(@"error getting samples", nil, nil)]); return; } }]; @@ -96,19 +87,9 @@ - (void)fitness_setObserver:(NSDictionary *)input HKUnit *unit = [RCTAppleHealthKit hkUnitFromOptions:input key:@"unit" withDefault:[HKUnit countUnit]]; NSString *type = [RCTAppleHealthKit stringFromOptions:input key:@"type" withDefault:@"Walking"]; - HKSampleType *samplesType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierStepCount]; - if ([type isEqual:@"Walking"]) { - samplesType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierStepCount]; - } else if ([type isEqual:@"StairClimbing"]) { - samplesType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierFlightsClimbed]; - } else if ([type isEqual:@"Running"]){ - samplesType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierDistanceWalkingRunning]; - unit = [HKUnit mileUnit]; - } else if ([type isEqual:@"Cycling"]){ - samplesType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierDistanceCycling]; + HKSampleType *samplesType = [RCTAppleHealthKit hkQuantityTypeFromString:type]; + if ([type isEqual:@"Running"] || [type isEqual:@"Cycling"]) { unit = [HKUnit mileUnit]; - } else if ([type isEqual:@"Workout"]){ - samplesType = [HKObjectType workoutType]; } [self setObserverForType:samplesType unit:unit]; diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Sleep.h b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Sleep.h index 3afd6d9f..cb71012d 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Sleep.h +++ b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Sleep.h @@ -3,7 +3,8 @@ // RCTAppleHealthKit // // Created by Greg Wilson on 2016-11-06. -// Copyright © 2016 Greg Wilson. All rights reserved. +// This source code is licensed under the MIT-style license found in the +// LICENSE file in the root directory of this source tree. // #import "RCTAppleHealthKit.h" diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Sleep.m b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Sleep.m index 4b1898f8..faba4ed1 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Sleep.m +++ b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Sleep.m @@ -3,7 +3,8 @@ // RCTAppleHealthKit // // Created by Greg Wilson on 2016-11-06. -// Copyright © 2016 Greg Wilson. All rights reserved. +// This source code is licensed under the MIT-style license found in the +// LICENSE file in the root directory of this source tree. // diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Queries.h b/RCTAppleHealthKit/RCTAppleHealthKit+Queries.h index 381a82c5..172152b6 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit+Queries.h +++ b/RCTAppleHealthKit/RCTAppleHealthKit+Queries.h @@ -3,7 +3,8 @@ // RCTAppleHealthKit // // Created by Greg Wilson on 2016-06-26. -// Copyright © 2016 Greg Wilson. All rights reserved. +// This source code is licensed under the MIT-style license found in the +// LICENSE file in the root directory of this source tree. // #import "RCTAppleHealthKit.h" diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Queries.m b/RCTAppleHealthKit/RCTAppleHealthKit+Queries.m index dc4b572c..11ea768c 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit+Queries.m +++ b/RCTAppleHealthKit/RCTAppleHealthKit+Queries.m @@ -3,7 +3,8 @@ // RCTAppleHealthKit // // Created by Greg Wilson on 2016-06-26. -// Copyright © 2016 Greg Wilson. All rights reserved. +// This source code is licensed under the MIT-style license found in the +// LICENSE file in the root directory of this source tree. // #import "RCTAppleHealthKit+Queries.h" @@ -56,10 +57,10 @@ - (void)fetchQuantitySamplesOfType:(HKQuantityType *)quantityType ascending:(BOOL)asc limit:(NSUInteger)lim completion:(void (^)(NSArray *, NSError *))completion { - + NSSortDescriptor *timeSortDescriptor = [[NSSortDescriptor alloc] initWithKey:HKSampleSortIdentifierEndDate ascending:asc]; - + // declare the block void (^handlerBlock)(HKSampleQuery *query, NSArray *results, NSError *error); // create and assign the block @@ -70,44 +71,42 @@ - (void)fetchQuantitySamplesOfType:(HKQuantityType *)quantityType } return; } - + if (completion) { NSMutableArray *data = [NSMutableArray arrayWithCapacity:1]; - + dispatch_async(dispatch_get_main_queue(), ^{ - + for (HKQuantitySample *sample in results) { HKQuantity *quantity = sample.quantity; double value = [quantity doubleValueForUnit:unit]; - + NSString *startDateString = [RCTAppleHealthKit buildISO8601StringFromDate:sample.startDate]; NSString *endDateString = [RCTAppleHealthKit buildISO8601StringFromDate:sample.endDate]; - + NSDictionary *elem = @{ - @"value" : @(value), - @"startDate" : startDateString, - @"endDate" : endDateString, - }; - + @"value" : @(value), + @"startDate" : startDateString, + @"endDate" : endDateString, + }; + [data addObject:elem]; } - + completion(data, error); }); } }; - + HKSampleQuery *query = [[HKSampleQuery alloc] initWithSampleType:quantityType predicate:predicate limit:lim sortDescriptors:@[timeSortDescriptor] resultsHandler:handlerBlock]; - + [self.healthStore executeQuery:query]; } - - - (void)fetchSamplesOfType:(HKSampleType *)type unit:(HKUnit *)unit predicate:(NSPredicate *)predicate @@ -146,13 +145,23 @@ - (void)fetchSamplesOfType:(HKSampleType *)type isTracked = false; } + NSString* device = @""; + if (@available(iOS 11.0, *)) { + device = [[sample sourceRevision] productType]; + } else { + device = [[sample device] name]; + if (!device) { + device = @"iPhone"; + } + } + NSDictionary *elem = @{ @"activityName" : [NSNumber numberWithInt:[sample workoutActivityType]], @"calories" : @(energy), @"tracked" : @(isTracked), @"sourceName" : [[[sample sourceRevision] source] name], @"sourceId" : [[[sample sourceRevision] source] bundleIdentifier], - @"device": [[sample sourceRevision] productType], + @"device": device, @"distance" : @(distance), @"start" : startDateString, @"end" : endDateString @@ -244,7 +253,6 @@ - (void)fetchSleepCategorySamplesForPredicate:(NSPredicate *)predicate limit:(NSUInteger)lim completion:(void (^)(NSArray *, NSError *))completion { - NSSortDescriptor *timeSortDescriptor = [[NSSortDescriptor alloc] initWithKey:HKSampleSortIdentifierEndDate ascending:false]; diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+TypesAndPermissions.h b/RCTAppleHealthKit/RCTAppleHealthKit+TypesAndPermissions.h index f8e30475..d69b7e95 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit+TypesAndPermissions.h +++ b/RCTAppleHealthKit/RCTAppleHealthKit+TypesAndPermissions.h @@ -3,7 +3,8 @@ // RCTAppleHealthKit // // Created by Greg Wilson on 2016-06-26. -// Copyright © 2016 Greg Wilson. All rights reserved. +// This source code is licensed under the MIT-style license found in the +// LICENSE file in the root directory of this source tree. // #import "RCTAppleHealthKit.h" diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+TypesAndPermissions.m b/RCTAppleHealthKit/RCTAppleHealthKit+TypesAndPermissions.m index 39e880f6..6cb5a058 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit+TypesAndPermissions.m +++ b/RCTAppleHealthKit/RCTAppleHealthKit+TypesAndPermissions.m @@ -3,7 +3,8 @@ // RCTAppleHealthKit // // Created by Greg Wilson on 2016-06-26. -// Copyright © 2016 Greg Wilson. All rights reserved. +// This source code is licensed under the MIT-style license found in the +// LICENSE file in the root directory of this source tree. // #import "RCTAppleHealthKit+TypesAndPermissions.h" diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Utils.h b/RCTAppleHealthKit/RCTAppleHealthKit+Utils.h index 1f2df839..7d00c782 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit+Utils.h +++ b/RCTAppleHealthKit/RCTAppleHealthKit+Utils.h @@ -3,7 +3,8 @@ // RCTAppleHealthKit // // Created by Greg Wilson on 2016-06-26. -// Copyright © 2016 Greg Wilson. All rights reserved. +// This source code is licensed under the MIT-style license found in the +// LICENSE file in the root directory of this source tree. // #import "RCTAppleHealthKit.h" @@ -22,6 +23,7 @@ + (NSDate *)startDateFromOptions:(NSDictionary *)options; + (NSDate *)endDateFromOptions:(NSDictionary *)options; + (NSDate *)endDateFromOptionsDefaultNow:(NSDictionary *)options; ++ (HKSampleType *)hkQuantityTypeFromString:(NSString *)type; + (HKUnit *)hkUnitFromOptions:(NSDictionary *)options key:(NSString *)key withDefault:(HKUnit *)defaultValue; + (NSUInteger)uintFromOptions:(NSDictionary *)options key:(NSString *)key withDefault:(NSUInteger)defaultValue; diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Utils.m b/RCTAppleHealthKit/RCTAppleHealthKit+Utils.m index 505e9abe..8a0c22b8 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit+Utils.m +++ b/RCTAppleHealthKit/RCTAppleHealthKit+Utils.m @@ -3,7 +3,8 @@ // RCTAppleHealthKit // // Created by Greg Wilson on 2016-06-26. -// Copyright © 2016 Greg Wilson. All rights reserved. +// This source code is licensed under the MIT-style license found in the +// LICENSE file in the root directory of this source tree. // #import "RCTAppleHealthKit+Utils.h" @@ -123,6 +124,20 @@ + (NSDate *)endDateFromOptionsDefaultNow:(NSDictionary *)options { return date; } ++ (HKSampleType *)hkQuantityTypeFromString:(NSString *)type { + if ([type isEqual:@"Walking"]) { + return [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierStepCount]; + } else if ([type isEqual:@"StairClimbing"]) { + return [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierFlightsClimbed]; + } else if ([type isEqual:@"Running"]){ + return [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierDistanceWalkingRunning]; + } else if ([type isEqual:@"Cycling"]){ + return [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierDistanceCycling]; + } + // default [type isEqual:@"Workout"]) + return [HKObjectType workoutType]; +} + + (HKUnit *)hkUnitFromOptions:(NSDictionary *)options key:(NSString *)key withDefault:(HKUnit *)defaultValue { NSString *unitString = [options objectForKey:key]; diff --git a/RCTAppleHealthKit/RCTAppleHealthKit.h b/RCTAppleHealthKit/RCTAppleHealthKit.h index eadffd31..6ccbe26b 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit.h +++ b/RCTAppleHealthKit/RCTAppleHealthKit.h @@ -3,7 +3,8 @@ // RCTAppleHealthKit // // Created by Greg Wilson on 2016-06-26. -// Copyright © 2016 Greg Wilson. All rights reserved. +// This source code is licensed under the MIT-style license found in the +// LICENSE file in the root directory of this source tree. // #import diff --git a/RCTAppleHealthKit/RCTAppleHealthKit.m b/RCTAppleHealthKit/RCTAppleHealthKit.m index 90e7872d..5ef4eccc 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit.m +++ b/RCTAppleHealthKit/RCTAppleHealthKit.m @@ -3,7 +3,8 @@ // RCTAppleHealthKit // // Created by Greg Wilson on 2016-06-26. -// Copyright © 2016 Greg Wilson. All rights reserved. +// This source code is licensed under the MIT-style license found in the +// LICENSE file in the root directory of this source tree. // #import "RCTAppleHealthKit.h" From 531e1b3234e7430b1c3cbfa53ffb2411b1e2a4f4 Mon Sep 17 00:00:00 2001 From: Evgeny Evstropov Date: Tue, 5 Feb 2019 14:45:15 +0100 Subject: [PATCH 21/24] update docs, change one of the returning key from getSamples --- RCTAppleHealthKit/RCTAppleHealthKit+Queries.m | 2 +- README.md | 3 ++ docs/getSamples().md | 52 +++++++++++++++++++ docs/setObserverForType().md | 15 ++++++ 4 files changed, 71 insertions(+), 1 deletion(-) create mode 100644 docs/getSamples().md create mode 100644 docs/setObserverForType().md diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Queries.m b/RCTAppleHealthKit/RCTAppleHealthKit+Queries.m index 11ea768c..fdbaea39 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit+Queries.m +++ b/RCTAppleHealthKit/RCTAppleHealthKit+Queries.m @@ -156,7 +156,7 @@ - (void)fetchSamplesOfType:(HKSampleType *)type } NSDictionary *elem = @{ - @"activityName" : [NSNumber numberWithInt:[sample workoutActivityType]], + @"activityNameId" : [NSNumber numberWithInt:[sample workoutActivityType]], @"calories" : @(energy), @"tracked" : @(isTracked), @"sourceName" : [[[sample sourceRevision] source] name], diff --git a/README.md b/README.md index 0a385f8a..9a402e8c 100644 --- a/README.md +++ b/README.md @@ -100,8 +100,10 @@ AppleHealthKit.initHealthKit(options: Object, (err: string, results: Object) => * Base Methods * [isAvailable](/docs/isAvailable().md) * [initHealthKit](/docs/initHealthKit().md) + * checkSharePermission * Realtime Methods * [initStepCountObserver](/docs/initStepCountObserver().md) + * [setObserverForType](/docs/setObserverForType().md) * Read Methods * [getActiveEnergyBurned](/docs/getActiveEnergyBurned().md) * [getBasalEnergyBurned](/docs/getBasalEnergyBurned().md) @@ -128,6 +130,7 @@ AppleHealthKit.initHealthKit(options: Object, (err: string, results: Object) => * [getSleepSamples](/docs/getsleepsamples().md) * [getStepCount](/docs/getStepCount().md) * [getWeightSamples](/docs/getweightsamples().md) + * [getSamples](docs/getSamples().md) * Write Methods * [saveBmi](/docs/savebmi().md) * [saveHeight](/docs/saveheight().md) diff --git a/docs/getSamples().md b/docs/getSamples().md new file mode 100644 index 00000000..8d7f6510 --- /dev/null +++ b/docs/getSamples().md @@ -0,0 +1,52 @@ +Query to get all activities of given type with extended information about it. + +```javascript 1.7 +let options = { + startDate: (new Date(2016,4,27)).toISOString(), + endDate: (new Date()).toISOString(), + type: 'Walking', // one of: ['Walking', 'StairClimbing', 'Running', 'Cycling', 'Workout'] +}; +``` + +The callback function will be called with a `samples` array containing objects with *value*, *startDate*, and *endDate* fields + +```javascript 1.7 +AppleHealthKit.getSamples(options, (err: Object, results: Array) => { + if (err) { + return; + } + console.log(results) +}); +``` + +Resulting object has different fields for different types. +In case of workout: +``` +{ + activityNameId: Number, // [NSNumber numberWithInt:[sample workoutActivityType]] + calories: Number, // [[sample totalEnergyBurned] doubleValueForUnit:[HKUnit kilocalorieUnit]] + tracked: Boolean, // [[sample metadata][HKMetadataKeyWasUserEntered] intValue] !== 1 + sourceName: String, // [[[sample sourceRevision] source] name] + sourceId: String, // [[[sample sourceRevision] source] bundleIdentifier] + device: String, // [[sample sourceRevision] productType] or 'iPhone' + distance: Number, // [[sample totalDistance] doubleValueForUnit:[HKUnit mileUnit]] + start: String, // [RCTAppleHealthKit buildISO8601StringFromDate:sample.startDate]; + end: String, // [RCTAppleHealthKit buildISO8601StringFromDate:sample.endDate]; +} +``` +for other types: +``` +{ + activityNameId: Number, // [NSNumber numberWithInt:[sample workoutActivityType]] + tracked: Boolean, // [[sample metadata][HKMetadataKeyWasUserEntered] intValue] !== 1 + sourceName: String, // [[[sample sourceRevision] source] name] + sourceId: String, // [[[sample sourceRevision] source] bundleIdentifier] + device: String, // [[sample sourceRevision] productType] or 'iPhone' + start: String, // [RCTAppleHealthKit buildISO8601StringFromDate:sample.startDate]; + end: String, // [RCTAppleHealthKit buildISO8601StringFromDate:sample.endDate]; + + //based on required type, one of the following will be present. + distance: Number, // [[sample totalDistance] doubleValueForUnit:[HKUnit mileUnit]] + calories: Number, // [[sample totalEnergyBurned] doubleValueForUnit:[HKUnit kilocalorieUnit]] +} +``` diff --git a/docs/setObserverForType().md b/docs/setObserverForType().md new file mode 100644 index 00000000..8f551613 --- /dev/null +++ b/docs/setObserverForType().md @@ -0,0 +1,15 @@ +Will listen for any updates in a given type data in healthKit and call app. + +type - one of the `['Walking', 'StairClimbing', 'Running', 'Cycling', 'Workout']` +```javascript 1.8 +import { NativeAppEventEmitter } from 'react-native'; +//...// +AppleHealthKit.setObserver({ type: 'Walking' }); +NativeAppEventEmitter.addListener( + 'observer', + callback + ); +``` + +So, callback would be call when new data of given type appears. When it happens, in order to get new info +need to call getSamples() function with proper arguments. From 3f9198745b79662558f7a29b09fffb69c0eb0dbc Mon Sep 17 00:00:00 2001 From: Evgeny Evstropov Date: Tue, 5 Feb 2019 14:49:45 +0100 Subject: [PATCH 22/24] fix typo --- README.md | 2 +- docs/{setObserverForType().md => setObserver().md} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename docs/{setObserverForType().md => setObserver().md} (100%) diff --git a/README.md b/README.md index 9a402e8c..6c29d920 100644 --- a/README.md +++ b/README.md @@ -103,7 +103,7 @@ AppleHealthKit.initHealthKit(options: Object, (err: string, results: Object) => * checkSharePermission * Realtime Methods * [initStepCountObserver](/docs/initStepCountObserver().md) - * [setObserverForType](/docs/setObserverForType().md) + * [setObserver](/docs/setObserver().md) * Read Methods * [getActiveEnergyBurned](/docs/getActiveEnergyBurned().md) * [getBasalEnergyBurned](/docs/getBasalEnergyBurned().md) diff --git a/docs/setObserverForType().md b/docs/setObserver().md similarity index 100% rename from docs/setObserverForType().md rename to docs/setObserver().md From 61a1e7c255201dc51b0690b348af7bc3bf4cf537 Mon Sep 17 00:00:00 2001 From: Evgeny Evstropov Date: Tue, 26 Feb 2019 20:03:07 +0100 Subject: [PATCH 23/24] change back default to imperial system, add activity name field, fix docs --- .../RCTAppleHealthKit+Methods_Body.m | 19 ++-------- RCTAppleHealthKit/RCTAppleHealthKit+Queries.m | 3 +- README.md | 38 +++++++++---------- docs/getSamples().md | 4 +- 4 files changed, 27 insertions(+), 37 deletions(-) diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Body.m b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Body.m index 5a29a898..34fd3288 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Body.m +++ b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Body.m @@ -18,11 +18,8 @@ - (void)body_getLatestWeight:(NSDictionary *)input callback:(RCTResponseSenderBl { HKQuantityType *weightType = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierBodyMass]; - HKUnit *unit = [RCTAppleHealthKit hkUnitFromOptions:input key:@"unit" withDefault:[HKUnit gramUnitWithMetricPrefix:HKMetricPrefixKilo]]; - if(unit == nil){ - unit = [HKUnit gramUnit]; - } - + HKUnit *unit = [RCTAppleHealthKit hkUnitFromOptions:input key:@"unit" withDefault:[HKUnit poundUnit]]; + [self fetchMostRecentQuantitySampleOfType:weightType predicate:nil completion:^(HKQuantity *mostRecentQuantity, NSDate *startDate, NSDate *endDate, NSError *error) { @@ -151,11 +148,7 @@ - (void)body_saveBodyMassIndex:(NSDictionary *)input callback:(RCTResponseSender - (void)body_getLatestHeight:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback { HKQuantityType *heightType = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierHeight]; - - HKUnit *unit = [RCTAppleHealthKit hkUnitFromOptions:input key:@"unit" withDefault:[HKUnit meterUnitWithMetricPrefix:HKMetricPrefixCenti]];; - if(unit == nil){ - unit = [HKUnit meterUnit]; - } + HKUnit *unit = [RCTAppleHealthKit hkUnitFromOptions:input key:@"unit" withDefault:[HKUnit inchUnit]];; [self fetchMostRecentQuantitySampleOfType:heightType predicate:nil @@ -217,11 +210,7 @@ - (void)body_saveHeight:(NSDictionary *)input callback:(RCTResponseSenderBlock)c { double height = [RCTAppleHealthKit doubleValueFromOptions:input]; NSDate *sampleDate = [RCTAppleHealthKit dateFromOptionsDefaultNow:input]; - - HKUnit *heightUnit = [RCTAppleHealthKit hkUnitFromOptions:input key:@"unit" withDefault:[HKUnit inchUnit]];; - if(heightUnit == nil){ - heightUnit = [HKUnit inchUnit]; - } + HKUnit *heightUnit = [RCTAppleHealthKit hkUnitFromOptions:input key:@"unit" withDefault:[HKUnit inchUnit]]; HKQuantity *heightQuantity = [HKQuantity quantityWithUnit:heightUnit doubleValue:height]; HKQuantityType *heightType = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierHeight]; diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Queries.m b/RCTAppleHealthKit/RCTAppleHealthKit+Queries.m index fdbaea39..f18ceb36 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit+Queries.m +++ b/RCTAppleHealthKit/RCTAppleHealthKit+Queries.m @@ -156,7 +156,8 @@ - (void)fetchSamplesOfType:(HKSampleType *)type } NSDictionary *elem = @{ - @"activityNameId" : [NSNumber numberWithInt:[sample workoutActivityType]], + @"activityId" : [NSNumber numberWithInt:[sample workoutActivityType]], + @"activityName" : type, @"calories" : @(energy), @"tracked" : @(isTracked), @"sourceName" : [[[sample sourceRevision] source] name], diff --git a/README.md b/README.md index 6c29d920..409d745e 100644 --- a/README.md +++ b/README.md @@ -108,34 +108,34 @@ AppleHealthKit.initHealthKit(options: Object, (err: string, results: Object) => * [getActiveEnergyBurned](/docs/getActiveEnergyBurned().md) * [getBasalEnergyBurned](/docs/getBasalEnergyBurned().md) * [getBiologicalSex](/docs/getBiologicalSex().md) - * [getBloodGlucoseSamples](/docs/getbloodglucosesamples().md) - * [getBloodPressureSamples](/docs/getbloodpressuresamples().md) - * [getBodyTemperatureSamples](/docs/getbodytemperaturesamples().md) - * [getDailyDistanceCyclingSamples]() + * [getBloodGlucoseSamples](/docs/getBloodglucoseSamples().md) + * [getBloodPressureSamples](/docs/getBloodPressureSamples().md) + * [getBodyTemperatureSamples](/docs/getBodyTemperatureSamples().md) + * [getDailyDistanceCyclingSamples](/docs/getDailyDistanceCyclingSamples().md) * [getDailyDistanceWalkingRunningSamples](/docs/getDailyDistanceWalkingRunningSamples().md) * [getDailyFlightsClimbedSamples](/docs/getDailyFlightsClimbedSamples().md) * [getDailyStepCountSamples](/docs/getDailyStepCountSamples().md) * [getDateOfBirth](/docs/getDateOfBirth().md) - * [getDistanceCycling](/docs/getdistancecycling().md) + * [getDistanceCycling](/docs/getDistanceCycling().md) * [getDistanceWalkingRunning](/docs/getDistanceWalkingRunning().md) - * [getFlightsClimbed](/docs/getflightsclimbed().md) - * [getHeartRateSamples](/docs/getheartratesamples().md) - * [getHeightSamples](/docs/getheightsamples().md) - * [getLatestBmi](/docs/getlatestbmi().md) - * [getLatestBodyFatPercentage](/docs/getlatestbodyfatpercentage().md) - * [getLatestHeight](/docs/getlatestheight().md) - * [getLatestLeanBodyMass](/docs/getlatestleanbodymass().md) - * [getLatestWeight](/docs/getlatestweight().md) - * [getRespiratoryRateSamples](/docs/getrespiratoryratesamples().md) - * [getSleepSamples](/docs/getsleepsamples().md) + * [getFlightsClimbed](/docs/getFlightsClimbed().md) + * [getHeartRateSamples](/docs/getHeartRateSamples().md) + * [getHeightSamples](/docs/getHeightSamples().md) + * [getLatestBmi](/docs/getLatestBmi().md) + * [getLatestBodyFatPercentage](/docs/getLatestBodyFatPercentage().md) + * [getLatestHeight](/docs/getLatestHeight().md) + * [getLatestLeanBodyMass](/docs/getLatestLeanBodyMass().md) + * [getLatestWeight](/docs/getLatestWeight().md) + * [getRespiratoryRateSamples](/docs/getRespiratoryRateSamples().md) + * [getSleepSamples](/docs/getSleepSamples().md) * [getStepCount](/docs/getStepCount().md) - * [getWeightSamples](/docs/getweightsamples().md) + * [getWeightSamples](/docs/getWeightSamples().md) * [getSamples](docs/getSamples().md) * Write Methods - * [saveBmi](/docs/savebmi().md) - * [saveHeight](/docs/saveheight().md) + * [saveBmi](/docs/saveBmi().md) + * [saveHeight](/docs/saveHeight().md) * [saveMindfulSession](/docs/saveMindfulSession().md) - * [saveWeight](/docs/saveweight().md) + * [saveWeight](/docs/saveWeight().md) * [saveSteps](/docs/saveSteps().md) * [References](#references) diff --git a/docs/getSamples().md b/docs/getSamples().md index 8d7f6510..a4c6cc68 100644 --- a/docs/getSamples().md +++ b/docs/getSamples().md @@ -23,7 +23,8 @@ Resulting object has different fields for different types. In case of workout: ``` { - activityNameId: Number, // [NSNumber numberWithInt:[sample workoutActivityType]] + activityId: Number, // [NSNumber numberWithInt:[sample workoutActivityType]] + activityName: Number, // [RCTAppleHealthKit stringForHKWorkoutActivityType:[sample workoutActivityType]] calories: Number, // [[sample totalEnergyBurned] doubleValueForUnit:[HKUnit kilocalorieUnit]] tracked: Boolean, // [[sample metadata][HKMetadataKeyWasUserEntered] intValue] !== 1 sourceName: String, // [[[sample sourceRevision] source] name] @@ -37,7 +38,6 @@ In case of workout: for other types: ``` { - activityNameId: Number, // [NSNumber numberWithInt:[sample workoutActivityType]] tracked: Boolean, // [[sample metadata][HKMetadataKeyWasUserEntered] intValue] !== 1 sourceName: String, // [[[sample sourceRevision] source] name] sourceId: String, // [[[sample sourceRevision] source] bundleIdentifier] From 181f4faa49c04a2cf7fc7be38dcf8677a13ddd62 Mon Sep 17 00:00:00 2001 From: Evgeny Evstropov Date: Tue, 26 Feb 2019 20:12:16 +0100 Subject: [PATCH 24/24] remove checkPermission functions in order to use from PR #69 --- RCTAppleHealthKit/RCTAppleHealthKit.m | 22 ---------------------- README.md | 1 - 2 files changed, 23 deletions(-) diff --git a/RCTAppleHealthKit/RCTAppleHealthKit.m b/RCTAppleHealthKit/RCTAppleHealthKit.m index 5ef4eccc..c91c4713 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit.m +++ b/RCTAppleHealthKit/RCTAppleHealthKit.m @@ -39,11 +39,6 @@ @implementation RCTAppleHealthKit [self initializeHealthKit:input callback:callback]; } -RCT_EXPORT_METHOD(checkSharePermission:(NSString *)input callback:(RCTResponseSenderBlock)callback) -{ - [self checkPermission:input callback:callback]; -} - RCT_EXPORT_METHOD(initStepCountObserver:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback) { [self fitness_initializeStepEventObserver:input callback:callback]; @@ -286,23 +281,6 @@ - (void)initializeHealthKit:(NSDictionary *)input callback:(RCTResponseSenderBlo } } -- (void)checkPermission:(NSString *)input callback:(RCTResponseSenderBlock)callback -{ - self.healthStore = [[HKHealthStore alloc] init]; - if ([HKHealthStore isHealthDataAvailable]) { - - HKObjectType *val = [[self writePermsDict] objectForKey:input]; - - if ([self.healthStore authorizationStatusForType:val] == HKAuthorizationStatusSharingAuthorized) { - callback(@[[NSNull null], @true]); - } else { - callback(@[[NSNull null], @false]); - } - } else { - callback(@[RCTMakeError(@"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 409d745e..170a40c4 100644 --- a/README.md +++ b/README.md @@ -100,7 +100,6 @@ AppleHealthKit.initHealthKit(options: Object, (err: string, results: Object) => * Base Methods * [isAvailable](/docs/isAvailable().md) * [initHealthKit](/docs/initHealthKit().md) - * checkSharePermission * Realtime Methods * [initStepCountObserver](/docs/initStepCountObserver().md) * [setObserver](/docs/setObserver().md)