iOS: Continous Background Location Updates - ios

I need to work on an app where accurate location updates are needed to run on the background.
I can see this paragraph from the iOS App Programming Guide:
An app that provides continuous location updates to the user (even when in the background) can enable background location services by including the UIBackgroundModes key (with the location value) in its Info.plist file. The inclusion of this value in the UIBackgroundModes key does not preclude the system from suspending the app, but it does tell the system that it should wake up the app whenever there is new location data to deliver. Thus, this key effectively lets the app run in the background to process location updates whenever they occur
However, I do not quite understand what happens in the background. Does the app keep the same accuricy measurement determined in the foreground location services? if so, how long does it keep up running in the background?

It does keep running in the back ground, till it is suspended by the iOS because of lack of resources. As long as it is in the back ground. A simple example would be for you to NSLog the location and then connect the iPhone later to your XCode and look at teh console. Not sure how long of an operation you can perform though, but I am pretty sure you can do some basic core data insertion.
Take a look at this cool tutorial http://mobile.tutsplus.com/tutorials/iphone/ios-multitasking-background-location/
Which gives you a project which you can play around with.

Related

React Native iOS app restart on reboot

I want to create an iOS app using React Native. One of the primary features of the app is that it runs constantly in the background. It also requires using GPS btw (in case that is important).
I have had a number of devs tell me its not possible to do this for iOS, however I have read that it is do-able.
Is this possible to do in the iOS environment? Mainly, if the app is running when the phone is powered off, can you make it open when the device is restarted without the user opening it?
I should say that I am a RN novice and any help is much appreciated.
If your app gets permission to get location while it's not in the foreground, then you will get periodic updates and some time to process it.
For example, if you are giving driving directions.
https://developer.apple.com/library/content/documentation/UserExperience/Conceptual/LocationAwarenessPG/CoreLocation/CoreLocation.html#//apple_ref/doc/uid/TP40009497-CH2-SW10
If there is no good user benefit for you to get the location in the background constantly, you might be rejected. Apple suggests region monitoring instead
iOS supports the delivery of location events to apps that are suspended or no longer running. The delivery of location events in the background supports apps whose functionality would be impaired without them, so configure your app to receive background events only when doing so provides a tangible benefit to the user. For example, a turn-by-turn navigation app needs to track the user’s position at all times and notify the user when it’s time to make the next turn. If your app can make do with alternate means, such as region monitoring, it should do so.
I have no idea how RN wraps this behavior, but no matter what it does (or what a plugin might do), the core iOS behavior is how it is described in that URL.
I verified yesterday (at least on iOS 11.2 simulator) that automatically restarting the app (and the location tracking) after phone reboot works.
The key point is that startMonitoringSignificantLocationChanges needs to be on to wake up the app after reboot. For me the difficult part was figuring out when to turn it on, because I couldn't find a reliable way to detect when the phone is being rebooted or run any code at that point. However, based on initial testing it looks like startMonitoringSignificantLocationChanges is independent and doesn't negatively impact the usual location updates, so now I just leave it on all the time and toggle startUpdatingLocation / stopUpdatingLocation on top of it based on Core Motion-detected activity.
Otherwise requirements are the same as for any location tracking on the background, i.e. handle permissions and don't process too much. Apple documentation explains how to detect that the app was relaunched by a location event.
Here's a react native module which basically helps you achieve what you're describing: https://github.com/transistorsoft/react-native-background-geolocation

Getting continous user location and based on that sending information to server

I've got a concept of adding feature to my app which will register user location in interval of few seconds. Then sending this coordinates through cellular or Wi-Fi all when staying active in background. I need to send this in almost real time, so the app can't be killed in backgorund.
I know this concept is very power consuming but it is only a conception.
The conception of getting constant location in backgorund is in this theard https://forums.developer.apple.com/thread/69152
so I think it is possible.
But refreshing only the process in my app of sending coordinates to server it's a little bit difficult. I could not get straight answer that it is possible to set the time interval in which the app will refresh in backgrund.
Is there a method for telling the app how often it should refresh in background?
Apple won't let your app idea onto the app store. They're quite strict about which types of apps are allowed to run in the background, and are allowed to use continuous GPS. (Both of those things really drain the user's battery.) Sending a continuous stream of location updates to a server will also keep the cellular/WiFi transmitter powered up, making things even worse.
For your own experimentation, though, you can probably set up your app to be a navigation app. Those are allowed to keep the GPS "lit" constantly and to run in the background. You could then set up the location manager with the highest accuracy setting and start updating your location.
I don't think you have the ability to control how often you get location updates though. You could create a timer that fires on a regular interval and fetches the current location from the location manager. However I don't think there's much value in that, since you WILL get called when the user's location changes, and fetching the current location more often will just give you the same answers repeatedly.

How to do BG NW download after geofence didEnterRegion/didExitRegion notice

I am developing a client/server app for a client where the clients are iOS devices.
One client module is for traveling salespeople.
My client wants the salesperson's app to automatically download it's local database when the salesperson leaves the office, and when the salesperson returns to the office.
I am setting up a geofence using the location manager's startMonitoringForRegion method, and will look for the UIApplicationLaunchOptionsLocationKey on launch, as well as looking for calls to the location manager locationManager:didEnterRegion/locationManager:didExitRegion methods from the background.
My question is, how do I ask the system to allow me time to make a network connection and download new data in response to either an app launch with a UIApplicationLaunchOptionsLocationKey, or background calls to locationManager:didEnterRegion/locationManager:didExitRegion?
None of the background mode keys (UIBackgroundModes) look like the right fit.
I don't need the location key, since I don't need live location information, just geofence enter/exit messages. The fetch key isn't what I need either, since that causes the system to wake my app up in the background at times it chooses.
Do I have to have one of the background mode keys set in order to make a beginBackgroundTaskWithExpirationHandler call?
I guess what I should do is submit my network request in my beginBackgroundTaskWithExpirationHandler in my locationManager:didEnterRegion/locationManager:didExitRegion methods. Will the system allow me to do that without having a UIBackgroundModes key set?
And can I make a call to beginBackgroundTaskWithExpirationHandler if I'm already running from the background? (In the case where the app is running but not frontmost and a locationManager:didEnterRegion or locationManager:didExitRegion call comes in.) My goal is to ask for enough background time to process my network download and save the data to my local database.
Any guidance from somebody who's done something like this would be a big help. The docs are pretty vague, and figuring out how to use the background APIs by trial and error is likely to be pretty time-consuming.
P.S. I'm developing this app in Swift, although I'm a longtime Objective-C developer. I'm comfortable translating Objective-C to Swift or mixing Objective-C and Swift as needed, so examples in either language would be useful.
It is OK to call beginBackgroundTaskWithExpirationHandler from background. As of iOS8 this call will extend your run time to 180 seconds from 10s.
Keep in mind that you need to request Always authorization for location services, that's what is required to run region monitoring.
I suggest you do use the background location key. I forgot to set it in one of my apps, and it still was receiving the region enter/exit events. However,
-- the behavior might change with minor iOS upgrade, and also
-- the app might be rejected by Apple

Play background music would be rejected by Apple Store?

I produced a pedometer program in ios.I want it can work in the background,But I found it would interrupt finally.So I add a AVAudioPlayer and play a silence music when in the background and it works right.
Now I want to submit to the App Store.I worried that I would be rejected.can anybody tell me about sth?
If this way doesn't work,How can I run a pedometer in the background?
(ps)I need to support the device without M7
Yes you will be rejected. You cannot do tricks like that just so you can have your application run in the background. It's like declaring your application as a VOIp app just so you can run background processes.
I suggest you have a legitimate feature that requires the background process otherwise your application will be rejected.
Have a look at this link and search for the heading UIBackgroundModes to see the 6 UIBackgroundMode keys:
UIBackgroundModes (Array - iOS) specifies that the app provides specific background services and must be allowed to continue running while in the background. These keys should be used sparingly and only by apps providing the indicated services. Where alternatives for running in the background exist, those alternatives should be used instead. For example, apps can use the signifiant location change interface to receive location events instead of registering as a background location app.
I do feel that you can have your application run in the background if you use some location services in your application. Then, quite possibly, could you register your application under the location's key:
The app provides location-based information to the user and requires the use of the standard location services (as opposed to the significant change location service) to implement this feature.

Processing network calls from background. Is it allowed by Apple?

We are working in a groupon-like app where alerts are displayed to the user when he/she enters in the range of an offer.
The client insists on having alerts even when the app is in the background.
Due to the architecture of the system, the app gets the location of the client at intervals and checks with the server if there is any new alert. If so, the app does some processing in the local database and displays a notification.
APN cannot be used since changes in the server are out of reach for this project.
My question is whether Apple would accept it in AppleStore as I have read different opinions about it and Apple discourages its use as in this extract from iOS Developer Library
http://developer.apple.com/library/ios/#documentation/userexperience/conceptual/LocationAwarenessPG/CoreLocation/CoreLocation.html
At wake-up time, your app is put into the background and given a small amount of time to process the location data. Because your app is in the background, it should do minimal work and avoid any tasks (such as querying the network) that might prevent it from returning before the allocated time expires. If it does not, your app may be terminated
Thanks
How often does your app get location from the user? According to Apple's Background Execution and Multitasking, if you are getting the location updates on a regular schedule (I think it's less than 10 minutes), your app can still process in the background if you add location to UIBackgroundModes in your info.plist. With those CLLocation coordinates, you can then process your web service requests.
I personally have not done something like this, so I can't tell you for sure if Apple will reject your app or not. However, if everything is within the guideline and requirements set by Apple, I don't see why they would reject your app.
EDIT:
From the Apple doc:
An app that provides continuous location updates to the user (even
when in the background) can enable background location services by
including the UIBackgroundModes key (with the location value) in its
Info.plist file. The inclusion of this value in the UIBackgroundModes
key does not preclude the system from suspending the app, but it does
tell the system that it should wake up the app whenever there is new
location data to deliver. Thus, this key effectively lets the app run
in the background to process location updates whenever they occur.
I guess even if the app is suspended, it will wake up whenever there is a new location data to deliver.
I think you should reconsider your approach for this application. It sounds like you have decided to build a set of features which are not necessarily well informed by, or a good fit for, the characteristics of the devices the app will run on.
You write that "the app gets the location every n minutes" but that's not how iOS location services work. Querying location services for the current location occasionally is a good approach when your app is running in the foreground but that's not an option once it is suspended or terminated. Instead you need to subscribe to location events, at some level of accuracy, and your app will be notified when the device's location changes. There are no guarantees about the schedule on which you receive these events and it varies depending on the accuracy you request and the speed at which the device is moving.
Additionally, obtaining a location is an expensive operation and can quickly drain the device's battery. Burning through a user's available battery power in an hour or two is a very good way to get your app uninstalled quickly. Where possible you should be using the significant location change service to get low accuracy location updates with minimal power consumption. If you need more precision then consider using boundary crossing events for a defined region or at least reduce the accuracy your have requested as much as possible.
With all that out of the way you still need to work within the limited time your app has to run once started by a location update. That's probably not long enough to make a round trip to the server. If a network connection is already active and the device happens to have low latency you will probably get a response some of the time but I would expect to see the app terminated by the OS frequently. When that happens I don't know that you will continue to receive location updates which might otherwise re-launch the app.
Instead of downloading a list of alerts and displaying them locally a better solution might be to attempt to send your current location to the server via UDP when you see a significant location change. That way you can fire off a network request without waiting for a response. Only some of those requests will still succeed but at least your app won't be terminated. You can then process the locations you receive on the server and send push notifications when appropriate.
I realize that you don't seem to be able to make server side changes. In that case the best you might be able to do is pre-fetch alerts for the nearby region when the app runs (and if you ever manage to complete a round-trip while in the background). That way you could compare location updates to that list and not need to fire off a network request on every location update. Unfortunately it sounds like you might be backed into a corner here with no reliable solution available under your current constraints.

Resources