I have an IOS application that uses location services.
I know that applications using location services can execute in the background.
However, I don't want my app to run in the background. If the user isn't watching it, it should not power.
Is this going to happen naturally (i.e. something special is needed for apps using location services to continue to operate in the background?)?
If not, what do I need to do to ensure the app using location services suspends when it goes into the background? If so, what? And what would need to be done to restore the app?
Thx
No problem - just do nothing. When the user switches away from your app (to another app, or locking the screen) your app will be suspended.
However, to make absolutely sure you don't do any location in the background, use the applicationDidEnterBackground and applicationWillEnterForeground notifications (or the corresponding app delegate methods) to stop and restart location updating.
Related
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
My application requires periodic location updates (every 10 minutes). In foreground and background (app not terminated) the application is working correctly. But the problem starts to occur when the app is terminated by the user.
I tried using this tutorial http://mobileoop.com/getting-location-updates-for-ios-7-and-8-when-the-app-is-killedterminatedsuspended .
It works only when user's location is changing because of startMonitoringSignificantLocationChanges. But I need locations in terminated state even if user is not changing its location.
Also, I have tried most of the stackoverflow questions but most of them gets satisfied with startMonitoringSignificantLocationChanges. But in my case it won't be enough to fulfil the application needs.
If a user terminates the app the system no longer grants it the same privileges. Background fetch operations and background location will not get executed until the user decides to start up your app again. The system recognizes this a user choice to not have this app running in any way again.
This isn't like the world of Android where an app can do as it pleases. Apple prefers user choice over what an app developer wants. This is of course good and bad as a developer. You need to provide the user with useful information about what your app is doing in the background so that they will allow it to run without terminating it. If they do terminate it, there is nothing that you can do.
I am sending user location at n time on server for tracking. Working fine in foreground and background mode. But my question is bit more theoretical.. Does my location update service remain running after i force close the app on the device?
I know i can check it on server, But sorry i don't have server access permission. So i have to be sure in which scenario my location service will stop running.
Yep it will continue to be updated when the application is sent into the background. For some official docs check here under the "Getting Location Events in the Background (iOS Only)" section.
Also, under special circumstances you can register your application to have a true background process running like Android allows. So when the user kills the background application, your app doesn't really die. The background process continues to work. Apple will only allow apps that have a necessary reason for this though. Such as a turn by turn navigation app (example from the docs).
Yes, if the application is removed from background then location update will be stopped.
iOS will only restart an app after a force close if its uses region monitoring or the significant-change location service. From the iOS Location and Maps Programming Guide section on Getting the User’s Location:
If your app is terminated either by a user or by the system, the system doesn’t automatically restart your app when new location updates arrive. A user must explicitly relaunch your app before the delivery of location updates resumes. The only way to have your app relaunched automatically is to use region monitoring or the significant-change location service.
iOS only restarts the app if it has Background App Refresh enabled:
when a user disables the Background App Refresh setting either globally or specifically for your app, the system doesn’t relaunch your app for any location events, including significant-change or region monitoring events.
How does Navita https://itunes.apple.com/us/app/navita-t.e.m.-personal/id590228620?mt=8
manage to display a call log?
If I swipe the app out of the task manager then it misses the calls, this indicates that it must presumably be using CTCallCenter's callEventHandler and is creating its own call log by saving the time/duration in response to the callEventHandler callbacks.
However if that is the case then how does it manage to do this in the background? I was under the impression that callEventHandler can only be used by apps in the foreground and not in the background?
The app is using location services, however even after disabling this it was still able to get information about the calls (provided the app isn't suspended). I though it might be using background location updates to keep itself primed to receive callEventHandler callbacks but apparently not.
The Navita app is additionally able to display call time and call duration.
The bounty will be awarded to an answer which contains sufficient, accurate and detailed information that enables me to emulate the behavior of the Navita app, specifically I must be able to write an app that can obtain the time and duration of a phone call that occurred while the app was not in the foreground, while the device's location services was turned off, and after the app had been in the background longer than the ~3 minutes granted by using beginBackgroundTaskWithExpirationHandler:
Here is what I observe with the Navita app that I want to be able to reproduce:
1) Run app
2) Task away from app
3) Go to device settings, privacy, and turn off Location Services.
4) Go to device settings, privacy, background app refresh and turn off for the app
5) Wait > 10 minutes to make sure the app is not still in the background as a consequence of using beginBackgroundTaskWithExpirationHandler:
6) Call the device from another phone, answer the phone call, then hang up.
7) Launch the app again and display the call time and duration
(This is iOS7 and unjailbroken)
Here is what I've found from Navita TEM disassembly and it's resources.
Application uses two background modes - location and audio. You can see it in the Info.plist file. When you enable phone calls logging application will also enable "alerts" and "Real-time" switches. When "alerts" enabled application infinitely loops in background "bg-sound.mp3" file which has no sound, it's just silence. Because of that it doesn't use hacks like this one How to get a call event using CTCallCenter:setCallEventHandler: that occurred while the app was suspended? . It's similar trick to location used in order to keep the app running in background and receive phone call events. Somehow this was not rejected from the AppStore.
If you are observing the call center while the app is in the background you get a set of updates when the app is brought back to the foreground. This set of data may not be as accurate as if the app had been mostly in the foreground but it does include quite a bit of info.
The Cardcase application lets you know if you approach a shop which you have a previous relationship with (if you've set up a tab for payments there etc.).
If background running applications cannot be started automatically on device boot, how does this app therefore work?
Edited to make my question clearer: I am not asking how to monitor for location changes or how to monitor for location changes in the background. My question is, if the user install this app, then adds some tabs for some locations, then they reboot their iPhone, then how can this app subsequently notify them when they approach a location if application launch on boot is not supported?
Must this application (and indeed any other application) be dependent upon it being launched explicitly by the user following every device reboot?
You can do this with region monitoring. You register regions that you would like to monitor with this method on CLLocationManager:
- (void)startMonitoringForRegion:(CLRegion *)region desiredAccuracy:(CLLocationAccuracy)accuracy
Then even if your app is not running, it will be launched in the background as the user enters or leaves the region.
From Apple's docs:
If you begin monitoring a region and your application is subsequently
terminated, the system automatically relaunches it into the background
if the region boundary is crossed. In such a case, the options
dictionary passed to the application:didFinishLaunchingWithOptions:
method of your application delegate contains the key
UIApplicationLaunchOptionsLocationKey to indicate that your
application was launched because of a location-related event. In
addition, creating a new location manager and assigning a delegate
results in the delivery of the corresponding region messages.
EDIT
Just tested this with my own app. Rebooted my phone before leaving the office, and the app was launched on my drive home as usual. So yes, this definitely survives a reboot.
Hope that helps.
This works for geo-fencing apps (apps that use startMonitoringForRegion).
My guess is that when you install apps using this class, the responsible iOS framework automatically registers an launchd script for the app background service startup inside iOS.
Of course this is all done automatically as you don't have fine control on iOS launch services unless you're jailbroken.
You can use the startMonitoringForRegion on your app, jailbreak your device and check on launchd to check how this works under the hood.