location services (CLLocation) requires explicit user action

I struggled a while yesterday with getting location services to work, and figured it out this morning.


tl;dr: From Settings app on TV:

Settings -> General -> Privacy -> Location Services -> Apps. Choose your app, and enable the needed location service level.


Here's what I had:

  if status == CLAuthorizationStatus.NotDetermined {
  print("requesting authorization")
  locationManager.requestWhenInUseAuthorization()
  }
// and then later...
  locationManager.requestLocation()


Info.plist had the correct NSLocationWhenInUseUsageDescription entry.


When I executed that code, and then queried CLAuthorizationStatus, the value came back as .NotDetermined. Repeatedly triggering the requestWhenInUseAuthorization() did nothing.


Calling .requestLocation() eventually triggered my CLLocationManagerDelegate's locationManagerDidFailWithError():

locationManager didFailWithError The operation couldn’t be completed. (kCLErrorDomain error 0.)


I tried adding "location-services" to the "Required device capabilties". That generated "Can't install application: Mapbox Static TV.app cannot be installed on Apple TV. Mapbox Static TV.app requires the “location-services” capability which is not supported by Apple TV."


I finally went digging in the Settings menu, and saw my app listed there, with a blank authorization status. Siri was listed "while using the app", and Time Zone was listed "always". Choosing the app brought up an alert, to select "while using the app" or "never".


After I made that change in Settings, my first call to CLLocationManager.authorizationStatus() returned .AuthorizedWhenInUse, and my first call to .requestLocation() had the correct value in it.


Back to Settings. Set my app's permission to "never". Relaunch. Now I immediately see "denied" as status, and didFailWithError shows

locationManager didFailWithError The operation couldn’t be completed. (kCLErrorDomain error 1.)


There's never a challenge generated by the system to choose location services permission, as you would see in iOS or OS X. Solution for the moment seems to be to query authorizationStatus(), and if it's showing .NotDetermined, put up your own instructions on what the user should do to authorize location services.


I'll update this with a Radar number once I file it.

Further observations:


When the app is in the state of never having had a Location Services setting applied through the Settings app, the Apple TV log shows

Sep 19 11:41:40 Apple-TV locationd[56] <Notice>: ERROR: com.mumble.foo is depending on legacy on-demand authorization, which is 
not supported for new apps


When the app has been given permission to see location through Settings.app, the call to locationManager.requestWhenInUseAuthorization() is not necessary. Asking for location succeeds even when that function has not been called.


The Info.plist key NSLocationWhenInUseUsageDescription is necessary, but the string value is never displayed to the user. If you omit that key, your app doesn't show up in Settings.app's list of apps that can use location.

It's rdar://22772216, sample project attached.

So I had a few problems getting to show my app under Location Services. Not only did I need to make sure I had the correct key-value pair set in the Plist for WhenInUse, but I also needed to make sure:


  1. I made my CLLocationManager call requestLocation
  2. I had to have a delegate for my CLLocationManager instance
  3. You -have- to implement the delegate methods (can be blank).


After all of those were done, my app magically showed up in Settings and I could turn it on to use location services, just as Halm mentioned.

In order for my app to appear in the list under Settings so I could manually authorize Location Services for it, I had to call requestLocation() even though the authorization status was .NotDetermined.

Make sure you have set a value for both CFBundleDisplayName and NSLocationWhenInUseUsageDescription in your Info.plist.

This appears to still be an issue in the tvOS GM seed, has anyone found a workaround for the request access dialog not showing up ? It really isn't cool to have to tell users to manually go to setting and turn on location services for your app.

I finally got the location services dialog to show, for me the problem was not having the CFBundleDisplayName present, I had CFBundleName but you have to have CFBundleDisplayName and NSLocationWhenInUseUsageDescription in your info.plist file just as TidBits posted earlier.

Thanks for this! It does appear that new tvOS targets do not include this key.

location services (CLLocation) requires explicit user action
 
 
Q