search
LoginSignup
6

More than 5 years have passed since last update.

posted at

updated at

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

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

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
What you can do with signing up
6