36

With the M7 chip in the latest iOS devices one can get programmatically notified as the user goes from stationary to running, walking, etc using CMMotionActivityManager. Stava and Runkeeper have both used this to auto-pause GPS polling (shut off the GPS antenna) when it detects the user isn't moving via the M7, and then re-enable GPS updates once they are moving again. It is able to do this while the app is in the background state, which is the key here.

The issue I run into while duplicating this functionality is that if I turn off GPS updates while my app is in the background I stop receiving activity updates, and can no longer detect when the user moves again via the M7 to turn the GPS back on.

If I leave the GPS running the whole time I'll continue to get movement updates from Core Motion the entire time the app is in the background.

I'm assuming they aren't playing white-noise or some other cheap trick to stay active. How did they go about this?

Mobiletainment
  • 22,201
  • 9
  • 82
  • 98
Parrots
  • 26,658
  • 14
  • 59
  • 78
  • See [this answer](http://stackoverflow.com/a/19085518/1693173). Setting `desiredAccuracy` to 3km shuts down the GPS but the app continues to run. – progrmr Nov 20 '13 at 23:43
  • possible duplicate of [Periodic iOS background location updates](http://stackoverflow.com/questions/19042894/periodic-ios-background-location-updates) – progrmr Nov 20 '13 at 23:43
  • @progrmr gave that a shot - the GPS indicator stays active at 3k. Both Runkeeper and Strava do something that turns off the GPS indicator (which pretty much means calling stopUpdatingLocation) when stationary. His approach seems to rely on 3k = cell-tower polling only. But 3k does not guarantee cell-only, and in weak cell locations this is still a drain I want to avoid. – Parrots Nov 21 '13 at 17:29
  • This is a little tricky but I imagine a triplet solution. What if you used beginBackgroundTaskWithName:expirationHandler and backgroundTimeRemaining to check UIAccelerometer data from CoreMotion and upon an event that appears like forward motion, reactivate GPS, else reactive GPS at termination of backgroundTimeRemaining or significationLocationChange? – Meshach Jan 28 '14 at 20:44
  • @Parrots..@Jan Did you find anything? I'm searching for the same thing. – Ashok Jan 21 '15 at 10:47
  • The closest guess I have is the audio trick, but no I haven't found any way besides that. (Kinda skeptical on the audio trick because wouldn't they need to play silence to keep the app open w/ no audio playing otherwise) – Parrots Jan 22 '15 at 00:38
  • @Parrots did you manage to do this in a legal way? – Desert Rose Feb 08 '16 at 06:02
  • @Parrots Did you finally manage a way to do this. I need something similar i.e. monitor motion updates while app is in background or suspended/not running – Dibzmania Mar 21 '19 at 22:21

5 Answers5

17

RunKeeper actually does use the audio trick to stay awake. If you open up the app package and check their Info.plist you will see that it registers for the background audio mode. This is how they pull off periodic audio notifications of your distance, speed, and pace. It is also how they stay awake during your run while minimizing battery drain.

If you noticed that the Location Services icon (the triangle in the status bar) disappears completely while using RunKeeper then they definitely are not using any type of location tracking to accomplish background execution. Even activating geo-fences and significant location change monitoring would cause the Location Services icon to appear.

They also aren't using the M7 to stay awake because it doesn't work that way. An update from the M7-related CoreMotion APIs will not wake up your app from sleep. When they app does wake up they would be able to query the Motion Activity and Step history and maybe try to compute something, but I doubt it would be all that accurate.

Finally you should note that the Auto-pause APIs were introduced in iOS 6 before the release of the iPhone 5s and M7 chip. They are orthogonal concepts.

Mike Gottlieb
  • 966
  • 6
  • 11
  • The presence of background audio declaration in RunKeeper is not proof of an audio keep-alive trick. They play speech to notify you of your progress while running, often while the App is in the background. This would require the flag. – Chris Hatton Feb 10 '15 at 03:20
  • 3
    I was thinking mainly of the Runkeeper Pedometer pre-M7. Their only audio feature was a beep every 1000 steps. It is circumstantial evidence and just a theory of mine, but it is exactly how it would work technically and still get approved by Apple. – Mike Gottlieb Feb 10 '15 at 03:24
  • 1
    I read it somewhere that if we use VOIP just to keep alive then app gets rejected.is there any legal way to do this? – Desert Rose Feb 08 '16 at 06:01
  • Knock to unlock app proves this info is no longer accurate. – ChuckKelly Apr 18 '16 at 06:03
  • Why is that @ChuckKelly ? Looks like the same principe as this answer. – Sjoerd Perfors Jul 14 '16 at 09:27
  • You can use VOIP as long as you have a reason for using it that Apple deems legitimate. If you try to use VOIP because it is just a workaround for general background execution then you will probably get rejected. Then again it is always kind of a roll of the dice. – Mike Gottlieb Jul 14 '16 at 16:22
1

have you considered experimenting with

application:performFetchWithCompletionHandler: 

in the app delegate? You can't control how often it is called, but depending on the app, it can be every ~15 minutes. You can then launch the CMMotionActivityManager from there to query M7 results.

It's not entirely clear what functionality you are trying to replicate, but the M7 chip records all of the activity, regardless of whether your app is running. So you can simply query in the background and update step totals or activity type totals.

0

What I noticed when you turn off GPS, app will not execute any code in background for iOS 7, app looks like in inactive state. So better while moving to background use startMonitoringSignificantLocationChanges and also get updates from your location manager. Means simultenoulsy use both service startUpdatingLocation on user state change and startMonitoringSignificantLocationChanges in Background.

So when user Turn on GPS, while you used startMonitoringSignificantLocationChanges your app will receive

- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations

Better check here in background itself what wrong with CoreMotion Framework. And try to restart it. Because wihtout M7 chip device I am able to read Accelerometer reading in such case.

Bhumeshwer katre
  • 4,671
  • 2
  • 19
  • 29
0

If your location manager is working in Active mode, to enable background mode you need to do this three steps:

  1. Check that [Target / Capabilities / Background Modes / Location updates] is enabled.
  2. [locationManager requestAlwaysAuthorization];
  3. locationManager.allowsBackgroundLocationUpdates = YES;
-2

First, check if you have set up the background behave of your app.

Go to target - capabilities section and check Background mode for location updates.

XCode Capabilities

Jesús Hurtado
  • 295
  • 2
  • 12
  • Thanks, but this does not help. The background aspect is enabled, the problem is if I turn off GPS polling when the M7 reports stationary, the app is fully-backgrounded and can't resume. – Parrots Jan 30 '14 at 14:19