1. 程式人生 > >十,iOS 健康資料獲取許可權和寫入許可權

十,iOS 健康資料獲取許可權和寫入許可權

本來以為以後可以好好種樹的,結果發現新增的資料可以在健康裡面看到,但是無法在支付寶這些裡面獲取。。。

1,Xcode 8之後需要在info.plist 中設定以下兩個許可權;

  (1)Privacy - Health Update Usage Description

 (2)Privacy - Health Share Usage Description

2,匯入標頭檔案;

#import <HealthKit/HealthKit.h>
#import <UIKit/UIDevice.h>

3,設定讀取資料的許可權和寫入資料的許可權

#pragma mark - 設定寫入許可權
- (NSSet *)dataTypesToWrite {
    HKQuantityType *stepType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierStepCount];
    HKQuantityType *distanceType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierDistanceWalkingRunning];
    return [NSSet setWithObjects:stepType,distanceType, nil];
}

#pragma mark - 設定讀取許可權
- (NSSet *)dataTypesToRead {

以下為設定的許可權型別:

   HKQuantityType *stepType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierStepCount];
    HKQuantityType *distanceType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierDistanceWalkingRunning];

    return [NSSet setWithObjects:stepType,distanceType, nil];
}

以下是關於fitness的全部許可權介紹可以直接去看HKQuantityType.h檔案很詳細,有//fitness,// Body Measurements,// Results,// Vitals等

// Fitness
HK_EXTERN HKQuantityTypeIdentifier const HKQuantityTypeIdentifierStepCount HK_AVAILABLE_IOS_WATCHOS(8_0, 2_0);                 // Scalar(Count),               Cumulative
HK_EXTERN HKQuantityTypeIdentifier const HKQuantityTypeIdentifierDistanceWalkingRunning HK_AVAILABLE_IOS_WATCHOS(8_0, 2_0);    // Length,                      Cumulative
HK_EXTERN HKQuantityTypeIdentifier const HKQuantityTypeIdentifierDistanceCycling HK_AVAILABLE_IOS_WATCHOS(8_0, 2_0);           // Length,                      Cumulative
HK_EXTERN HKQuantityTypeIdentifier const HKQuantityTypeIdentifierDistanceWheelchair HK_AVAILABLE_IOS_WATCHOS(10_0, 3_0);       // Length,               Cumulative
HK_EXTERN HKQuantityTypeIdentifier const HKQuantityTypeIdentifierBasalEnergyBurned HK_AVAILABLE_IOS_WATCHOS(8_0, 2_0);         // Energy,                      Cumulative
HK_EXTERN HKQuantityTypeIdentifier const HKQuantityTypeIdentifierActiveEnergyBurned HK_AVAILABLE_IOS_WATCHOS(8_0, 2_0);        // Energy,                      Cumulative
HK_EXTERN HKQuantityTypeIdentifier const HKQuantityTypeIdentifierFlightsClimbed HK_AVAILABLE_IOS_WATCHOS(8_0, 2_0);            // Scalar(Count),               Cumulative
HK_EXTERN HKQuantityTypeIdentifier const HKQuantityTypeIdentifierNikeFuel HK_AVAILABLE_IOS_WATCHOS(8_0, 2_0);                  // Scalar(Count),               Cumulative
HK_EXTERN HKQuantityTypeIdentifier const HKQuantityTypeIdentifierAppleExerciseTime HK_AVAILABLE_IOS_WATCHOS(9_3, 2_2);         // Time                         Cumulative
HK_EXTERN HKQuantityTypeIdentifier const HKQuantityTypeIdentifierPushCount HK_AVAILABLE_IOS_WATCHOS(10_0, 3_0);                // Scalar(Count),               Cumulative
HK_EXTERN HKQuantityTypeIdentifier const HKQuantityTypeIdentifierDistanceSwimming HK_AVAILABLE_IOS_WATCHOS(10_0, 3_0);         // Length,                      Cumulative
HK_EXTERN HKQuantityTypeIdentifier const HKQuantityTypeIdentifierSwimmingStrokeCount HK_AVAILABLE_IOS_WATCHOS(10_0, 3_0);      // Scalar(Count),               Cumulative



4,判斷裝置是否支援

 if(![HKHealthStore isHealthDataAvailable]){
        NSLog(@"裝置不支援healthkit");
    }

5,獲取許可權和獲取資料

 //    此處獲取許可權的寫入和讀取 獲取之後才可以加到資料中
    NSSet *writeDataTypes = [self dataTypesToWrite];
    NSSet *readDataTypes = [self dataTypesToRead];
    [self.healthstore requestAuthorizationToShareTypes:writeDataTypes readTypes:readDataTypes completion:^(BOOL success, NSError * _Nullable error) {
        if (success) {
 
            [self getStepsFromHealthKit];//第二種獲取方法
//            [self getdistanceFromHealthKit]; //獲取公里數
        }else{
       
        }
    }];
    
6,獲取具體的資料的方法,三個方法是一起的//unit此處需要注意的是單位的不同

- (void)getDistancesFromHealthKit{
    HKQuantityType *stepType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierDistanceWalkingRunning];
    [self fetchSumOfSamplesTodayForType:stepType unit:[HKUnit meterUnit] completion:^(double stepCount, NSError *error) {
        dispatch_async(dispatch_get_main_queue(), ^{
            NSLog(@"你的公里數為:%.f",stepCount);
            self.pedoLab.text = [NSString stringWithFormat:@"%.2fm",stepCount];
        });
    }];
}

#pragma mark - 讀取HealthKit資料
- (void)fetchSumOfSamplesTodayForType:(HKQuantityType *)quantityType unit:(HKUnit *)unit completion:(void (^)(double, NSError *))completionHandler {
    NSPredicate *predicate = [self predicateForSamplesToday];
    
    HKStatisticsQuery *query = [[HKStatisticsQuery alloc] initWithQuantityType:quantityType quantitySamplePredicate:predicate options:HKStatisticsOptionCumulativeSum completionHandler:^(HKStatisticsQuery *query, HKStatistics *result, NSError *error) {
        HKQuantity *sum = [result sumQuantity];
        NSLog(@"result ==== %@",result);
        if (completionHandler) {
            double value = [sum doubleValueForUnit:unit];
             NSLog(@"sum ==== %@",sum);
            NSLog(@"value ===%f",value);

            completionHandler(value, error);
        }
    }];
    [self.healthstore executeQuery:query];
}

#pragma mark - NSPredicate資料模型
- (NSPredicate *)predicateForSamplesToday {
    NSCalendar *calendar = [NSCalendar currentCalendar];
    NSDate *now = [NSDate date];
    NSDate *startDate = [calendar startOfDayForDate:now];
    NSDate *endDate = [calendar dateByAddingUnit:NSCalendarUnitDay value:1 toDate:startDate options:0];
    return [HKQuery predicateForSamplesWithStartDate:startDate endDate:endDate options:HKQueryOptionStrictStartDate];
}

7,新增和寫入資料,並重新獲取資料

#pragma mark - 新增步數
- (void)adddistanceWithStepNum:(double)stepNum {
    HKQuantitySample *stepCorrelationItem = [self distanceCorrelationWithStepNum:stepNum];
    
    [self.healthstore saveObject:stepCorrelationItem withCompletion:^(BOOL success, NSError *error) {
        dispatch_async(dispatch_get_main_queue(), ^{
            if (success) {
                [self.view endEditing:YES];
                UIAlertView *doneAlertView = [[UIAlertView alloc] initWithTitle:@"提示" message:@"新增成功" delegate:nil cancelButtonTitle:@"確定" otherButtonTitles:nil, nil];
                [doneAlertView show];
                //重新整理資料  重新獲取距離
                [self getDistancesFromHealthKit];
                
            }else {
                NSLog(@"The error was: %@.", error);
                UIAlertView *doneAlertView = [[UIAlertView alloc] initWithTitle:@"提示" message:@"新增失敗" delegate:nil cancelButtonTitle:@"確定" otherButtonTitles:nil, nil];
                [doneAlertView show];
                return ;
            }
        });
    }];
}

- (HKQuantitySample *)distanceCorrelationWithStepNum:(double)stepNum {
    NSDate *endDate = [NSDate date];
    NSDate *startDate = [NSDate dateWithTimeInterval:-300 sinceDate:endDate];
  /** 

//這裡的quantityWithUnit單位如果不對則會報錯注意 ,有以下單位獲取下面的對應的健康資料需要注意

+ (instancetype)meterUnitWithMetricPrefix:(HKMetricPrefix)prefix;      // m
+ (instancetype)meterUnit;  // m
+ (instancetype)inchUnit;   // in
+ (instancetype)footUnit;   // ft
+ (instancetype)yardUnit HK_AVAILABLE_IOS_WATCHOS(9_0, 2_0);   // yd
+ (instancetype)mileUnit;   // mi

**/
    HKQuantity *stepQuantityConsumed = [HKQuantity quantityWithUnit:[HKUnit meterUnit] doubleValue:stepNum];
    HKQuantityType *stepConsumedType = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierDistanceWalkingRunning];
    
    NSString *strName = [[UIDevice currentDevice] name];
    NSString *strModel = [[UIDevice currentDevice] model];
    NSString *strSysVersion = [[UIDevice currentDevice] systemVersion];
    NSString *localeIdentifier = [[NSLocale currentLocale] localeIdentifier];
    
    HKDevice *device = [[HKDevice alloc] initWithName:strName manufacturer:@"Apple" model:strModel hardwareVersion:strModel firmwareVersion:strModel softwareVersion:strSysVersion localIdentifier:localeIdentifier UDIDeviceIdentifier:localeIdentifier];
    
   // HKQuantitySample *stepConsumedSample = [HKQuantitySample quantitySampleWithType:stepConsumedType quantity:stepQuantityConsumed startDate:startDate endDate:endDate device:device metadata:nil];

//此處在iOS 8 的系統中使用會崩潰,報錯找不到該方法,由於以前一直用iOS10的系統測試的未曾發現這個問題,修改為以下方法即可

 HKQuantitySample *stepConsumedSample = [HKQuantitySample quantitySampleWithType:stepConsumedType quantity:stepQuantityConsumed startDate:startDate endDate:endDate];

  
    return stepConsumedSample;
}