RCTAppleHealthKit.m 12.7 KB
Newer Older
1 2 3 4 5
//
//  RCTAppleHealthKit.m
//  RCTAppleHealthKit
//
//  Created by Greg Wilson on 2016-06-26.
Furyou81's avatar
Furyou81 committed
6 7
//  This source code is licensed under the MIT-style license found in the
//  LICENSE file in the root directory of this source tree.
8 9 10 11 12
//

#import "RCTAppleHealthKit.h"
#import "RCTAppleHealthKit+TypesAndPermissions.h"

13
#import "RCTAppleHealthKit+Methods_Activity.h"
14 15
#import "RCTAppleHealthKit+Methods_Body.h"
#import "RCTAppleHealthKit+Methods_Fitness.h"
Hazem El-Sisy's avatar
Hazem El-Sisy committed
16
#import "RCTAppleHealthKit+Methods_Dietary.h"
17
#import "RCTAppleHealthKit+Methods_Characteristic.h"
18
#import "RCTAppleHealthKit+Methods_Vitals.h"
19
#import "RCTAppleHealthKit+Methods_Results.h"
20
#import "RCTAppleHealthKit+Methods_Sleep.h"
skleest's avatar
skleest committed
21
#import "RCTAppleHealthKit+Methods_Mindfulness.h"
22
#import "RCTAppleHealthKit+NSUserDefaults.h"
23

24 25
#import <React/RCTBridgeModule.h>
#import <React/RCTEventDispatcher.h>
26

27
@implementation RCTAppleHealthKit
Furyou81's avatar
Furyou81 committed
28

29 30
@synthesize bridge = _bridge;

31 32 33 34 35 36 37 38 39 40 41 42
RCT_EXPORT_MODULE();

RCT_EXPORT_METHOD(isAvailable:(RCTResponseSenderBlock)callback)
{
    [self isHealthKitAvailable:callback];
}

RCT_EXPORT_METHOD(initHealthKit:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback)
{
    [self initializeHealthKit:input callback:callback];
}

43 44 45 46 47
RCT_EXPORT_METHOD(initStepCountObserver:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback)
{
    [self fitness_initializeStepEventObserver:input callback:callback];
}

48 49 50 51 52 53 54 55 56 57
RCT_EXPORT_METHOD(getBiologicalSex:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback)
{
    [self characteristic_getBiologicalSex:input callback:callback];
}

RCT_EXPORT_METHOD(getDateOfBirth:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback)
{
    [self characteristic_getDateOfBirth:input callback:callback];
}

58
RCT_EXPORT_METHOD(getLatestWeight:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback)
59
{
60
    [self body_getLatestWeight:input callback:callback];
61 62
}

63 64 65 66 67
RCT_EXPORT_METHOD(getWeightSamples:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback)
{
    [self body_getWeightSamples:input callback:callback];
}

68 69
RCT_EXPORT_METHOD(saveWeight:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback)
{
70
    [self body_saveWeight:input callback:callback];
71 72
}

73
RCT_EXPORT_METHOD(getLatestHeight:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback)
74
{
75
    [self body_getLatestHeight:input callback:callback];
76 77
}

78 79 80 81 82
RCT_EXPORT_METHOD(getHeightSamples:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback)
{
    [self body_getHeightSamples:input callback:callback];
}

Greg Wilson's avatar
Greg Wilson committed
83 84 85 86
RCT_EXPORT_METHOD(saveHeight:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback)
{
    [self body_saveHeight:input callback:callback];
}
87

88 89 90 91 92
RCT_EXPORT_METHOD(getLatestBmi:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback)
{
    [self body_getLatestBodyMassIndex:input callback:callback];
}

93 94 95 96 97
RCT_EXPORT_METHOD(saveBmi:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback)
{
    [self body_saveBodyMassIndex:input callback:callback];
}

98
RCT_EXPORT_METHOD(getLatestBodyFatPercentage:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback)
99
{
100
    [self body_getLatestBodyFatPercentage:input callback:callback];
101 102
}

103 104 105 106 107
RCT_EXPORT_METHOD(getBodyFatPercentageSamples:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback)
{
    [self body_getBodyFatPercentageSamples:input callback:callback];
}

Andrew Allen's avatar
Andrew Allen committed
108 109 110 111 112
RCT_EXPORT_METHOD(saveBodyFatPercentage:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback)
{
    [self body_saveBodyFatPercentage:input callback:callback];
}

113
RCT_EXPORT_METHOD(getLatestLeanBodyMass:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback)
114
{
115
    [self body_getLatestLeanBodyMass:input callback:callback];
116 117
}

118 119 120 121 122
RCT_EXPORT_METHOD(getLeanBodyMassSamples:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback)
{
    [self body_getLeanBodyMassSamples:input callback:callback];
}

Andrew Allen's avatar
Andrew Allen committed
123 124 125 126 127
RCT_EXPORT_METHOD(saveLeanBodyMass:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback)
{
    [self body_saveLeanBodyMass:input callback:callback];
}

128
RCT_EXPORT_METHOD(getStepCount:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback)
129
{
130
    [self fitness_getStepCountOnDay:input callback:callback];
131
}
132

133 134 135 136 137
RCT_EXPORT_METHOD(getStepCountSamples:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback)
{
    [self fitness_geStepSamples:input callback:callback];
}

138 139 140 141 142
RCT_EXPORT_METHOD(getStepCountSamplesByAnchor:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback)
{
    [self fitness_geStepSamplesByAnchor:input callback:callback];
}

Furyou81's avatar
Furyou81 committed
143 144 145 146 147 148 149 150 151 152 153
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];
}


154
RCT_EXPORT_METHOD(getDailyStepCountSamples:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback)
155 156 157 158
{
    [self fitness_getDailyStepSamples:input callback:callback];
}

159 160 161 162 163
RCT_EXPORT_METHOD(saveSteps:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback)
{
    [self fitness_saveSteps:input callback:callback];
}

164 165 166 167 168
RCT_EXPORT_METHOD(getDistanceWalkingRunning:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback)
{
    [self fitness_getDistanceWalkingRunningOnDay:input callback:callback];
}

Jackson Tomlinson's avatar
Jackson Tomlinson committed
169 170 171 172 173
RCT_EXPORT_METHOD(getDailyDistanceWalkingRunningSamples:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback)
{
    [self fitness_getDailyDistanceWalkingRunningSamples:input callback:callback];
}

174 175 176 177 178
RCT_EXPORT_METHOD(getDailyDistanceSwimmingSamples:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback)
{
    [self fitness_getDailyDistanceSwimmingSamples:input callback:callback];
}

179 180 181 182 183
RCT_EXPORT_METHOD(getDistanceCycling:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback)
{
    [self fitness_getDistanceCyclingOnDay:input callback:callback];
}

Jackson Tomlinson's avatar
Jackson Tomlinson committed
184 185 186 187 188
RCT_EXPORT_METHOD(getDailyDistanceCyclingSamples:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback)
{
    [self fitness_getDailyDistanceCyclingSamples:input callback:callback];
}

189 190 191 192 193
RCT_EXPORT_METHOD(getFlightsClimbed:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback)
{
    [self fitness_getFlightsClimbedOnDay:input callback:callback];
}

Jackson Tomlinson's avatar
Jackson Tomlinson committed
194 195 196 197 198
RCT_EXPORT_METHOD(getDailyFlightsClimbedSamples:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback)
{
    [self fitness_getDailyFlightsClimbedSamples:input callback:callback];
}

Hazem El-Sisy's avatar
Hazem El-Sisy committed
199 200 201 202 203 204 205 206 207 208
RCT_EXPORT_METHOD(saveFood:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback)
{
    [self saveFood:input callback:callback];
}

RCT_EXPORT_METHOD(saveWater:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback)
{
    [self saveWater:input callback:callback];
}

209 210 211 212 213
RCT_EXPORT_METHOD(getHeartRateSamples:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback)
{
    [self vitals_getHeartRateSamples:input callback:callback];
}

214 215 216 217 218
RCT_EXPORT_METHOD(getHeartRateSamplesByAnchor:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback)
{
    [self vitals_getHeartRateSamplesByAnchor:input callback:callback];
}

219 220 221 222 223
RCT_EXPORT_METHOD(getActiveEnergyBurned:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback)
{
   [self activity_getActiveEnergyBurned:input callback:callback];
}

hira's avatar
hira committed
224 225 226 227 228
RCT_EXPORT_METHOD(getBasalEnergyBurned:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback)
{
    [self activity_getBasalEnergyBurned:input callback:callback];
}

229 230 231 232 233
RCT_EXPORT_METHOD(getBodyTemperatureSamples:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback)
{
    [self vitals_getBodyTemperatureSamples:input callback:callback];
}

234 235 236 237
RCT_EXPORT_METHOD(getBloodPressureSamples:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback)
{
    [self vitals_getBloodPressureSamples:input callback:callback];
}
238

239 240 241 242 243
RCT_EXPORT_METHOD(getBloodPressureSamplesByAnchor:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback)
{
    [self vitals_getBloodPressureSamplesByAnchor:input callback:callback];
}

244 245 246 247 248
RCT_EXPORT_METHOD(getRespiratoryRateSamples:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback)
{
    [self vitals_getRespiratoryRateSamples:input callback:callback];
}

249 250 251 252 253
RCT_EXPORT_METHOD(getBloodGlucoseSamples:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback)
{
    [self results_getBloodGlucoseSamples:input callback:callback];
}

254 255 256
RCT_EXPORT_METHOD(getSleepSamples:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback)
{
    [self sleep_getSleepSamples:input callback:callback];
257 258 259 260 261
}

RCT_EXPORT_METHOD(getSleepSamplesByAnchor:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback)
{
    [self sleep_getSleepSamplesByAnchor:input callback:callback];
262 263
}

264 265 266 267 268
RCT_EXPORT_METHOD(getInfo:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback)
{
    [self getModuleInfo:input callback:callback];
}

skleest's avatar
skleest committed
269 270 271 272 273
RCT_EXPORT_METHOD(saveMindfulSession:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback)
{
    [self mindfulness_saveMindfulSession:input callback:callback];
}

274 275 276 277 278 279 280 281 282
RCT_EXPORT_METHOD(setUserDefaults:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback)
{
    [self set_UserDefaultsByKey:input callback:callback];
}

RCT_EXPORT_METHOD(resetUserDefaults:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback)
{
    [self reset_UserDefaultsByKey:input callback:callback];
}
283

王品堯's avatar
王品堯 committed
284 285 286 287 288 289 290 291 292 293
RCT_EXPORT_METHOD(getLastTimestamp:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback)
{
    [self get_TimestampByKey:input callback:callback];
}

RCT_EXPORT_METHOD(setTimestamp:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback)
{
    [self set_TimestampByKey:input callback:callback];
}

294 295 296 297 298 299 300 301 302 303 304 305 306
- (void)isHealthKitAvailable:(RCTResponseSenderBlock)callback
{
    BOOL isAvailable = NO;
    if ([HKHealthStore isHealthDataAvailable]) {
        isAvailable = YES;
    }
    callback(@[[NSNull null], @(isAvailable)]);
}


- (void)initializeHealthKit:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback
{
    self.healthStore = [[HKHealthStore alloc] init];
307

308
    if ([HKHealthStore isHealthDataAvailable]) {
309 310 311
        NSSet *writeDataTypes;
        NSSet *readDataTypes;

312
        // get permissions from input object provided by JS options argument
313 314 315 316 317 318
        NSDictionary* permissions =[input objectForKey:@"permissions"];
        if(permissions != nil){
            NSArray* readPermsArray = [permissions objectForKey:@"read"];
            NSArray* writePermsArray = [permissions objectForKey:@"write"];
            NSSet* readPerms = [self getReadPermsFromOptions:readPermsArray];
            NSSet* writePerms = [self getWritePermsFromOptions:writePermsArray];
319

320 321 322 323 324 325
            if(readPerms != nil) {
                readDataTypes = readPerms;
            }
            if(writePerms != nil) {
                writeDataTypes = writePerms;
            }
326 327 328 329 330 331 332
        } else {
            callback(@[RCTMakeError(@"permissions must be provided in the initialization options", nil, nil)]);
            return;
        }

        // make sure at least 1 read or write permission is provided
        if(!writeDataTypes && !readDataTypes){
333
            callback(@[RCTMakeError(@"at least 1 read or write permission must be set in options.permissions", nil, nil)]);
334
            return;
335
        }
336

337 338
        [self.healthStore requestAuthorizationToShareTypes:writeDataTypes readTypes:readDataTypes completion:^(BOOL success, NSError *error) {
            if (!success) {
339
                callback(@[RCTJSErrorFromNSError(error)]);
340 341 342 343 344 345 346 347
                return;
            } else {
                dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
                    callback(@[[NSNull null], @true]);
                });
            }
        }];
    } else {
Greg Wilson's avatar
Greg Wilson committed
348
        callback(@[RCTMakeError(@"HealthKit data is not available", nil, nil)]);
349 350 351
    }
}

352 353 354 355
RCT_EXPORT_METHOD(authorizationStatusForType:(NSString *)type
                  resolver:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject
{
356 357 358
    if (self.healthStore == nil) {
        self.healthStore = [[HKHealthStore alloc] init];
    }
359 360 361 362 363 364 365 366 367 368 369 370 371 372 373

    if ([HKHealthStore isHealthDataAvailable]) {
        HKObjectType *objectType = [self getWritePermFromString:type];
        if (objectType == nil) {
            reject(@"unknown write permission", nil, nil);
            return;
        }

        NSString *status = [self getAuthorizationStatusString:[self.healthStore authorizationStatusForType:objectType]];
        resolve(status);
    } else {
        reject(@"HealthKit data is not available", nil, nil);
    }
})

374 375
- (void)getModuleInfo:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback
{
376 377 378 379 380 381 382
    NSDictionary *info = @{
            @"name" : @"react-native-apple-healthkit",
            @"description" : @"A React Native bridge module for interacting with Apple HealthKit data",
            @"className" : @"RCTAppleHealthKit",
            @"author": @"Greg Wilson",
    };
    callback(@[[NSNull null], info]);
383 384 385
}

@end