5

I'm implementing a pedometer on iOS. An important requirement is it must work even if the app were to put in the background mode (e.g., a device is locked or a user presses the home button). You can see such implementation in the App Store like Nike+, Runtastic Pedometer and so on.

A few SO posts confirmed that this is made possible with Core Motion or, specifically, CMMotionManager with an additional property of Required background modes set to location.

I ran a quick test with the code below and found a strange problem:

// AppDelegate.m
- (void)applicationDidEnterBackground:(UIApplication *)application
{ 
    if(self.motionManager==nil) {
        self.motionManager=[[CMMotionManager alloc] init];
    }
    self.motionManager.accelerometerUpdateInterval=1/50;

    if(self.accelerometerReadings==nil) 
        self.accelerometerReadings=[[NSMutableArray alloc] init];

    [self.motionManager startAccelerometerUpdatesToQueue:[NSOperationQueue mainQueue] withHandler:^(CMAccelerometerData *accelerometerData, NSError *error) {
        dispatch_async(dispatch_get_main_queue(), ^{
            [self.accelerometerReadings addObject:accelerometerData];
        });
    }
}

- (void)applicationWillEnterForeground:(UIApplication *)application
{
    NSLog(@"The number of readings %d",self.accelerometerReadings.count);

    // do something with accelerometer data...
}

I tried this code with an iPhone 4S and iOS 6.1. When the app is launched I press the home button and shake it (to simulate walking) for 5 seconds and open the app again. These actions get repeated a few times. The output I got is:

2013-02-05 16:41:42.028 [1147:907] readings 0
2013-02-05 16:41:51.572 [1147:907] readings 444
2013-02-05 16:42:00.386 [1147:907] readings 1032
2013-02-05 16:42:08.026 [1147:907] readings 1555
...

I didn't check the correctness of the readings, but quick observation already reveals some problem. There is no readings (or sometimes only one reading) at the first time this app ran in the background mode.

What am I doing wrong here? And is this a correct approach for implementing a pedometer?

Nimit Pattanasri
  • 1,602
  • 1
  • 26
  • 37
  • You should set [accelerometerUpdateInterval](http://developer.apple.com/library/ios/documentation/CoreMotion/Reference/CMMotionManager_Class/Reference/Reference.html#//apple_ref/occ/instp/CMMotionManager/accelerometerUpdateInterval) to `1/50` instead of `deviceMotionUpdateInterval` – Kay Feb 05 '13 at 12:09
  • Nice catch! Unfortunately, this doesn't change the outcome. – Nimit Pattanasri Feb 05 '13 at 14:12
  • hi, did you find a solution to your problem? – Axarydax Sep 25 '13 at 11:03
  • @Axarydax No hope for a solution. I will give it another shot on iOS7 which should provide stronger support for running background tasks. – Nimit Pattanasri Oct 26 '13 at 19:05
  • any luck on ios7? i have the same exact issue trying too use accel data in the background. – Archie1986 Nov 07 '13 at 22:20
  • @Archie1986 Not try on iOS7 yet, but later on, I would focus on iPhone 5s' M7 chip and its API instead. Seem promising. http://www.macnn.com/articles/13/11/04/currently.limited.to.iphone.5s.program.tracks.all.motion/ – Nimit Pattanasri Nov 12 '13 at 13:04

1 Answers1

1

With M7 chip embedded in iPhone5s, an Apple built-in class, CMStepCounter, is probably the best way to go.

https://developer.apple.com/library/ios/documentation/CoreMotion/Reference/CMStepCounter_class/Reference/Reference.html#//apple_ref/doc/uid/TP40013504

Nimit Pattanasri
  • 1,602
  • 1
  • 26
  • 37