My understanding since iOS 13 is that background location permissions can only be granted by the user after they have already granted foreground location permissions, and the app is in the background, when a location event which would have triggered the app's background location occurs. At that point they get a dialog something like:
Allow “App” to also access your location even when you are not using the app?
Every app I've used has the same behaviour, except one app, which is able to present that dialog immediately after asking for the foreground location permission dialog:
How does this app immediately and repeatedly trigger the background location dialog like this?
If your app has asked for and received "when in use" authorisation it can then ask for "always" authorisation to trigger a second permission dialog. This behaviour requires iOS 13.4 or later.
You should consider the user experience. I suggest that your app explains why it needs always authorisation before asking for it, otherwise the user may be peppered with permission requests
Related
Is it possible to check permission status while app is closed on iOS? My use case is I want to send out a notification at periodic intervals if the app does not have the “Always” location turned on.
Follow this Using Background Tasks to Update Your App.
You can do something when app is wakened by system to run in the background.
But if the user explicitly denies the AlwaysAuthorization permission, you should not ask the user periodically. It is very bad UX.
AppleStore reviewers may reject your app also.
I think you should find a suitable way to ask the user or only show a warning popup when the user opens app and use the function that requires AlwaysAuthorization. Or ask the user to grant this permission on the first app runs.
Changes in authorization state are typically detected using the locationManagerDidChangeAuthorization event in CLLocationManagerDelegate. However, when the app is closed, the user's status cannot be detected. You can use this method to detect the change of authorization status when the user is using the app.
For more details, you can refer to the following docs:
locationManagerDidChangeAuthorization
I'm creating an app that uses location services. I need to provide our backend with continues location updates (even when the app is in the background). For this case I have enabled Location Updates Background Mode.
Now my problem is I'm not 100% sure what authorization is required for this.
Do I need to ask for "Always" or is it enough to get "When in use" authorization from the user to be able to process location updates in the background.
I'm not interested in starting the app, on location updates, if it has been terminated (ex. significant location change).
It depends on your needs. If you need the location to be fetched when the app is in not-running state (that is, when the user switched on the device without opening your app, or if the user has terminated your app), you need "Always" authorisation. If not, then you only need "When in use" authorisation.
I think you have to use "Always" in your case when you want the location update while app is in background or not running, according to this link
In my application I'm using Geofencing to track whether customer is currently present in the specified location while delivering an order.Is it possible to update his status to a server when he enters or exits geofence even when the app is in background?
It depends on what kind of location authorization you have. If you have 'always' authorization, you would be able to do it. If you have 'in-use' authorization, you would have a very small amount of time (~10s) to make the request before iOS suspends your app.
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 faced with a situation where we would like to kick off a particular process based on whether or not a user has locations services enabled or not. This part is trivial. However, we want to extend this functionality by changing our process if the user turns the locations services off or on. We currently are able to monitor, and change or process, when the user turns off location services. My question is, how can our app be notified when the user turns locations services back on?
Here is what we are currently working with
iOS 7
Background Location Mode is enabled
We are using request always for location services
Here is what we tried
We have tried setting a timer after a user turns off the location service to periodically check if the user turns back on the location service. This is less than desirable for many reasons. Besides that the timer is killed once location services is turned off because background services is no longer needed and the OS kills our process. This is understandable.
We also went the approach of notifying the user that they just stopped a process and they need to turn location services back on. There are two problems with this approach.
If the user does not have notifications enabled then this approach is no good at all.
If they do have notifications enable then we first need the user to turn the location services back on and then they would need to open the app back up to get our app to "wake" back up.
Thank you in advance!
After hours of research and implement trying to a solution we have discovered that this is not possible as of iOS 8. For reference here is what we found:
We were able to be notified when the user had shut off the location services, ONLY if they shut off location services to our app. We did not receive a notification if the user shut off the main location services.
We did not receive a message if the locations services was turned back on, regardless, if it was our location service or the main location service.
You cannot use a timer approach because the timer is killed if the app is sent to background. So we could not have periodically checked. This would not have been acceptable for our use case but it was worth entertaining
You can still call CLLocationManager as if you had permission to use location service, even if you don't have permissions.
If you do call the CLLocationManager you will start receiving location messages, after permissions have been granted to your app, without having to re-register to receive location messages.
Our solution:
The combination of 4 and 5 was our saving grace. We were faced with an edge case where a user could have been eligible for a location event trigger but previously had denied use the location services and then after becoming eligible the user grants us permission to use location services. After doing a little refactoring we moved our location manager so we would register for location event updates, specifically geofencing, even if we did not have permissions. After testing we found that in the edge case event we started receiving location updates even without having to reinitialize the location manager. The same applies to beacon region monitoring for anyone interested.
Just check your location services after app has entered foreground.
NotificationCenter.default.addObserver(self, selector: #selector(applicationDidEnterForeground), name: UIApplication.didEnterForegroundNotification, object: nil)
func applicationDidEnterForeground() {
print("Location services enabled? \(CLLocationManager.locationServicesEnabled())")
}