RCTAppleHealthKit.m 4.71 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11
//
//  RCTAppleHealthKit.m
//  RCTAppleHealthKit
//
//  Created by Greg Wilson on 2016-06-26.
//  Copyright © 2016 Greg Wilson. All rights reserved.
//

#import "RCTAppleHealthKit.h"
#import "RCTAppleHealthKit+Queries.h"
#import "RCTAppleHealthKit+TypesAndPermissions.h"
12
#import "RCTAppleHealthKit+Utils.h"
13

14 15 16
#import "RCTAppleHealthKit+Methods_Body.h"
#import "RCTAppleHealthKit+Methods_Fitness.h"

17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
@implementation RCTAppleHealthKit

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];
}

RCT_EXPORT_METHOD(getCurrentWeight:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback)
{
34
    [self body_getCurrentWeight:input callback:callback];
35 36 37 38
}

RCT_EXPORT_METHOD(saveWeight:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback)
{
39
    [self body_saveWeight:input callback:callback];
40 41
}

42 43 44 45 46 47 48 49

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



50 51 52 53 54
RCT_EXPORT_METHOD(getLatestBmi:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback)
{
    [self body_getLatestBodyMassIndex:input callback:callback];
}

55 56 57 58 59 60 61 62 63 64 65 66

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

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


67 68
RCT_EXPORT_METHOD(getStepCountForToday:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback)
{
69
    [self fitness_getStepCountForToday:input callback:callback];
70 71
}

72 73 74



75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
RCT_EXPORT_METHOD(getInfo:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback)
{
    [self getModuleInfo:input callback:callback];
}


- (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];
    
    if ([HKHealthStore isHealthDataAvailable]) {
96 97 98
        NSSet *writeDataTypes;
        NSSet *readDataTypes;

99
        // get permissions from input object provided by JS options argument
100 101 102 103 104 105 106 107 108 109 110 111 112
        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];
            
            if(readPerms != nil) {
                readDataTypes = readPerms;
            }
            if(writePerms != nil) {
                writeDataTypes = writePerms;
            }
113 114 115 116 117 118 119
        } 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){
120
            callback(@[RCTMakeError(@"at least 1 read or write permission must be set in options.permissions", nil, nil)]);
121
            return;
122
        }
123

124 125
        [self.healthStore requestAuthorizationToShareTypes:writeDataTypes readTypes:readDataTypes completion:^(BOOL success, NSError *error) {
            if (!success) {
126 127 128
                NSString *errMsg = [NSString stringWithFormat:@"Error with HealthKit authorization: %@", error];
                NSLog(errMsg);
                callback(@[RCTMakeError(errMsg, nil, nil)]);
129 130 131 132 133 134 135 136
                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
137
        callback(@[RCTMakeError(@"HealthKit data is not available", nil, nil)]);
138 139 140 141 142 143
    }
}


- (void)getModuleInfo:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback
{
144 145 146 147 148 149 150
    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]);
151 152 153 154
}


@end