0

I'm trying to use CMMotionActivityManager's startActivityUpdatesToQueue in the background.

But it doesn't seem to work, is there additional things that I need to do besides adding this code:

        if CMMotionActivityManager.isActivityAvailable() {
            CMMotionActivityManager().startActivityUpdatesToQueue(NSOperationQueue.mainQueue(), withHandler: { (activity: CMMotionActivity?) in
                if (activity?.automotive)! {
                    let notification = UILocalNotification()
                    notification.alertTitle = "Arounder"
                    notification.alertBody = "User using car"
                    notification.soundName = "Notification Sound"
                    notification.category = "category"

                    UIApplication.sharedApplication().scheduleLocalNotification(notification)

                    print(notification.alertBody)
                } else if (activity?.cycling)! {
                    let notification = UILocalNotification()
                    notification.alertTitle = "Arounder"
                    notification.alertBody = "User is cycling"
                    notification.soundName = "Notification Sound"
                    notification.category = "category"

                    UIApplication.sharedApplication().scheduleLocalNotification(notification)
                    print(notification.alertBody)
                } else if (activity?.walking)! || (activity?.running)! {
                    let notification = UILocalNotification()
                    notification.alertTitle = "Arounder"
                    notification.alertBody = "User is walking/running"
                    notification.soundName = "Notification Sound"
                    notification.category = "category"

                    UIApplication.sharedApplication().scheduleLocalNotification(notification)
                    print(notification.alertBody)
                } else if (activity?.stationary)! {
                    let notification = UILocalNotification()
                    notification.alertTitle = "Arounder"
                    notification.alertBody = "User is standing"
                    notification.soundName = "Notification Sound"
                    notification.category = "category"

                    UIApplication.sharedApplication().scheduleLocalNotification(notification)
                    print(notification.alertBody)
                } else if (activity?.unknown)! {
                    let notification = UILocalNotification()
                    notification.alertTitle = "Arounder"
                    notification.alertBody = "Unknown activity"
                    notification.soundName = "Notification Sound"
                    notification.category = "category"

                    UIApplication.sharedApplication().scheduleLocalNotification(notification)
                    print(notification.alertBody)
                }
            })
        }

Do I need to get permission from the user like in Core Location (requestAlwaysAuthorization)? Something is the .plist file?

Thanks!

FS.O6
  • 1,394
  • 2
  • 20
  • 42

1 Answers1

0

CMMotionActivityManager does not deliver updates while your app is in the background (suspended). From the documentation:

The handler block is executed on a best effort basis and updates are not delivered while your app is suspended. If updates arrived while your app was suspended, the last update is delivered to your app when it resumes execution. To get all of the updates that occurred while your app was suspended, use the queryActivityStarting(from:to:to:withHandler:) method.

You could use some other background mode, such as significant location change mode, to have your app periodically resume background execution and take the opportunity to retrieve activity update, but a change in motion type on its own will not cause your app to move from suspended to background execution.

Paulw11
  • 108,386
  • 14
  • 159
  • 186
  • Look at this answer, he said you CAN get the activity in the background: http://stackoverflow.com/questions/40238591/is-it-possible-to-detect-the-users-moving-activity-on-the-background/40239325#40239325 Is it wrong? – FS.O6 Oct 27 '16 at 19:51
  • That answer is basically the same as mine; you need to use some other background mode, such as location updates to get your app to execute. You can then take advantage of this background execution to receive motion activity updates. An activity change on it own will not move your app from suspended to background execution – Paulw11 Oct 27 '16 at 19:54
  • Oh, so I'll clarify a bit: In my app I have a some region monitoring, I want to send a notification to the user when he arrives to some region (for example, "Home") just if he is walking, so I'm calling the code I added on `didEnterRegion` method, is it ok? – FS.O6 Oct 27 '16 at 19:56
  • That should work, but you may need to use the query method https://developer.apple.com/reference/coremotion/cmmotionactivitymanager/1615929-queryactivitystarting in your `didEnterRegion` to try and determine the most recent activity mode – Paulw11 Oct 27 '16 at 20:01
  • But I want the current user's activity, not from `start` to `end` – FS.O6 Oct 27 '16 at 20:02
  • The documentation for startActivityUpdates says that it will deliver the current activity to the queue, so it should work. You will need to use `beginBackgroundTaskWithExpirationHandler` in your `didEnterRegion` to prevent your app from being suspended before the closure is a called asynchronously. – Paulw11 Oct 27 '16 at 20:04