@@ -50,10 +50,12 @@ @implementation OneSignalLocation
5050os_last_location *lastLocation;
5151bool initialLocationSent = false ;
5252UIBackgroundTaskIdentifier fcTask;
53+ const int alertSettingsTag = 199 ;
5354
5455static id locationManager = nil ;
5556static bool started = false ;
5657static bool hasDelayed = false ;
58+ static bool fallbackToSettings = false ;
5759
5860// CoreLocation must be statically linked for geotagging to work on iOS 6 and possibly 7.
5961// plist NSLocationUsageDescription (iOS 6 & 7) and NSLocationWhenInUseUsageDescription (iOS 8+) keys also required.
@@ -104,18 +106,18 @@ + (void)clearLastLocation {
104106 }
105107}
106108
107- + (void )getLocation : (bool )prompt withCompletionHandler : (void (^)(PromptActionResult result))completionHandler {
109+ + (void )getLocation : (bool )prompt fallbackToSettings : ( BOOL ) fallback withCompletionHandler : (void (^)(PromptActionResult result))completionHandler {
108110 if (completionHandler)
109111 [OneSignalLocation.locationListeners addObject: completionHandler];
110112
111113 if (hasDelayed)
112- [OneSignalLocation internalGetLocation: prompt];
114+ [OneSignalLocation internalGetLocation: prompt fallbackToSettings: fallback ];
113115 else {
114116 // Delay required for locationServicesEnabled and authorizationStatus return the correct values when CoreLocation is not statically linked.
115117 dispatch_time_t popTime = dispatch_time (DISPATCH_TIME_NOW, 2.0 * NSEC_PER_SEC);
116118 dispatch_after (popTime, dispatch_get_main_queue (), ^(void ) {
117119 hasDelayed = true ;
118- [OneSignalLocation internalGetLocation: prompt];
120+ [OneSignalLocation internalGetLocation: prompt fallbackToSettings: fallback ];
119121 });
120122 }
121123 // Listen to app going to and from background
@@ -193,16 +195,29 @@ + (void)sendCurrentAuthStatusToListeners {
193195 [self sendAndClearLocationListener: denied ? PERMISSION_DENIED : PERMISSION_GRANTED];
194196}
195197
196- + (void )internalGetLocation : (bool )prompt {
198+ + (void )internalGetLocation : (bool )prompt fallbackToSettings : (BOOL )fallback {
199+ fallbackToSettings = fallback;
200+ id clLocationManagerClass = NSClassFromString (@" CLLocationManager" );
201+
202+ // On the application init we are always calling this method
203+ // If location permissions was not asked "started" will never be true
197204 if ([self started ]) {
198- [self sendCurrentAuthStatusToListeners ];
205+ // We evaluate the following cases after permissions were asked (denied or given)
206+ CLAuthorizationStatus permissionStatus = [clLocationManagerClass performSelector: @selector (authorizationStatus )];
207+ // Fallback to settings alert view when the following condition are true:
208+ // - On a prompt flow
209+ // - Fallback to settings is enabled
210+ // - Permission were denied
211+ if (prompt && fallback && permissionStatus == kCLAuthorizationStatusDenied )
212+ [self showLocationSettingsAlertView ];
213+ else
214+ [self sendCurrentAuthStatusToListeners ];
199215 return ;
200216 }
201217
202- id clLocationManagerClass = NSClassFromString (@" CLLocationManager" );
203-
204218 // Check for location in plist
205219 if (![clLocationManagerClass performSelector: @selector (locationServicesEnabled )]) {
220+ onesignal_Log (ONE_S_LL_DEBUG, @" CLLocationManager locationServices Disabled." );
206221 [self sendAndClearLocationListener: ERROR];
207222 return ;
208223 }
@@ -249,11 +264,30 @@ + (void)internalGetLocation:(bool)prompt {
249264 started = true ;
250265}
251266
267+ + (void )showLocationSettingsAlertView {
268+ onesignal_Log (ONE_S_LL_DEBUG, @" CLLocationManager permissionStatus kCLAuthorizationStatusDenied fallaback to settings" );
269+ UIAlertView *alertView = [[UIAlertView alloc ] initWithTitle: @" Location Not Available" message: @" You have previously denied sharing your device location. Please go to settings to enable." delegate: singleInstance cancelButtonTitle: @" Cancel" otherButtonTitles: @" Open Settings" , nil ];
270+ alertView.tag = alertSettingsTag;
271+ [alertView show ];
272+ }
273+
274+ - (void )alertView : (UIAlertView *)alertView clickedButtonAtIndex : (NSInteger )buttonIndex {
275+ if (alertView.tag == alertSettingsTag) {
276+ if (buttonIndex == 1 ) {
277+ onesignal_Log (ONE_S_LL_DEBUG, @" CLLocationManage open settings option click" );
278+ [[UIApplication sharedApplication ] openURL: [NSURL URLWithString: UIApplicationOpenSettingsURLString]];
279+ }
280+ [OneSignalLocation sendAndClearLocationListener: false ];
281+ return ;
282+ }
283+ }
284+
252285#pragma mark CLLocationManagerDelegate
253286
254287- (void )locationManager : (id )manager didUpdateLocations : (NSArray *)locations {
255288 // return if the user has not granted privacy permissions or location shared is false
256- if ([OneSignal requiresUserPrivacyConsent ] || ![OneSignal isLocationShared ]) {
289+ if (([OneSignal requiresUserPrivacyConsent ] || ![OneSignal isLocationShared ]) && !fallbackToSettings) {
290+ onesignal_Log (ONE_S_LL_DEBUG, @" CLLocationManagerDelegate clear Location listener due to permissions denied or location shared not available" );
257291 [OneSignalLocation sendAndClearLocationListener: PERMISSION_DENIED];
258292 return ;
259293 }
0 commit comments