In this post i will discuss about how to create a HealthKit Application , By which you can share your Health and Fitness information to Health application or retrieve data from it.
If you do not know what is HealthKit and Health application then please check my blogs
Health App and HealthKit Part:- 1 and Health App and HealthKit Part:- 2
Lets start with our example.
Requirements: Xcode 6 and iOS 8
Example:
1) Create an Application id which supports HealthKit.
From developer.apple.com you need to create an App ID , and you can check HealthKit feature same as you do with Push Notifications, In App Purchase.
Now you have to create provisioning profile which supports this application. You have to your application with this provisioning profile.
2) An Entitlements.plist file
An Entitlements.plist with com.apple.developer.healthkit property which has Boolean type and Set it to Yes.
3) Change in Info.plist file
In your Info.plist file UIRequiredDeviceCapabilities key you need to add entry called healthkit with String type.
4) Coding Part
You can add ass many quantitypes here , For making example simpler i just considered two to four.
By Calling this authentication method it will open below screen.
This screen contains read and write quantity types which we request. You can access in in your applications by setting them ON.
So here we created a Sample with quantity type weight with pound Unit. and we are wring 100 pound value in to it.
So by the method saveObject:weightSample you can write any quantity to your healthstore and here we are writing Weight to it and it is 100 in our case.
If you do not know what is HealthKit and Health application then please check my blogs
Health App and HealthKit Part:- 1 and Health App and HealthKit Part:- 2
Lets start with our example.
Requirements: Xcode 6 and iOS 8
Example:
1) Create an Application id which supports HealthKit.
From developer.apple.com you need to create an App ID , and you can check HealthKit feature same as you do with Push Notifications, In App Purchase.
Now you have to create provisioning profile which supports this application. You have to your application with this provisioning profile.
2) An Entitlements.plist file
An Entitlements.plist with com.apple.developer.healthkit property which has Boolean type and Set it to Yes.
3) Change in Info.plist file
In your Info.plist file UIRequiredDeviceCapabilities key you need to add entry called healthkit with String type.
4) Coding Part
- Add healthKit Framework to your project.
- Import HealthKit in your controller by
@import HealthKit
- Authentication: Open an HealthKit view which contains reading and writing permissions.
-
(void)authentication
{
self.healthStore = [[HKHealthStore alloc] init];
if ([HKHealthStore isHealthDataAvailable]) {
NSSet *writeDataTypes = [self dataTypesToWrite];
NSSet *readDataTypes = [self dataTypesToRead];
[self.healthStore
requestAuthorizationToShareTypes:writeDataTypes readTypes:readDataTypes
completion:^(BOOL success, NSError *error) {
if (!success) {
NSLog(@"You didn't allow
HealthKit to access these read/write data types. In your app, try to handle
this error gracefully when a user decides not to provide access. The error was:
%@. If you're using a simulator, try it on a device.", error);
return;
}
dispatch_async(dispatch_get_main_queue(), ^{
// Update the user
interface based on the current user's health information.
});
}];
}
}
- Where read and write data types are
- (NSSet *)dataTypesToWrite {
HKQuantityType *heightType =
[HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierHeight];
HKQuantityType *weightType =
[HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierBodyMass];
return [NSSet
setWithObjects: heightType, weightType, nil];
}
// Returns the types of data that Fit wishes to read from HealthKit.
- (NSSet *)dataTypesToRead {
HKQuantityType *heightType =
[HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierHeight];
HKQuantityType *weightType =
[HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierBodyMass];
HKCharacteristicType *birthdayType =
[HKObjectType
characteristicTypeForIdentifier:HKCharacteristicTypeIdentifierDateOfBirth];
HKCharacteristicType
*biologicalSexType = [HKObjectType
characteristicTypeForIdentifier:HKCharacteristicTypeIdentifierBiologicalSex];
return [NSSet
setWithObjects: heightType, weightType, birthdayType, biologicalSexType, nil];
}
You can add ass many quantitypes here , For making example simpler i just considered two to four.
By Calling this authentication method it will open below screen.
This screen contains read and write quantity types which we request. You can access in in your applications by setting them ON.
- Now we need to write data to Health Application.
- (IBAction)storeWeight:(id)sender
{
HKQuantityType *weightType = [HKQuantityType
quantityTypeForIdentifier:HKQuantityTypeIdentifierBodyMass];
HKUnit *poundUnit = [HKUnit poundUnit];
HKQuantity *weightQuantity = [HKQuantity quantityWithUnit:poundUnit
doubleValue:100];
NSDate *now = [NSDate date];
HKQuantitySample *weightSample = [HKQuantitySample
quantitySampleWithType:weightType quantity:weightQuantity startDate:now
endDate:now];
[self.healthStore saveObject:weightSample
withCompletion:^(BOOL success, NSError *error) {
if(error) {
UIAlertView *alert =
[[UIAlertView alloc] initWithTitle:@"error" message:error.description
delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];
[alert show];
}
else{
UIAlertView *alert =
[[UIAlertView alloc] initWithTitle:@"Weight added to health app" message:nil delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];
[alert show];
}
}];
}
So by the method saveObject:weightSample you can write any quantity to your healthstore and here we are writing Weight to it and it is 100 in our case.
- For reading Data from HealthKit
- (IBAction)getWeight:(id)sender
{
HKQuantityType *weightType = [HKQuantityType
quantityTypeForIdentifier:HKQuantityTypeIdentifierBodyMass];
// Since we are interested in retrieving the
user's latest sample
// we sort the samples in descending order by
end date
// and set the limit to 1
// We are not filtering the data, and so the
predicate is set to nil.
NSSortDescriptor *timeSortDescriptor =
[[NSSortDescriptor alloc] initWithKey:HKSampleSortIdentifierEndDate
ascending:NO];
// construct the query & since we are not
filtering the data the predicate is set to nil
HKSampleQuery *query = [[HKSampleQuery alloc]
initWithSampleType:weightType predicate:nil limit:1 sortDescriptors:@[timeSortDescriptor] resultsHandler:^(HKSampleQuery
*query, NSArray *results, NSError *error) {
if(error)
{
UIAlertView *alert =
[[UIAlertView alloc] initWithTitle:@"error" message:error.description
delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];
[alert show];
}
// if there is a data point,
dispatch to the main queue
if (results) {
dispatch_async(dispatch_get_main_queue(),
^{
HKQuantitySample *quantitySample = results.firstObject;
//
pull out the quantity from the sample
HKQuantity
*quantity = quantitySample.quantity;
HKUnit
*weightUnit = [HKUnit poundUnit];
double usersWeight
= [quantity doubleValueForUnit:weightUnit];
NSString
*str = [NSString stringWithFormat:@"%@ lbs", [NSNumberFormatter
localizedStringFromNumber:@(usersWeight) numberStyle:NSNumberFormatterNoStyle]];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Success" message:str
delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];
[alert
show];
});
}
}];
// do not forget to execute the query after its
constructed
[self.healthStore executeQuery:query];
}