Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions RCTAppleHealthKit/RCTAppleHealthKit+Methods_Fitness.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
- (void)fitness_getFlightsClimbedOnDay:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback;
- (void)fitness_getDailyFlightsClimbedSamples:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback;

- (void)fitness_getAnchoredQuery:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback;
- (void)fitness_setObserver:(NSDictionary *)input __deprecated;
- (void)fitness_registerObserver:(NSString *)type
bridge:(RCTBridge *)bridge
Expand Down
33 changes: 33 additions & 0 deletions RCTAppleHealthKit/RCTAppleHealthKit+Methods_Fitness.m
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,39 @@ - (void)fitness_getDailyFlightsClimbedSamples:(NSDictionary *)input callback:(RC
}];
}

- (void)fitness_getAnchoredQuery:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback
{
NSUInteger limit = [RCTAppleHealthKit uintFromOptions:input key:@"limit" withDefault:HKObjectQueryNoLimit];

HKSampleType *stepType = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierStepCount];
HKQueryAnchor *anchor = [RCTAppleHealthKit hkAnchorFromOptions:input];
NSDate *startDate = [RCTAppleHealthKit dateFromOptions:input key:@"startDate" withDefault:nil];
NSDate *endDate = [RCTAppleHealthKit dateFromOptions:input key:@"endDate" withDefault:[NSDate date]];

NSPredicate *predicate = [RCTAppleHealthKit predicateForAnchoredQueries:anchor startDate:startDate endDate:endDate];

void (^completion)(NSDictionary *results, NSError *error);

completion = ^(NSDictionary *results, NSError *error) {
if (results){
callback(@[[NSNull null], results]);

return;
} else {
NSLog(@"error getting samples: %@", error);
callback(@[RCTMakeError(@"error getting samples", error, nil)]);

return;
}
};

[self fetchAnchoredStepCount:stepType
predicate:predicate
anchor:anchor
limit:limit
completion:completion];
}

/*!
Register observer from React Native object

Expand Down
6 changes: 6 additions & 0 deletions RCTAppleHealthKit/RCTAppleHealthKit+Queries.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,12 @@
limit:(NSUInteger)lim
completion:(void (^)(NSDictionary *, NSError *))completion;

- (void)fetchAnchoredStepCount:(HKSampleType *)type
predicate:(NSPredicate *)predicate
anchor:(HKQueryAnchor *)anchor
limit:(NSUInteger)lim
completion:(void (^)(NSDictionary *, NSError *))completion;

- (void)fetchQuantitySamplesOfType:(HKQuantityType *)quantityType
unit:(HKUnit *)unit
predicate:(NSPredicate *)predicate
Expand Down
63 changes: 63 additions & 0 deletions RCTAppleHealthKit/RCTAppleHealthKit+Queries.m
Original file line number Diff line number Diff line change
Expand Up @@ -578,6 +578,69 @@ - (void)fetchAnchoredWorkouts:(HKSampleType *)type
[self.healthStore executeQuery:query];
}

- (void)fetchAnchoredStepCount:(HKSampleType *)type
predicate:(NSPredicate *)predicate
anchor:(HKQueryAnchor *)anchor
limit:(NSUInteger)lim
completion:(void (^)(NSDictionary *, NSError *))completion {

// declare the block
void (^handlerBlock)(HKAnchoredObjectQuery *query, NSArray<__kindof HKSample *> *sampleObjects, NSArray<HKDeletedObject *> *deletedObjects, HKQueryAnchor *newAnchor, NSError *error);

// create and assign the block
handlerBlock = ^(HKAnchoredObjectQuery *query, NSArray<__kindof HKSample *> *sampleObjects, NSArray<HKDeletedObject *> *deletedObjects, HKQueryAnchor *newAnchor, NSError *error) {

if (!sampleObjects) {
if (completion) {
completion(nil, error);
}
return;
}

if (completion) {
NSMutableArray *data = [NSMutableArray arrayWithCapacity:1];

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
for (HKQuantitySample *sample in sampleObjects) {
@try {
double stepCount = [sample.quantity doubleValueForUnit:[HKUnit countUnit]];

NSString *startDateString = [RCTAppleHealthKit buildISO8601StringFromDate:sample.startDate];
NSString *endDateString = [RCTAppleHealthKit buildISO8601StringFromDate:sample.endDate];

NSDictionary *elem = @{
@"id" : [[sample UUID] UUIDString],
@"startDate" : startDateString,
@"endDate" : endDateString,
@"value" : @(stepCount),
@"sourceName" : [[[sample sourceRevision] source] name],
};

[data addObject:elem];
} @catch (NSException *exception) {
NSLog(@"RNHealth: An error occured while trying to add step count sample from: %@ ", [[[sample sourceRevision] source] bundleIdentifier]);
}
}

NSData *anchorData = [NSKeyedArchiver archivedDataWithRootObject:newAnchor];
NSString *anchorString = [anchorData base64EncodedStringWithOptions:0];
completion(@{
@"anchor": anchorString,
@"data": data,
}, error);
});
}
};

HKAnchoredObjectQuery *query = [[HKAnchoredObjectQuery alloc] initWithType:type
predicate:predicate
anchor:anchor
limit:lim
resultsHandler:handlerBlock];

[self.healthStore executeQuery:query];
}

- (void)fetchSleepCategorySamplesForPredicate:(NSPredicate *)predicate
limit:(NSUInteger)lim
ascending:(BOOL)asc
Expand Down
6 changes: 6 additions & 0 deletions RCTAppleHealthKit/RCTAppleHealthKit.m
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,12 @@ + (BOOL)requiresMainQueueSetup
[self fitness_getDailyStepSamples:input callback:callback];
}

RCT_EXPORT_METHOD(getAnchoredStepCount:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback)
{
[self _initializeHealthStore];
[self fitness_getAnchoredQuery:input callback:callback];
}

RCT_EXPORT_METHOD(saveSteps:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback)
{
[self _initializeHealthStore];
Expand Down
21 changes: 19 additions & 2 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,14 @@ declare module 'react-native-health' {
callback: (err: HKErrorResponse, results: AnchoredQueryResults) => void,
): void

getAnchoredStepCount(
options: HealthInputOptions,
callback: (
err: HKErrorResponse,
results: AnchoredStepCountQueryResults,
) => void,
): void

getDailyStepCountSamples(
options: HealthInputOptions,
callback: (err: string, results: Array<HealthValue>) => void,
Expand Down Expand Up @@ -462,7 +470,6 @@ declare module 'react-native-health' {
callback: (error: string, result: HealthValue) => void,
): void


Constants: Constants
}

Expand Down Expand Up @@ -499,6 +506,11 @@ declare module 'react-native-health' {
value: number
}

export interface HealthValueWithSource extends BaseValue {
value: number
sourceName: string
}

export interface BloodPressureSampleValue extends BaseValue {
bloodPressureSystolicValue: number
bloodPressureDiastolicValue: number
Expand Down Expand Up @@ -546,7 +558,7 @@ declare module 'react-native-health' {
PausedOrResumeRequest = 'pause or resume request',
Lap = 'lap',
Segment = 'segment',
Marker = 'marker'
Marker = 'marker',
}

export type HKWorkoutEventType = {
Expand Down Expand Up @@ -857,6 +869,11 @@ declare module 'react-native-health' {
data: Array<HKWorkoutQueriedSampleType>
}

export interface AnchoredStepCountQueryResults {
anchor: string
data: Array<HealthValueWithSource>
}

export interface WorkoutRouteQueryResults {
anchor: string
data: HKWorkoutRouteSampleType
Expand Down