Acquire user location from notification action

Hey,


I'm trying to let the user send her/his current location through a notification action (via application:handleActionWithIdentifier:forRemoteNotification:completionHandler:). However, I'm unsure if this will really work, since AFAIK that delegate method will be called from the background and there is no way to start a location manager from the background, correct?

Is there maybe a way to use the iOS 9 method requestLocation: to do this?

Replies

If I understand correctly, you are not trying to start monitoring the users location, but just get the current location.

requestLocation: sounds like exactly what you need.


BTW, it is possible to start location updates in the background. They will start and work as long as your app is active.

What won't work is your app will not be kept active in response to the location updates in such a case.


The end result might be the same, but the technical details are different, for those who care.

Hey Gualtier,


thanks for your your feedback. By "[...] it is possible to start location updates in the background. They will start and work as long as your app is active." you mean, that location updates will be processed as long as my app has background time to run, correct (I'm a little confused by the term 'active' since my app remains in the background)?

So is this why it's not working in my case? I get a push notification and use a notification action to act on it - so the app is not opened, but instead application:handleActionWithIdentifier:forRemoteNotification:completionHandler: is called. From this method I tried calling requestLocation: but it works only half the time - I haven't figured out the conditions for this exactly but I think it only works if the app has recently been active and is in an inactive state. However, it seems that this won't work if the app is killed and then "woken up" by the push notifications. Can you confirm that?

Apologies for the confusing terminology. By "active" I meant to say non-suspended in the background.


So, when you app is in suspended or terminated mode, and the user interacts with the notification, your app is given background execution time for a limited time. You can start a location request then, and it will run as long as your app is still executing within that time. But your app won't be given additional time to wait for the results of the location service.


requestLocation has a time limit. If it can't obtain the location in a timely manner, it will error out and will call the didFailWithError method instead.

If you implement this method, you can check the error and see what is causing the problem.

If requestLocation is only working part of the time, especially after a while, I can think of a couple things:

- the location hardware may have been powered down and it takes longer than the allowed time to get a fresh fix, depending on your environment at the time

- if you suspect that it is not working after your app has been terminated, please make sure you are re-instantiating your location manager and other related objects, as your previous memory objects have all been destroyed by then.

EDIT: After some trial & error I was able to answer some of my own questions below. AFAIK now the location usage has to be set to "Always". So don't forget to set the NSLocationAlwaysUsageDescription key within your info.plist.

It won't work with "In-Use".

Next, background mode for "location" has to be set within Capabilities.

Last but not least make sure you instantiate your location manager on the main thread. I quarreled with this for quite some time since the notification callback within AppDelegate is called on a background thread and at first this was where I instantiated my Singleton Location Manager. After making sure that this happened on the main thread everything works now!

On a side note it would be great if the "requestLocation" method also worked without requiring the "Always Authorization", especially within the AppDelegate's handleActionWithIdentifier callback, since this is actually a foreground operation (from a user's perspective).


====================================================


Thx a lot, I'll give this another try. One more thing I'm wondering? Will I need to request authorization to "Always" query location, or just "In-Use"? And I guess that goes hand in hand with the question if the background mode for "location" has to be set?

I know that I'm processing from the background at this point (in reaction to a push notification action) - so I guess at least the background mode "location" has to be set? But since this is in reaction to a user interaction my gut says that this should only need the "In-Use" authorization. Is that right?