11

My app reports and records location, altitude, rotation and accelerometer data (DeviceMotion) while in the background. This works fine on ios 10.3.3. On IOS 11, I no longer have access motion data while the device is locked. Altitude data and location data is still streaming to the console, though.

Has something changed in IOS 11 that prevents me from accessing motion data or am I doing trying to access it in a way that Apple now blocks like OperationQueue.main

Here is how I'm starting motion updates. If the phone is unlocked, all works fine. If I locking the phone, no more updates.:

let motionManager = self.motionManager

    if motionManager.isDeviceMotionAvailable {
        motionUpdateInterval = 0.15
        motionManager.deviceMotionUpdateInterval = motionUpdateInterval

        motionManager.startDeviceMotionUpdates(using: .xArbitraryZVertical, to: OperationQueue.main) {deviceMotion, error in
            guard let deviceMotion = deviceMotion else { return }

I can't find anything about Motion background modes changing but it seems there must be a way otherwise RunKeeper, Strava will break. Can someone help me get this working again before IOS11 launch?

Thanks!

Nicholas K
  • 151
  • 1
  • 10
  • Having a similar problem myself. Are you using the CoreLocation background mode to keep the app active for the motion updates? – doovers Sep 21 '17 at 13:20
  • @doovers Correct. CoreLocation is in use and has previously supported the background modes needed for motion. What's frustrating is that WatchKit has a workout mode to allow access to motion in the background. – Nicholas K Sep 22 '17 at 16:43
  • Seems we're not alone on this... Check this [thread](https://forums.developer.apple.com/thread/86034). Which devices are you seeing the issue on? I've tried 6 & 7 and only 7 is not working. – doovers Sep 22 '17 at 16:50
  • I've been watching that thread for a few days. I have a support request open with Apple that's been open since Sunday. I'll post back if something happens. Please do the same. – Nicholas K Sep 22 '17 at 20:03
  • Appreciate that mate and I’ll certainly let you know if I find anything! Hopefully we can resolve this ASAP! – doovers Sep 22 '17 at 20:06
  • Have you tried upgrading your project to swift 4 to see if there is any difference? – Nicholas K Sep 23 '17 at 04:01
  • I just realized I didn't answer your question on devices @doovers. I've tested it on 7 Plus. My roommate will update their 6 tomorrow to IOS11 and I'll test there. On the thread you posted, I'm ichola. – Nicholas K Sep 23 '17 at 04:49
  • I just updated to Swift 4 with no improvement. – Nicholas K Sep 23 '17 at 06:35
  • Yes I did too. No improvement for me either! – doovers Sep 23 '17 at 07:47
  • Seems to be a 7, 7 plus issue but would be curious to know if 8, 8 plus and X are also having the same problem... – doovers Sep 23 '17 at 07:48
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/155157/discussion-between-nicholas-k-and-doovers). – Nicholas K Sep 23 '17 at 16:46
  • Seeing the same issue on iphone 7, iphone 7 plus, iphone 8 and iphone 8 plus with ios 11. With ios 10 the iphone 7 works fine. – Simon Bengtsson Oct 10 '17 at 11:45
  • 1
    Hey all. I got an email from Apple yesterday saying that the issue may be fixed in 11.1 Beta 2. Installed it last night and things look good on app. I'm having a different compile issue with Xcode Beta and haven't been able to verify things in the console yet but check out 11.1 Beta 2. – Nicholas K Oct 11 '17 at 13:54
  • Thanks for the update, downloading it now... – doovers Oct 12 '17 at 02:47
  • Unfortunately no joy for me :( – doovers Oct 12 '17 at 03:23
  • I have information that it is still **not** solved in iOS 11.1 (15B93). What is your experience? – fishinear Nov 07 '17 at 19:27
  • @fishinear It is working for me and my users in 11.1. It is also continuing to work in 11.2. – Nicholas K Nov 11 '17 at 00:54
  • Well, I experience the same issue now with release iOS 12.1.2 --- does anyone here know what has changed? I do get my updates in the background on an iPhone SE running iOS 12.0.x but not on iPhone 7 and 8 running iOS 12.1.x – Motti Shneor Dec 31 '18 at 08:28
  • @MottiShneor The only help I can offer here is saying that nothing has broken with my app in 12.1.2. I've tested on an iPhone 7 and Xs in 12.1.2. – Nicholas K Jan 03 '19 at 01:54
  • Yes - but did you try to build it again, on latest Xcode and iOS SDK? that's my point - maybe the SDK broke behaviour? If you did (build on latest SDK) and it works for you --- than I have both hope and a bug --- and I will fix it, and get this to work right. – Motti Shneor Jan 04 '19 at 07:24

2 Answers2

10

Also came across this problem.

Our solution was to ensure we have another background mode enabled and running (in our case location updates + audio) and restart core motion updates when switching background/foreground.

Code sample:

import UIKit
import CoreMotion

final class MotionDetector {
    private let motionManager = CMMotionManager()
    private let opQueue: OperationQueue = {
        let o = OperationQueue()
        o.name = "core-motion-updates"
        return o
    }()

    private var shouldRestartMotionUpdates = false

    init() {
        NotificationCenter.default.addObserver(self,
                                               selector: #selector(appDidEnterBackground),
                                               name: .UIApplicationDidEnterBackground,
                                               object: nil)
        NotificationCenter.default.addObserver(self,
                                               selector: #selector(appDidBecomeActive),
                                               name: .UIApplicationDidBecomeActive,
                                               object: nil)
    }

    deinit {
        NotificationCenter.default.removeObserver(self,
                                                  name: .UIApplicationDidEnterBackground,
                                                  object: nil)
        NotificationCenter.default.removeObserver(self,
                                                  name: .UIApplicationDidBecomeActive,
                                                  object: nil)
    }

    func start() {
        self.shouldRestartMotionUpdates = true
        self.restartMotionUpdates()
    }

    func stop() {
        self.shouldRestartMotionUpdates = false
        self.motionManager.stopDeviceMotionUpdates()
    }

    @objc private func appDidEnterBackground() {
        self.restartMotionUpdates()
    }

    @objc private func appDidBecomeActive() {
        self.restartMotionUpdates()
    }

    private func restartMotionUpdates() {
        guard self.shouldRestartMotionUpdates else { return }

        self.motionManager.stopDeviceMotionUpdates()
        self.motionManager.startDeviceMotionUpdates(using: .xArbitraryZVertical, to: self.opQueue) { deviceMotion, error in
            guard let deviceMotion = deviceMotion else { return }
            print(deviceMotion)
        }
    }
}
Simon Bengtsson
  • 7,573
  • 3
  • 58
  • 87
mani
  • 3,068
  • 2
  • 14
  • 25
  • 1
    Thank you Mani. I didn't have a chance to try this since I've been traveling. Apple released 11.1 Beta 2 yesterday and initial results are good. I need to do more testing but wanted to thank you for sharing. – Nicholas K Oct 11 '17 at 13:55
  • It seems to be working, although I reckon it's not needed to have the background audio mode activated. – inigo333 Mar 20 '18 at 11:16
  • 1
    I am using iOS 11.4.1 and the core Motion updates stop when the app goes into the background. I have enabled Core Locaton Background mode also, but with no success – Praveen Kondapalli Sep 03 '18 at 13:00
  • Thanks. First - thanks. I'm struggling with this issue for few days now. However - Is this answer still viable on latest iPhones (X, Xs, 8 etc) and latest OS version (iOS 12.1.2 ? And also - You skipped the implementation of the notification handlers. What do they do? call the "restartMotionUpdates() ? set the "shouldRestartMotionUpdates" to true? Who sets it to false anyway (when we don't need it). – Motti Shneor Dec 27 '18 at 14:47
  • hey @MottiShneor - we're currently using a version of this in our production app. The notification handlers *are* implemented. `shouldRestartMotionUpdates` is used to decide if the handlers should be restarted (hiding complexity), as the calling class only needs to call `start` or `stop`. To save battery/etc you should call `start`/`stop` as relevant. – mani Dec 28 '18 at 15:44
  • We used your scheme few days after you posted it, and it played nicely for some time. Now it stopped working for us. Maybe building against latest iOS SDK kills it? Maybe your production app - was built against older SDK? I'm out of tricks :( – Motti Shneor Jan 02 '19 at 07:22
  • OK. I tried it, (set for both Location Updates and Audio background modes) and the update-restarting dance, and it won't work for me - unless some audio is actually playing in the background all the time (not very battery friendly). If only Location updates are on - behaviour is very arbitrary. It may work for some time in BG, then cease. sometimes abruptly, sometimes slowly decrease update rate - and most annoying - it plays differently on different devices and OS versions. – Motti Shneor Jan 08 '19 at 05:50
  • Hey @MottiShneor - that sounds worrying. Let me run some tests with different background modes. We're definitely building against latest iOS SDK; but we're a music player app, and so haven't encountered this issue as we always have audio playing when we need motion updates. – mani Jan 08 '19 at 07:15
  • Has anybody found a reliable way for motionActivity to update in the background. I'm using iOS 16 now and it's still a problem. I have even tried the solution above. I think what makes it work for @mani is the fact that they are also running music in the background – RawMean Oct 11 '22 at 00:03
  • 1
    @RawMean if you don't have any ongoing background activities, motion detector will be paused. Your app needs some background capabilities to continue receiving motion updates. If you can get away with it, start silent audio or background location updated or a health kit workout. – mani Oct 15 '22 at 17:23
0

The official 11.1 release fixed the issue and I've heard from iPhone 8 users that the original implementation is working for them.

The 11.2 beta has not broken anything.

Nicholas K
  • 151
  • 1
  • 10
  • 2
    I have multiple reports now that it is still **not** working for the 11.1 release. But that is with an .xMagneticNorthZVertical setting. I've asked Apple to re-open the bug report. – fishinear Nov 12 '17 at 14:13
  • Still having the same problem on iOS 12.3.1, only works with .xArbitraryZVertical setting, was that solved in older versions? – Reham M Samir Jul 16 '19 at 20:40