How to use CMMotionActivityManager and receive updates?

13.2k views Asked by At

I want to create an app that can receive and process motion updates in order to understand if the user is stationary, walking, running or is on a transport. I've seen on the reference that CMMotionActivityManager can be useful for me.

The CMMotionActivityManager class provides access to the motion data stored by a device. Motion data reflects whether the user is walking, running, in a vehicle, or stationary for periods of time.

I'm new to app developing and I don't understand how to use the method for starting the updating. The method for doing this is - (void)startActivityUpdatesToQueue:(NSOperationQueue *)queue withHandler:(CMMotionActivityHandler)handler. I don't understand what should i write on handler because the reference says:

handler The block to execute when a change in the current type of motion is detected. For information about the parameters of this block, see CMMotionActivityHandler. This property must not be nil.

My implementation is:

- (IBAction)startButtonPressed:(id)sender {
_motionActivityManager = [[CMMotionActivityManager alloc] init];
[_motionActivityManager startActivityUpdatesToQueue:NSOperationQueueDefaultMaxConcurrentOperationCount withHandler:CMMotionActivityHandler];
}

I've already imported the CoreMotion framework But XCode don't recognize CMMotionActivityHandler, where am I wrong? How can I resolve this problem?

Thanks

4

There are 4 answers

2
Bhavin On

Sample Code :

[_motionActivityManager startActivityUpdatesToQueue:[[NSOperationQueue alloc] init]
                                          withHandler:
     ^(CMMotionActivity *activity) {

         dispatch_async(dispatch_get_main_queue(), ^{

             if ([activity walking]) {
                 NSLog(@"walking");
             }
     });
}];
0
Aggressor On

Swift 2.0

_motionActivityManager = CMMotionActivityManager()   
_motionActivityManager.startActivityUpdatesToQueue(NSOperationQueue.mainQueue())
{
    // CMMotionActivity
    activity in

    // do your logic here

}
0
mikeho On

The highest voted version of this answer is a bit roundabout. It creates a queue, but then uses GCD to execute back on the main queue. Also, many examples put a block within the withHandler parameter, but I find that clunky and doesn't look as clean (from a code formatting perspective).

Here's my example implementation:

@implementation MotionHandler {
@private
    // this is a private variable for this class that is not visible outside
    // (also, iOS handles memory and access management of these faster than properties)
    CMMotionActivityManager *_motionActivityManager;
}

// initialization method, you can do other stuff here too
- (instancetype)init {
    self = [super init];
    if (self) {
        // check to see if the device can handle motion activity
        if ([CMMotionActivityManager isActivityAvailable]) {
            // if so, initialize the activity manager
            _motionActivityManager = [[CMMotionActivityManager alloc] init];
        }
    }
}

- (void)startMotionActivityMonitoring {
    // create the motion activity handler
    CMMotionActivityHandler motionActivityHandler = ^(CMMotionActivity *activity) {
         // TODO motion detected here. Do something.
    }

    // check to see if the motion activity manager exists
    if (_motionActivityManager) {
        // if so, start monitoring activity
        // notice that we add updates to the mainQueue. This will call your handler on the main thread
        [_motionActivityManager startActivityUpdatesToQueue:[NSOperationQueue mainQueue] withHandler:motionActivityHandler];
    }
}

@end
0
user3272090 On

//check if availasble on device

BOOL b=  [CMMotionActivityManager isActivityAvailable];;

motionActivityManager=[[CMMotionActivityManager alloc]init];
//register for coremotion notification

 [motionActivityManager startActivityUpdatesToQueue:[NSOperationQueue mainQueue] withHandler:^(CMMotionActivity *activity) {

    NSLog(@"Got a core motion update");
    NSLog(@"Current activity date is %f",activity.timestamp);
    NSLog(@"Current activity confidence from a scale of 0 to 2 - 2 being best- is: %ld",activity.confidence);
    NSLog(@"Current activity type is unknown: %i",activity.unknown);
    NSLog(@"Current activity type is stationary: %i",activity.stationary);
    NSLog(@"Current activity type is walking: %i",activity.walking);
    NSLog(@"Current activity type is running: %i",activity.running);
    NSLog(@"Current activity type is cycling: %i",activity.cycling);
    NSLog(@"Current activity type is automotive: %i",activity.automotive);



}];

Please check on device