LoginSignup
14
6

More than 5 years have passed since last update.

HealthKitに保存された情報を、バックグラウンドで取れるのか検証

Last updated at Posted at 2017-04-19

HealtKit(歩数や心拍数などのデータ)の分析ツールを作る場合など、バックグラウンドでデータの検証などを行いたい場合があります。
しかしAppleのHealthKitのドキュメントなどを見ていると、Healthkitのデータはバックグラウンドでは取れるけど、ロック中は取れないという記載があったため、実際に検証してみました。

検証

background fetchではいつ呼ばれるのか不定のため、テスト用にバックグラウンドでの位置情報アップデート時に、Healthkitの情報取得を行うようにしてみた。

位置情報取得開始
- (void)startGetLocation {

    NSString* timeText = [[NSDate date] description];
    [self.logText appendString:timeText];
    [self.logText appendString:@" startGetLocation"];
    [self.logText appendString:@"\r\n"];

    _locationManager = [CLLocationManager new];
    _locationManager.delegate = self;
    // バックグラウンドでの更新を許可する
    _locationManager.allowsBackgroundLocationUpdates = true;
    // 更新を自動停止する
    _locationManager.pausesLocationUpdatesAutomatically = false;
    // 精度を設定する(最高制度)
    _locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation;
    // 位置情報の更新間隔(0m)
    _locationManager.distanceFilter = kCLDistanceFilterNone;
    // 位置情報の更新頻度(その他)
    _locationManager.activityType = CLActivityTypeFitness;

    if ([_locationManager respondsToSelector:@selector(requestAlwaysAuthorization)]) {
        [_locationManager requestAlwaysAuthorization];
    }

    // 位置情報取得開始
    [_locationManager startUpdatingLocation];
}
位置情報取得時に、HealthKitデータ(歩数)取得
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations
{
    NSString* timeText = [[NSDate date] description];
    [self.logText appendString:timeText];
    [self.logText appendString:@" didUpdateLocations"];
    [self.logText appendString:@"\r\n"];

    [self getHealthKitString];
}

- (void)getHealthKitString
{
    NSCalendar *calendar = [NSCalendar currentCalendar];
    NSDateComponents *interval = [[NSDateComponents alloc] init];
    interval.day = 1;
    NSDateComponents *anchorComponents = [calendar components:NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear
                                                     fromDate:[NSDate date]];
    anchorComponents.hour = 0;
    NSDate *anchorDate = [calendar dateFromComponents:anchorComponents];
    HKQuantityType *quantityType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierStepCount];

    HKStatisticsCollectionQuery *query = [[HKStatisticsCollectionQuery alloc] initWithQuantityType:quantityType
                                                                           quantitySamplePredicate:nil
                                                                                           options:HKStatisticsOptionCumulativeSum
                                                                                        anchorDate:anchorDate
                                                                                intervalComponents:interval];

    query.initialResultsHandler = ^(HKStatisticsCollectionQuery *query, HKStatisticsCollection *results, NSError *error) {
        if (error) {
            [self.logText appendString:[error description]];
            [self.logText appendString:@"\r\n"];
            return;
        }
        NSDate *endDate = [NSDate date];
        NSDate *startDate = [calendar dateByAddingUnit:NSCalendarUnitDay
                                                 value:0
                                                toDate:endDate
                                               options:0];

        [results enumerateStatisticsFromDate:startDate toDate:endDate
                                   withBlock:^(HKStatistics *result, BOOL *stop) {
                                       HKQuantity *quantity = result.sumQuantity;
                                       [self.logText appendString:@" "];

                                       if (quantity) {
                                           double value = [quantity doubleValueForUnit:[HKUnit countUnit]];
                                           NSLog(@"%f", value);
                                           [self.logText appendString:[NSString stringWithFormat:@"%f",value]];
                                       }
                                       else {
                                           [self.logText appendString:@"no data"];
                                       }

                                       [self.logText appendString:@"\r\n"];
                                   }];
    };

    [_healthStore executeQuery:query];
}

結果

結果としては、iPhoneがロックされていない場合は正常取得できておりましたが、ロック状態になるとquery.initialResultsHandlerにて、エラーが返却されました。

Error Domain=com.apple.healthkit Code=6
"Protected health data is inaccessible"

iPhone紛失時などのセキュリティを考慮してのことだろうと思いますが、ちゃんとしてますね。Androidはどうなんだろうと気になります。

参考

[iOS 8] HealthKitを実装する(1) HealthKit簡易リファレンス
[iOS][Obj-C] 今こそ HealthKit を使ってみる
HealthKit data inaccessible in background

14
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
6