diff --git a/Constants/Permissions.js b/Constants/Permissions.js index 4d2fdc273e2821d338a08d05673543ae930f71ff..d54f0b8559464e90ff7893b2963592b259c860af 100644 --- a/Constants/Permissions.js +++ b/Constants/Permissions.js @@ -55,6 +55,7 @@ export const Permissions = { Zinc: "Zinc", Water: "Water", DistanceCycling: "DistanceCycling", + DistanceSwimming: "DistanceSwimming", DistanceWalkingRunning: "DistanceWalkingRunning", FlightsClimbed: "FlightsClimbed", HeartRate: "HeartRate", diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Fitness.h b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Fitness.h index 51449f864e2fecdb5aaa0eab201b316b5aefe0a9..d4a8152a4975e2b09290e7ad21083406da78e738 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Fitness.h +++ b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Fitness.h @@ -19,6 +19,7 @@ - (void)fitness_initializeStepEventObserver:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; - (void)fitness_getDistanceWalkingRunningOnDay:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; - (void)fitness_getDailyDistanceWalkingRunningSamples:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; +- (void)fitness_getDailyDistanceSwimmingSamples:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; - (void)fitness_getDistanceCyclingOnDay:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; - (void)fitness_getDailyDistanceCyclingSamples:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; - (void)fitness_getFlightsClimbedOnDay:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback; diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Fitness.m b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Fitness.m index eb812a17728085f8cb4b5606829e145aa93f8460..6ca17408675c52085c8f43862799f9d10c05ae87 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Fitness.m +++ b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Fitness.m @@ -102,6 +102,9 @@ BOOL ascending = [RCTAppleHealthKit boolFromOptions:input key:@"ascending" withDefault:false]; NSDate *startDate = [RCTAppleHealthKit dateFromOptions:input key:@"startDate" withDefault:nil]; NSDate *endDate = [RCTAppleHealthKit dateFromOptions:input key:@"endDate" withDefault:[NSDate date]]; + NSUInteger period = [RCTAppleHealthKit uintFromOptions:input key:@"period" withDefault:60]; + BOOL includeManuallyAdded = [RCTAppleHealthKit boolFromOptions:input key:@"includeManuallyAdded" withDefault:false]; + if(startDate == nil){ callback(@[RCTMakeError(@"startDate is required in options", nil, nil)]); return; @@ -111,10 +114,12 @@ [self fetchCumulativeSumStatisticsCollection:stepCountType unit:unit + period:period startDate:startDate endDate:endDate ascending:ascending limit:limit + includeManuallyAdded:includeManuallyAdded completion:^(NSArray *arr, NSError *err){ if (err != nil) { callback(@[RCTJSErrorFromNSError(err)]); @@ -212,6 +217,8 @@ BOOL ascending = [RCTAppleHealthKit boolFromOptions:input key:@"ascending" withDefault:false]; NSDate *startDate = [RCTAppleHealthKit dateFromOptions:input key:@"startDate" withDefault:nil]; NSDate *endDate = [RCTAppleHealthKit dateFromOptions:input key:@"endDate" withDefault:[NSDate date]]; + NSUInteger period = [RCTAppleHealthKit uintFromOptions:input key:@"period" withDefault:60]; + BOOL includeManuallyAdded = [RCTAppleHealthKit boolFromOptions:input key:@"includeManuallyAdded" withDefault:false]; if(startDate == nil){ callback(@[RCTMakeError(@"startDate is required in options", nil, nil)]); return; @@ -221,10 +228,46 @@ [self fetchCumulativeSumStatisticsCollection:quantityType unit:unit + period:period + startDate:startDate + endDate:endDate + ascending:ascending + limit:limit + includeManuallyAdded:includeManuallyAdded + completion:^(NSArray *arr, NSError *err){ + if (err != nil) { + NSLog(@"error with fetchCumulativeSumStatisticsCollection: %@", err); + callback(@[RCTMakeError(@"error with fetchCumulativeSumStatisticsCollection", err, nil)]); + return; + } + callback(@[[NSNull null], arr]); + }]; +} + +- (void)fitness_getDailyDistanceSwimmingSamples:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback +{ + HKUnit *unit = [RCTAppleHealthKit hkUnitFromOptions:input key:@"unit" withDefault:[HKUnit meterUnit]]; + NSUInteger limit = [RCTAppleHealthKit uintFromOptions:input key:@"limit" withDefault:HKObjectQueryNoLimit]; + BOOL ascending = [RCTAppleHealthKit boolFromOptions:input key:@"ascending" withDefault:false]; + NSDate *startDate = [RCTAppleHealthKit dateFromOptions:input key:@"startDate" withDefault:nil]; + NSDate *endDate = [RCTAppleHealthKit dateFromOptions:input key:@"endDate" withDefault:[NSDate date]]; + NSUInteger period = [RCTAppleHealthKit uintFromOptions:input key:@"period" withDefault:60]; + BOOL includeManuallyAdded = [RCTAppleHealthKit boolFromOptions:input key:@"includeManuallyAdded" withDefault:false]; + if(startDate == nil){ + callback(@[RCTMakeError(@"startDate is required in options", nil, nil)]); + return; + } + + HKQuantityType *quantityType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierDistanceSwimming]; + + [self fetchCumulativeSumStatisticsCollection:quantityType + unit:unit + period:period startDate:startDate endDate:endDate ascending:ascending limit:limit + includeManuallyAdded:includeManuallyAdded completion:^(NSArray *arr, NSError *err){ if (err != nil) { callback(@[RCTJSErrorFromNSError(err)]); @@ -264,6 +307,8 @@ BOOL ascending = [RCTAppleHealthKit boolFromOptions:input key:@"ascending" withDefault:false]; NSDate *startDate = [RCTAppleHealthKit dateFromOptions:input key:@"startDate" withDefault:nil]; NSDate *endDate = [RCTAppleHealthKit dateFromOptions:input key:@"endDate" withDefault:[NSDate date]]; + NSUInteger period = [RCTAppleHealthKit uintFromOptions:input key:@"period" withDefault:60]; + BOOL includeManuallyAdded = [RCTAppleHealthKit boolFromOptions:input key:@"includeManuallyAdded" withDefault:false]; if(startDate == nil){ callback(@[RCTMakeError(@"startDate is required in options", nil, nil)]); return; @@ -273,10 +318,12 @@ [self fetchCumulativeSumStatisticsCollection:quantityType unit:unit + period:period startDate:startDate endDate:endDate ascending:ascending limit:limit + includeManuallyAdded:includeManuallyAdded completion:^(NSArray *arr, NSError *err){ if (err != nil) { callback(@[RCTJSErrorFromNSError(err)]); diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Queries.h b/RCTAppleHealthKit/RCTAppleHealthKit+Queries.h index 172152b61135dcdd1da5fbf5d0ed41c42f41ffe2..357aa895d3ac1dc69d60cd33736a0970800d1137 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit+Queries.h +++ b/RCTAppleHealthKit/RCTAppleHealthKit+Queries.h @@ -50,7 +50,15 @@ ascending:(BOOL)asc limit:(NSUInteger)lim completion:(void (^)(NSArray *, NSError *))completionHandler; - +- (void)fetchCumulativeSumStatisticsCollection:(HKQuantityType *)quantityType + unit:(HKUnit *)unit + period:(NSUInteger)period + startDate:(NSDate *)startDate + endDate:(NSDate *)endDate + ascending:(BOOL)asc + limit:(NSUInteger)lim + includeManuallyAdded:(BOOL)includeManuallyAdded + completion:(void (^)(NSArray *, NSError *))completionHandler; - (void)fetchSleepCategorySamplesForPredicate:(NSPredicate *)predicate diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Queries.m b/RCTAppleHealthKit/RCTAppleHealthKit+Queries.m index 4a484fea2829b60b9ad60ec88f55e98027fc8072..325493bdb6c79b1ffaf37d12a93faf8004beed1d 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit+Queries.m +++ b/RCTAppleHealthKit/RCTAppleHealthKit+Queries.m @@ -463,10 +463,10 @@ fromDate:[NSDate date]]; anchorComponents.hour = 0; NSDate *anchorDate = [calendar dateFromComponents:anchorComponents]; - + NSPredicate *predicate = [NSPredicate predicateWithFormat:@"metadata.%K != YES", HKMetadataKeyWasUserEntered]; // Create the query HKStatisticsCollectionQuery *query = [[HKStatisticsCollectionQuery alloc] initWithQuantityType:quantityType - quantitySamplePredicate:nil + quantitySamplePredicate:predicate options:HKStatisticsOptionCumulativeSum anchorDate:anchorDate intervalComponents:interval]; @@ -518,10 +518,87 @@ fromDate:[NSDate date]]; anchorComponents.hour = 0; NSDate *anchorDate = [calendar dateFromComponents:anchorComponents]; + NSPredicate *predicate = [NSPredicate predicateWithFormat:@"metadata.%K != YES", HKMetadataKeyWasUserEntered]; + // Create the query + HKStatisticsCollectionQuery *query = [[HKStatisticsCollectionQuery alloc] initWithQuantityType:quantityType + quantitySamplePredicate:predicate + options:HKStatisticsOptionCumulativeSum + anchorDate:anchorDate + intervalComponents:interval]; + + // Set the results handler + query.initialResultsHandler = ^(HKStatisticsCollectionQuery *query, HKStatisticsCollection *results, NSError *error) { + if (error) { + // Perform proper error handling here + NSLog(@"*** An error occurred while calculating the statistics: %@ ***", error.localizedDescription); + } + + NSMutableArray *data = [NSMutableArray arrayWithCapacity:1]; + + [results enumerateStatisticsFromDate:startDate + toDate:endDate + withBlock:^(HKStatistics *result, BOOL *stop) { + + HKQuantity *quantity = result.sumQuantity; + if (quantity) { + NSDate *startDate = result.startDate; + NSDate *endDate = result.endDate; + double value = [quantity doubleValueForUnit:unit]; + + NSString *startDateString = [RCTAppleHealthKit buildISO8601StringFromDate:startDate]; + NSString *endDateString = [RCTAppleHealthKit buildISO8601StringFromDate:endDate]; + + NSDictionary *elem = @{ + @"value" : @(value), + @"startDate" : startDateString, + @"endDate" : endDateString, + }; + [data addObject:elem]; + } + }]; + // is ascending by default + if(asc == false) { + [RCTAppleHealthKit reverseNSMutableArray:data]; + } + if((lim > 0) && ([data count] > lim)) { + NSArray* slicedArray = [data subarrayWithRange:NSMakeRange(0, lim)]; + NSError *err; + completionHandler(slicedArray, err); + } else { + NSError *err; + completionHandler(data, err); + } + }; + + [self.healthStore executeQuery:query]; +} + +- (void)fetchCumulativeSumStatisticsCollection:(HKQuantityType *)quantityType + unit:(HKUnit *)unit + period:(NSUInteger)period + startDate:(NSDate *)startDate + endDate:(NSDate *)endDate + ascending:(BOOL)asc + limit:(NSUInteger)lim + includeManuallyAdded:(BOOL)includeManuallyAdded + completion:(void (^)(NSArray *, NSError *))completionHandler { + + NSCalendar *calendar = [NSCalendar currentCalendar]; + NSDateComponents *interval = [[NSDateComponents alloc] init]; + interval.minute = period; + + NSDateComponents *anchorComponents = [calendar components:NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond | NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear + fromDate:startDate]; + //anchorComponents.hour = 0; + NSDate *anchorDate = [calendar dateFromComponents:anchorComponents]; + NSPredicate *predicate = nil; + if (includeManuallyAdded == false) { + predicate = [NSPredicate predicateWithFormat:@"metadata.%K != YES", HKMetadataKeyWasUserEntered]; + } // Create the query HKStatisticsCollectionQuery *query = [[HKStatisticsCollectionQuery alloc] initWithQuantityType:quantityType - quantitySamplePredicate:nil + quantitySamplePredicate:predicate options:HKStatisticsOptionCumulativeSum anchorDate:anchorDate intervalComponents:interval]; diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+TypesAndPermissions.m b/RCTAppleHealthKit/RCTAppleHealthKit+TypesAndPermissions.m index 4925c3c7e9b61eb5dab20db06e73f678c5ae8734..a54f03fb80a47d3030312b714e74f225ecefdcd1 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit+TypesAndPermissions.m +++ b/RCTAppleHealthKit/RCTAppleHealthKit+TypesAndPermissions.m @@ -31,6 +31,7 @@ @"StepCount" : [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierStepCount], @"DistanceWalkingRunning" : [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierDistanceWalkingRunning], @"DistanceCycling" : [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierDistanceCycling], + @"DistanceSwimming" : [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierDistanceSwimming], @"BasalEnergyBurned" : [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierBasalEnergyBurned], @"ActiveEnergyBurned" : [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierActiveEnergyBurned], @"FlightsClimbed" : [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierFlightsClimbed], diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Utils.m b/RCTAppleHealthKit/RCTAppleHealthKit+Utils.m index 8a0c22b8bbc93a8e4efcee7d56f731e72db490f4..f3a2f225ede4c77c284082f4e1451e34291967df 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit+Utils.m +++ b/RCTAppleHealthKit/RCTAppleHealthKit+Utils.m @@ -133,6 +133,8 @@ return [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierDistanceWalkingRunning]; } else if ([type isEqual:@"Cycling"]){ return [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierDistanceCycling]; + } else if ([type isEqual:@"Swimming"]){ + return [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierDistanceSwimming]; } // default [type isEqual:@"Workout"]) return [HKObjectType workoutType]; diff --git a/RCTAppleHealthKit/RCTAppleHealthKit.m b/RCTAppleHealthKit/RCTAppleHealthKit.m index dae204830bbf459503420baa72fc91905ad9c6c0..e2b13587d65be4f5e3c593811f52ed70e3c70a8c 100644 --- a/RCTAppleHealthKit/RCTAppleHealthKit.m +++ b/RCTAppleHealthKit/RCTAppleHealthKit.m @@ -160,6 +160,11 @@ RCT_EXPORT_METHOD(getDailyDistanceWalkingRunningSamples:(NSDictionary *)input ca [self fitness_getDailyDistanceWalkingRunningSamples:input callback:callback]; } +RCT_EXPORT_METHOD(getDailyDistanceSwimmingSamples:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback) +{ + [self fitness_getDailyDistanceSwimmingSamples:input callback:callback]; +} + RCT_EXPORT_METHOD(getDistanceCycling:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback) { [self fitness_getDistanceCyclingOnDay:input callback:callback]; diff --git a/README.md b/README.md index 3308848f47a300ad1305d433fa64bbd630dc8a19..6ad3ead0b94a3ba6b0b69298479f6a2b39a8495c 100644 --- a/README.md +++ b/README.md @@ -123,6 +123,7 @@ AppleHealthKit.initHealthKit(options: Object, (err: string, results: Object) => * [getDailyStepCountSamples](/docs/getDailyStepCountSamples().md) * [getDateOfBirth](/docs/getDateOfBirth().md) * [getDistanceCycling](/docs/getDistanceCycling().md) + * [getDistanceSwimming](/docs/getDistanceSwimming().md) * [getDistanceWalkingRunning](/docs/getDistanceWalkingRunning().md) * [getFlightsClimbed](/docs/getFlightsClimbed().md) * [getHeartRateSamples](/docs/getHeartRateSamples().md) diff --git a/docs/getDailyDistanceSwimmingSamples().md b/docs/getDailyDistanceSwimmingSamples().md new file mode 100644 index 0000000000000000000000000000000000000000..220451496853b24fc2fc473fc28aebb79489ad71 --- /dev/null +++ b/docs/getDailyDistanceSwimmingSamples().md @@ -0,0 +1,19 @@ +```javascript +let options = { + startDate: (new Date(2016,4,27)).toISOString(), // required + endDate: (new Date()).toISOString(), // optional; default now + ascending: false, // optional; default false + limit:10, // optional; default no limit + period: 60, // time interval in minutes optional: default 60 + includeManuallyAdded: false. // optional: default false +}; +``` + +```javascript +AppleHealthKit.getDailyDistanceSwimmingSamples(options, (err: Object, results: Array) => { + if (err) { + return; + } + console.log(results) +}); +```