Commit 715a0ebe authored by Evstropov Evgenii's avatar Evstropov Evgenii Committed by GitHub

Merge pull request #25 from EJohnF/observer

Add unified way to get workouts with activity name/id, isTracked flag. Add listener for any changes
parents 3a47aefc 181f4faa
......@@ -66,5 +66,6 @@ export const Permissions = {
SleepAnalysis: "SleepAnalysis",
StepCount: "StepCount",
Steps: "Steps",
Weight: "Weight"
Weight: "Weight",
Workout: "Workout"
}
......@@ -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)
......
......@@ -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"
......
......@@ -18,10 +18,7 @@
{
HKQuantityType *weightType = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierBodyMass];
HKUnit *unit = [RCTAppleHealthKit hkUnitFromOptions:input];
if(unit == nil){
unit = [HKUnit poundUnit];
}
HKUnit *unit = [RCTAppleHealthKit hkUnitFromOptions:input key:@"unit" withDefault:[HKUnit poundUnit]];
[self fetchMostRecentQuantitySampleOfType:weightType
predicate:nil
......@@ -33,7 +30,6 @@
else {
// Determine the weight in the required unit.
double usersWeight = [mostRecentQuantity doubleValueForUnit:unit];
NSDictionary *response = @{
@"value" : @(usersWeight),
@"startDate" : [RCTAppleHealthKit buildISO8601StringFromDate:startDate],
......@@ -152,11 +148,7 @@
- (void)body_getLatestHeight:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback
{
HKQuantityType *heightType = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierHeight];
HKUnit *unit = [RCTAppleHealthKit hkUnitFromOptions:input];
if(unit == nil){
unit = [HKUnit inchUnit];
}
HKUnit *unit = [RCTAppleHealthKit hkUnitFromOptions:input key:@"unit" withDefault:[HKUnit inchUnit]];;
[self fetchMostRecentQuantitySampleOfType:heightType
predicate:nil
......@@ -218,11 +210,7 @@
{
double height = [RCTAppleHealthKit doubleValueFromOptions:input];
NSDate *sampleDate = [RCTAppleHealthKit dateFromOptionsDefaultNow:input];
HKUnit *heightUnit = [RCTAppleHealthKit hkUnitFromOptions:input];
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];
......
......@@ -12,6 +12,8 @@
@interface RCTAppleHealthKit (Methods_Fitness)
- (void)fitness_getStepCountOnDay:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback;
- (void)fitness_getSamples:(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;
......
......@@ -49,6 +49,52 @@
}];
}
- (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];
BOOL ascending = [RCTAppleHealthKit boolFromOptions:input key:@"ascending" withDefault:false];
NSString *type = [RCTAppleHealthKit stringFromOptions:input key:@"type" withDefault:@"Walking"];
NSDate *startDate = [RCTAppleHealthKit dateFromOptions:input key:@"startDate" withDefault:[NSDate date]];
NSDate *endDate = [RCTAppleHealthKit dateFromOptions:input key:@"endDate" withDefault:[NSDate date]];
NSPredicate *predicate = [HKQuery predicateForSamplesWithStartDate:startDate endDate:endDate options:HKQueryOptionStrictStartDate];
HKSampleType *samplesType = [RCTAppleHealthKit hkQuantityTypeFromString:type];
if ([type isEqual:@"Running"] || [type isEqual:@"Cycling"]) {
unit = [HKUnit mileUnit];
}
NSLog(@"error getting samples: %@", [samplesType identifier]);
[self fetchSamplesOfType:samplesType
unit:unit
predicate:predicate
ascending:ascending
limit:limit
completion:^(NSArray *results, NSError *error) {
if(results){
callback(@[[NSNull null], results]);
return;
} else {
NSLog(@"error getting samples: %@", error);
callback(@[RCTMakeError(@"error getting samples", nil, nil)]);
return;
}
}];
}
- (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 = [RCTAppleHealthKit hkQuantityTypeFromString:type];
if ([type isEqual:@"Running"] || [type isEqual:@"Cycling"]) {
unit = [HKUnit mileUnit];
}
[self setObserverForType:samplesType unit:unit];
}
- (void)fitness_getDailyStepSamples:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback
{
......
......@@ -19,6 +19,18 @@
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;
- (void)fetchQuantitySamplesOfType:(HKQuantityType *)quantityType
unit:(HKUnit *)unit
predicate:(NSPredicate *)predicate
......
......@@ -10,8 +10,10 @@
#import "RCTAppleHealthKit+Queries.h"
#import "RCTAppleHealthKit+Utils.h"
@implementation RCTAppleHealthKit (Queries)
#import <React/RCTBridgeModule.h>
#import <React/RCTEventDispatcher.h>
@implementation RCTAppleHealthKit (Queries)
- (void)fetchMostRecentQuantitySampleOfType:(HKQuantityType *)quantityType
predicate:(NSPredicate *)predicate
......@@ -49,7 +51,6 @@
[self.healthStore executeQuery:query];
}
- (void)fetchQuantitySamplesOfType:(HKQuantityType *)quantityType
unit:(HKUnit *)unit
predicate:(NSPredicate *)predicate
......@@ -106,19 +107,153 @@
[self.healthStore executeQuery:query];
}
- (void)fetchSamplesOfType:(HKSampleType *)type
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
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(), ^{
if (type == [HKObjectType workoutType]) {
for (HKWorkout *sample in results) {
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];
bool isTracked = true;
if ([[sample metadata][HKMetadataKeyWasUserEntered] intValue] == 1) {
isTracked = false;
}
NSString* device = @"";
if (@available(iOS 11.0, *)) {
device = [[sample sourceRevision] productType];
} else {
device = [[sample device] name];
if (!device) {
device = @"iPhone";
}
}
NSDictionary *elem = @{
@"activityId" : [NSNumber numberWithInt:[sample workoutActivityType]],
@"activityName" : type,
@"calories" : @(energy),
@"tracked" : @(isTracked),
@"sourceName" : [[[sample sourceRevision] source] name],
@"sourceId" : [[[sample sourceRevision] source] bundleIdentifier],
@"device": device,
@"distance" : @(distance),
@"start" : startDateString,
@"end" : endDateString
};
[data addObject:elem];
}
} else {
for (HKQuantitySample *sample in results) {
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];
bool isTracked = true;
if ([[sample metadata][HKMetadataKeyWasUserEntered] intValue] == 1) {
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": device,
@"start" : startDateString,
@"end" : endDateString
};
[data addObject:elem];
}
}
completion(data, error);
});
}
};
HKSampleQuery *query = [[HKSampleQuery alloc] initWithSampleType:type
predicate:predicate
limit:lim
sortDescriptors:@[timeSortDescriptor]
resultsHandler:handlerBlock];
[self.healthStore executeQuery:query];
}
- (void)setObserverForType:(HKSampleType *)type
unit:(HKUnit *)unit {
HKObserverQuery *query = [[HKObserverQuery alloc] initWithSampleType:type predicate:nil updateHandler:^(HKObserverQuery *query, HKObserverQueryCompletionHandler completionHandler, NSError * _Nullable error){
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.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]);
}];
}
- (void)fetchSleepCategorySamplesForPredicate:(NSPredicate *)predicate
limit:(NSUInteger)lim
completion:(void (^)(NSArray *, NSError *))completion {
NSSortDescriptor *timeSortDescriptor = [[NSSortDescriptor alloc] initWithKey:HKSampleSortIdentifierEndDate
ascending:false];
......
......@@ -11,6 +11,8 @@
@interface RCTAppleHealthKit (TypesAndPermissions)
- (NSDictionary *)readPermsDict;
- (NSDictionary *)writePermsDict;
- (NSSet *)getReadPermsFromOptions:(NSArray *)options;
- (NSSet *)getWritePermsFromOptions:(NSArray *)options;
......
......@@ -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"
......@@ -49,6 +50,8 @@
@"SleepAnalysis" : [HKObjectType categoryTypeForIdentifier:HKCategoryTypeIdentifierSleepAnalysis],
// Mindfulness
@"MindfulSession" : [HKObjectType categoryTypeForIdentifier:HKCategoryTypeIdentifierMindfulSession],
//workouts
@"Workout" : [HKObjectType workoutType],
};
return readPerms;
}
......@@ -118,7 +121,6 @@
return writePerms;
}
// Returns HealthKit read permissions from options array
- (NSSet *)getReadPermsFromOptions:(NSArray *)options {
NSDictionary *readPermDict = [self readPermsDict];
......
......@@ -23,7 +23,7 @@
+ (NSDate *)startDateFromOptions:(NSDictionary *)options;
+ (NSDate *)endDateFromOptions:(NSDictionary *)options;
+ (NSDate *)endDateFromOptionsDefaultNow:(NSDictionary *)options;
+ (HKUnit *)hkUnitFromOptions:(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;
......@@ -33,5 +33,6 @@
+ (bool)boolFromOptions:(NSDictionary *)options key:(NSString *)key withDefault:(bool)defaultValue;
+ (NSMutableArray *)reverseNSMutableArray:(NSMutableArray *)array;
+ (NSString*) stringForHKWorkoutActivityType:(int) enumValue;
@end
......@@ -124,56 +124,18 @@
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;
+ (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];
}
......@@ -184,12 +146,21 @@
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];
}
......@@ -321,4 +292,166 @@
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";
case HKWorkoutActivityTypeBarre:
return @"Barre";
case HKWorkoutActivityTypeCoreTraining:
return @"CoreTraining";
case HKWorkoutActivityTypeCrossCountrySkiing:
return @"CrossCountrySkiing";
case HKWorkoutActivityTypeDownhillSkiing:
return @"DownhillSkiing";
case HKWorkoutActivityTypeFlexibility:
return @"Flexibility";
case HKWorkoutActivityTypeHighIntensityIntervalTraining:
return @"HighIntensityIntervalTraining";
case HKWorkoutActivityTypeJumpRope:
return @"JumpRope";
case HKWorkoutActivityTypeKickboxing:
return @"Kickboxing";
case HKWorkoutActivityTypePilates:
return @"Pilates";
case HKWorkoutActivityTypeSnowboarding:
return @"Snowboarding";
case HKWorkoutActivityTypeStairs:
return @"Stairs";
case HKWorkoutActivityTypeStepTraining:
return @"StepTraining";
case HKWorkoutActivityTypeWheelchairWalkPace:
return @"WheelchairWalkPace";
case HKWorkoutActivityTypeWheelchairRunPace:
return @"WheelchairRunPace";
case HKWorkoutActivityTypeTaiChi:
return @"TaiChi";
case HKWorkoutActivityTypeMixedCardio:
return @"MixedCardio";
case HKWorkoutActivityTypeHandCycling:
return @"HandCycling";
default:{
NSException *e = [NSException
exceptionWithName:@"HKWorkoutActivityType InvalidValue"
reason:@"HKWorkoutActivityType can only have a value from the HKWorkoutActivityType enum"
userInfo:nil];
@throw e;
}
}
}
@end
......@@ -16,9 +16,11 @@
@interface RCTAppleHealthKit : NSObject <RCTBridgeModule>
@property (nonatomic) HKHealthStore *healthStore;
@property BOOL isSync;
- (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
......@@ -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"
......@@ -23,6 +24,7 @@
#import <React/RCTEventDispatcher.h>
@implementation RCTAppleHealthKit
@synthesize bridge = _bridge;
RCT_EXPORT_MODULE();
......@@ -107,6 +109,17 @@ RCT_EXPORT_METHOD(getStepCount:(NSDictionary *)input callback:(RCTResponseSender
[self fitness_getStepCountOnDay:input callback:callback];
}
RCT_EXPORT_METHOD(getSamples:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback)
{
[self fitness_getSamples:input callback:callback];
}
RCT_EXPORT_METHOD(setObserver:(NSDictionary *)input)
{
[self fitness_setObserver:input];
}
RCT_EXPORT_METHOD(getDailyStepCountSamples:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback)
{
[self fitness_getDailyStepSamples:input callback:callback];
......
......@@ -102,37 +102,39 @@ AppleHealthKit.initHealthKit(options: Object, (err: string, results: Object) =>
* [initHealthKit](/docs/initHealthKit().md)
* Realtime Methods
* [initStepCountObserver](/docs/initStepCountObserver().md)
* [setObserver](/docs/setObserver().md)
* Read Methods
* [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)
......
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<Object>) => {
if (err) {
return;
}
console.log(results)
});
```
Resulting object has different fields for different types.
In case of workout:
```
{
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]
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:
```
{
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]]
}
```
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.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment