Is there a way to get sensor data from Apple Watch? For example, how can I connect and get heart rate from Apple Watch to my app? These are the steps I need do in my app:
- Define a delegate to receive heart rate information from Apple Watch.
- Make a request to Apple Watch to send the data periodically
I know how it works for other HR monitors over BT. Is the interface similar to that? Or should depend on HealthKit to achieve that?
As per WatchKit FAQ on raywenderlich.com (scroll to "Can you access the heartbeat sensor and other sensors on the watch from your watch app?") it appears as though you can not access the sensor data.
No. There is currently no API to access the hardware sensors on the
Apple Watch at this time.
I have made my own workout application (just to learn how communication between iWatch and the iPhone work). I am currently getting the heart rate information in the following way. Obviously this has not been tested but it makes sense once you look at how the HealthKit framework is laid out.
We know that the Apple Watch will communicate with the iPhone through Bluetooth. If you read the first paragraph of the HealthKit's documentation you will see this:
In iOS 8.0, the system can automatically save data from compatible
Bluetooth LE heart rate monitors directly into the HealthKit store.
Since we know the Apple Watch will be a Bluetooth device and has a heart rate sensor I will be assuming the information is stored in HealthKit.
So I wrote the following code:
- (void) retrieveMostRecentHeartRateSample: (HKHealthStore*) _healthStore completionHandler:(void (^)(HKQuantitySample*))completionHandler
{
HKSampleType *_sampleType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierHeartRate];
NSPredicate *_predicate = [HKQuery predicateForSamplesWithStartDate:[NSDate distantPast] endDate:[NSDate new] options:HKQueryOptionNone];
NSSortDescriptor *_sortDescriptor = [[NSSortDescriptor alloc] initWithKey:HKSampleSortIdentifierStartDate ascending:NO];
HKSampleQuery *_query = [[HKSampleQuery alloc] initWithSampleType:_sampleType predicate:_predicate limit:1 sortDescriptors:@[_sortDescriptor] resultsHandler:^(HKSampleQuery *query, NSArray *results, NSError *error)
{
if (error)
{
NSLog(@"%@ An error has occured with the following description: %@", self, error.localizedDescription);
}
else
{
HKQuantitySample *mostRecentSample = [results objectAtIndex:0];
completionHandler(mostRecentSample);
}
}];
[_healthStore executeQuery:_query];
}
static HKObserverQuery *observeQuery;
- (void) startObservingForHeartRateSamples: (HKHealthStore*) _healthStore completionHandler:(void (^)(HKQuantitySample*))_myCompletionHandler
{
HKSampleType *_sampleType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierHeartRate];
if (observeQuery != nil)
[_healthStore stopQuery:observeQuery];
observeQuery = [[HKObserverQuery alloc] initWithSampleType:_sampleType predicate:nil updateHandler:^(HKObserverQuery *query, HKObserverQueryCompletionHandler completionHandler, NSError *error)
{
if (error)
{
NSLog(@"%@ An error has occured with the following description: %@", self, error.localizedDescription);
}
else
{
[self retrieveMostRecentHeartRateSample:_healthStore completionHandler:^(HKQuantitySample *sample)
{
_myCompletionHandler(sample);
}];
// If you have subscribed for background updates you must call the completion handler here.
// completionHandler();
}
}];
[_healthStore executeQuery:observeQuery];
}
Make sure to stop executing the observe query once the screen is deallocated.