0

Giới thiệu Framework Healthkit trong iOS

Mở đầu

Chào các bạn, như các bạn đã biết Framework HealthKit được Apple giới thiệu từ iOS 8, tuy nhiên trong các dự án bình thuường nếu không cần sử dụng đến thì chúng ta sẽ không bao giờ để ý đến nó. Tình cờ lần này có một người bạn của mình có nhờ thực hiện một bài toán về Framework này, và bạn đấy mong muốn mình viết bài toán với ngôn ngữ Objective C, một chút hoài niệm vì giờ mình không còn sử dụng nó trong công việc hàng này nữa rồi =)). Vì vậy hôm nay mình viết bài chia sẻ về Framework mà ít dev iOS nào động đến này. Chúng ta cùng bắt đầu....

Giới thiệu ứng dụng Demo

Trong bài này mình sẽ viết một ứng dụng Demo sử dụng Framework HealthKit bằng ngôn ngữ Objective C. Trong ứng dụng Health của Apple, phần activity của chúng ta chúng ta chỉ có thể xem được riêng lẻ được số bước chân (steps) hoặc khoảng cách đi (distance). Trong ứng dụng demo này của chúng ta, tôi sẽ gộp 2 activity này vào để chúng ta có thể quan sát số bước chân và khoảng cách đi được trong một khoảng thời gian của chúng ta được rõ ràng hơn. 2 ảnh cuối là ảnh của ứng dụng Demo của chúng ta, các bạn có thể thấy chúng ta có thể xem được cả số bước chân + khoảng cách của các lần mà framework Healthkit này đo được. Vậy chúng ta phải thực hiện như thế nào? Chúng ta cùng bắt đầu thôi.

Demo

Đầu tiên, chúng ta tạo mới một project như một project bình thường. Trong phần config của App, chúng ta vào Capabilities rồi On mục HealthKit lên. Giờ là đến việc Code:

Model

Chúng ta tạo Object gọi là HealthModel

#import <Foundation/Foundation.h>

@interface HealthModel : NSObject

@property (nonatomic, strong) NSString *startDate;
@property (nonatomic, strong) NSString *endDate;

@property (nonatomic, strong) NSString *distance;
@property (nonatomic, strong) NSString *stepCount;

- (NSDictionary *)dictionary;

- (NSInteger) stepCountValue;

- (NSInteger) distanceValue;

@end

#import "HealthModel.h"

@implementation HealthModel

  • (NSDictionary *)dictionary { NSDictionary *dict = @{@"startDate": self.startDate, @"endDate" : self.endDate, @"distance" : self.distance, @"stepCount" : self.stepCount}; return dict; }

  • (NSInteger)stepCountValue { NSString *stepCountString = [self.stepCount stringByReplacingOccurrencesOfString:@" count" withString:@""]; return [stepCountString integerValue]; }

  • (NSInteger)distanceValue { NSString *distanceString = [self.distance stringByReplacingOccurrencesOfString:@" m" withString:@""]; return [distanceString doubleValue]; }

@end

Get Data HealthKit + Map dữ liệu

Trong MainViewController, tôi thực hiện việc get dữ liệu sức khoẻ thông qua Framework HealthKit, do việc get dữ iệu chúng ta thì làm được lần lượt get số bước chân hoặc khoảng cách, chứ không thể get được đồng thời cùng một lúc nên chúng ta phải có bước map dữ liệu về model mà bên trên chúng ta đã tạo.

#pragma mark - fetchHealthData
- (void) fetchHealthData {
    HKQuantityType *stepCountType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierStepCount];
    __block NSMutableArray *stepCountResults = [[NSMutableArray alloc] init];
    __block NSMutableArray *distanceResults = [[NSMutableArray alloc] init];
    
    __block NSMutableArray *mapResults = [[NSMutableArray alloc] init];
    
    [self queryHealthData:stepCountType queryResultBlock:^(NSArray *results) {
        
        [stepCountResults addObjectsFromArray:results];
        if (results.count > 0) {
            HKQuantityType *distanceType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierDistanceWalkingRunning];
            [self queryHealthData:distanceType queryResultBlock:^(NSArray *results) {
                [distanceResults addObjectsFromArray:results];
                
                for (HKQuantitySample *distanceResult in results) {
                    for (HKQuantitySample *stepCountResult in stepCountResults) {
                        if ([distanceResult.startDate compare:stepCountResult.startDate] == NSOrderedSame && [distanceResult.endDate compare:stepCountResult.endDate] == NSOrderedSame)  {
                            HealthModel *healthModel = [[HealthModel alloc] init];
                            healthModel.startDate = [self changeDateToDateString:stepCountResult.startDate];
                            healthModel.endDate = [self changeDateToDateString:stepCountResult.endDate];
                            
                            HKQuantity *stepQuantity = stepCountResult.quantity;
                            healthModel.stepCount = [NSString stringWithFormat:@"%@", stepQuantity];
                            
                            HKQuantity *distanceQuantity = distanceResult.quantity;
                            
                            healthModel.distance = [NSString stringWithFormat:@"%@", distanceQuantity];
                            
                            [mapResults addObject:healthModel];
                        }
                    }
                }
                dispatch_async(dispatch_get_main_queue(), ^{
                    self.healthModelArray = mapResults;
                    [self.tableView reloadData];
                });
                
                // Export to JSON String
                NSMutableArray *dicHealthModels = [[NSMutableArray alloc] init];
                for (HealthModel *result in mapResults) {
                    [dicHealthModels addObject:result.dictionary];
                }
                
                NSError *writeError = nil;
                NSData *jsonData = [NSJSONSerialization dataWithJSONObject: dicHealthModels options:NSJSONWritingPrettyPrinted error:&writeError];
                NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
                NSLog(@"JSON Output: %@", jsonString);
                
                NSLog(@"%lu", (unsigned long)dicHealthModels.count);
            }];
        }
    }];
}
- (void) queryHealthData:(HKQuantityType *)quantityType
   queryResultBlock:(void (^)(NSArray *results))queryResultBlock {
    if (NSClassFromString(@"HKHealthStore") && [HKHealthStore isHealthDataAvailable]) {
        HKHealthStore *healthStore = [[HKHealthStore alloc] init];
        
        NSSet *shareObjectTypes = [NSSet setWithObjects:
                                   [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierDistanceWalkingRunning],
                                   [HKSampleType quantityTypeForIdentifier:HKQuantityTypeIdentifierStepCount],
                                   nil];
        
        
        // Request access
        [healthStore requestAuthorizationToShareTypes:nil
                                            readTypes:shareObjectTypes
                                           completion:^(BOOL success, NSError *error) {
                                               if(success == YES) {
                                                   NSSortDescriptor *timeSortDescription = [[NSSortDescriptor alloc] initWithKey:HKSampleSortIdentifierEndDate ascending:NO];
                                                   HKSampleQuery *query = [[HKSampleQuery alloc] initWithSampleType:quantityType
                                                                                                          predicate:nil
                                                                                                              limit:HKObjectQueryNoLimit
                                                                                                    sortDescriptors:@[timeSortDescription]
                                                                                                     resultsHandler:^(HKSampleQuery *query, NSArray *result, NSError *error) {
                                                                                                         if(!error && result) {
                                                                                                             queryResultBlock(result);
                                                                                                         }
                                                                                                     }];
                                                   [healthStore executeQuery:query];
                                               }
                                               else {
                                                   // Handle Error
                                                   NSLog(@"Error query health data");
                                               }
                                               
                                           }];
    }
}

Sau khi get được dữ liệu + map chúng lại với nhau thì chúng ta sẽ được list dữ liệu như sau:

{
    "stepCount" : "326 count",
    "startDate" : "09\/19\/2017, 1:02 PM",
    "endDate" : "09\/19\/2017, 1:06 PM",
    "distance" : "177.15 m"
  },
  {
    "stepCount" : "67 count",
    "startDate" : "09\/19\/2017, 12:52 PM",
    "endDate" : "09\/19\/2017, 1:02 PM",
    "distance" : "31.76 m"
  },

  {
    "stepCount" : "53 count",
    "startDate" : "09\/19\/2017, 11:45 AM",
    "endDate" : "09\/19\/2017, 11:46 AM",
    "distance" : "27.37 m"
  },
  {
    "stepCount" : "279 count",
    "startDate" : "09\/19\/2017, 11:35 AM",
    "endDate" : "09\/19\/2017, 11:45 AM",
    "distance" : "137.25 m"
  }

Công việc còn lại thì chúng ta chỉ cần hiển thị chúng lên Tableview và sẽ show được như hình bên trên mà tôi đã nhắc đến.

Kết luận

Ở trên tôi đã giới thiệu các bạn cách config một project để get dữ liệu sức khoẻ của chúng ta trên chiếc iphone của mình. Bài viết dừng ở mức độ cơ bản của người mới bắt đầu tìm hiểu về HealthKit, có chỗ nào thắc mắc hoặc sai lầm các bạn có thể góp ý cho mình. Bài viết của mình đến đây là hết, cám ơn các bạn đã đọc bài. Nguồn: Apple Link Prject: Demo


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí