Is it possible to have the phone power up the GPS every say 30 minutes and get the user's location while the app is in a background state?
The significant location change service is a little too unprecise for my needs.
I am 开发者_开发百科trying to track a phone at all times without killing the battery life too much. Any suggestions are more than welcome!
I know this is "late", but since this is still an issue as far as I know (always looking for a fix - if there is a recent change please post)...
The responses here cover most of the bases unfortunately, but my experience might be somewhat helpful. Using the VOIP flag to allow your app to wakeup at intervals and do some processing (like GPS) works great, BUT Apple review won't allow it unless you are in fact using VOIP. We had an app in the AppStore that did this trick. It worked beautifully - very low batter consumption, perfect GPS tracking. After a couple of updates some smartass reviewer (probably an automated check now) recognized the flag but that we were not really using voip and rejected the app. Ever since we had just turned of background GPS tracking - not much choice when battery life drops to 90 minutes with constant GPS burn.
The other comment related this was why the timed GPS collection dies in the background when not running in a debugger - it dies because the active threads stop or expire (if you have bought some time to complete some tasks),and there is no way to resurrect any background activity based on an internal timer. Some sort of periodic notification might work (I'm going to try that approach) or worst case a periodic push notification... but it probably does not buy enough time to get and report an accurate GPS location, so you'd be once again in a position to leave the GPS running. Our app has a "force background GPS" mode that is intended to be used only when the device is plugged in so there is no battery drain, but that's the best we have figured out so far.
The absolute worst case (almost forgot this one) is the wake on significant change option, but that has been shown to be both inaccurate and much to far apart (yeah, a couple miles is significant but what good is that for real tracking).
The periodic wakeup approach worked so well, and was in the best interest of the user by far (to conserve battery) that I was flabbergasted that Apple did not allow it for this purpose. A major oversight in support for location based apps.
Apple only gives you two options, which happen to be two extremes:
- Use GPS multitasking (kills battery life because it's on all the time).
- Use local notifications or push notifications timed every 30 minutes (or whatever interval) that opens the app when the user hits Okay.
I have a very similar requirement: my app is supposed to take highly accurate location snapshots at a periodic interval (typically 1 minute) and it has to do so even if the device is sleeping or the app is in the background.
To accomplish this in the foreground I implemented a system which turns on the location service, waits for a location of the desired accuracy, then shuts off the service until a timer fires. This process repeats and seems to work as expected: half a dozen inaccurate location readings are returned (in the space of a few seconds) before an accurate one is received.
Testing has shown that this approach WILL work when the device is sleeping, which surprised me! So now we just have to worry about when the app is backgrounded.
Here is the mechanism I am using to extend this to data collection while in the background:
Set the info.plist value to indicate that location updates are needed by the app, even when not in the foreground. This is documented in the "Tracking The User's Location" section of the Apple SDK docs. It guarantees that location updates will be delivered to the app even in the background, or sleeping.
However, this approach doesn't allow (out of the box) a periodic collection, but, instead notices are sent whenever the location services see a location change as defined by the desired accuracy value.
Unfortunately, if you turn off location services data collection after the app is backgrounded it no longer receives notices (the app is in the background, remember?). So I'm exploring using the setKeepAliveTimeout:handle method on UIApplication to ALSO do a periodic check, effectively replacing my foreground timer. [Note -- to register the KeepAlive handler you also have to set the info.plist to indicate the app is doing VOIP] When the KeepAlive handler gets called it turns on location services in the handler, gather data, then turn off the location services. Testing has shown that this DOES re-start the location services notifications. But I'm seeing the KeepAlive handler only getting called at 10 minute intervals (600 seconds) and I'm not sure if that is good enough.
Note that the setKeepAliveTimeout:handle method is intended for VOIP applications, and apparently Apple examines apps that use it VERY closely. In my case this is an app for a client who uses Wireless Distribution, not the Apple store, so it isn't an issue for me.
However, if this approach works it seems to satisfy a need not met by the Apple API: balancing the need for highly accurate location data, while only collecting that data at intervals to conserve battery life. Apple really should support a timed collection model, and not just based on accuracy. Ah, well!
Cheers
精彩评论