dimanche 25 janvier 2015

Why does CMMotionActivityManager not return any recent activity data?

I am working on an iPhone app that tracks how many steps a person takes and how much time they invest in doing that. The step counting is done using the CMStepCounter class. However, time stamps are only provided with live steps, and not with historical step data. So to check how much time has actually elapsed while walking, I am using CMMotionActivityManager.


I have two methods, one for live counting, and one for fetching historical data while the app was in the background. The live counting works well enough, but the method for fetching historical activity data does not! Whenever the app enters the background I save the current date (via NSUserDefaults), and when the app enters the foreground again, I use queryActivityStartingFromDate with the aforementioned date as the start date, and the current date as the end date. This way it should tell me about the activities that happened in the meantime when the app was suspended. But usually the array of activities turns up empty, even if there was motion in between. If I enter the start of day as the start date, I get a huge array of activities, but there is sometimes fluctuation in the exact amount of entries.


I get the feeling that there is a delay in the logging of activities. Could that be my problem? But then, even if I wait half an hour before resuming the app, correct logging of the activity that occurred in between is not guaranteed.


The method for fetching historical activity data is at the bottom of this post. It is called on launch and then every time the app gets back into the foreground. It's always called with



[self calculateHistoricalActivitySince: _enteredBackgroundAt];


_enteredBackground is an NSDate. On launch, a method is called to restore some NSUserDefaults, among them this date. Every time the app enters the background it is set to the then-current date. When restoring this date the method makes sure it’s from the same day – if it’s an older date (i.e. the app was last used days ago), then it’s set to the start of the current day (0am today). self.activityInSecondsToday is an NSInteger.



-(void)calculateHistoricalActivitySince: (NSDate *) date
{

[_motionActivityManager queryActivityStartingFromDate: date
toDate: [NSDate date]
toQueue: _activityQueue
withHandler:^(NSArray *activities,
NSError *error)
{
if ([error code] == CMErrorUnknown)
{
NSLog(@"Motion Activity Manager Error: %@", error);
}

// Fill my activity array with historical data if it was walking or running
else
{
NSLog(@"Historical Total Activities from %@ \rto %@:\r %i", date, [NSDate date], (int)[activities count]);

// Create an array for all relevant activity data
_activityStorage = [NSMutableArray new];

for (int i = 0; i < [activities count]; i++)
{
if( [[activities objectAtIndex: i] walking] || [[activities objectAtIndex: i] running] || [[activities objectAtIndex: i] unknown])
[_activityStorage addObject: [activities objectAtIndex: i]];
}

// Calculate the time interval between each entry and increase activityInSecondsToday if the interval is not too large.
for (int i = 1; i < [_activityStorage count]; i++)
{
NSTimeInterval timeInterval = [[[_activityStorage objectAtIndex: i] startDate] timeIntervalSinceDate:[[_activityStorage objectAtIndex: i-1] startDate]];

if (timeInterval <= _maxTimeBetweenTimestampsForContinuedActivity)
self.activityInSecondsToday += timeInterval;

NSLog(@"ACTIVITY SINCE: %@ \r %ld", date, _activityInSecondsToday);
}
NSLog(@"Last activity’s timestamp: %@", [[_activityStorage objectAtIndex: [_activityStorage count]-1] startDate]);

[_activityStorage removeAllObjects];
}
}];


}




Aucun commentaire:

Enregistrer un commentaire