1// Copyright 2016-present 650 Industries. All rights reserved. 2 3#import <EXLocation/EXBackgroundLocationPermissionRequester.h> 4 5#import <objc/message.h> 6#import <CoreLocation/CLLocationManagerDelegate.h> 7 8static SEL alwaysAuthorizationSelector; 9 10@interface EXBackgroundLocationPermissionRequester () 11 12@property (nonatomic, assign) bool wasAsked; 13 14@end 15 16@implementation EXBackgroundLocationPermissionRequester 17 18- (instancetype)init 19{ 20 if (self = [super init]) { 21 _wasAsked = false; 22 } 23 return self; 24} 25 26+ (NSString *)permissionType 27{ 28 return @"locationBackground"; 29} 30 31+ (void)load 32{ 33 alwaysAuthorizationSelector = NSSelectorFromString([@"request" stringByAppendingString:@"AlwaysAuthorization"]); 34} 35 36- (void)requestLocationPermissions 37{ 38 if ([EXBaseLocationRequester isConfiguredForAlwaysAuthorization] && [self.locationManager respondsToSelector:alwaysAuthorizationSelector]) { 39 _wasAsked = true; 40 [[NSNotificationCenter defaultCenter] addObserver:self 41 selector:@selector(handleAppBecomingActive) 42 name:UIApplicationDidBecomeActiveNotification 43 object:nil]; 44 ((void (*)(id, SEL))objc_msgSend)(self.locationManager, alwaysAuthorizationSelector); 45 } else { 46 self.reject(@"ERR_LOCATION_INFO_PLIST", @"One of the `NSLocation*UsageDescription` keys must be present in Info.plist to be able to use geolocation.", nil); 47 48 self.resolve = nil; 49 self.reject = nil; 50 } 51} 52 53// If user selects "Keep Only While Using" option, the `locationManagerDidChangeAuthorization` won't be called. 54// So we don't know when we should resolve promise. 55// Hovewer, we can check for `UIApplicationDidBecomeActiveNotification` event which is called when permissions modal disappears. 56- (void)handleAppBecomingActive 57{ 58 [[NSNotificationCenter defaultCenter] removeObserver:self]; 59 if (self.resolve) { 60 self.resolve([self getPermissions]); 61 self.resolve = nil; 62 self.reject = nil; 63 } 64} 65 66- (NSDictionary *)parsePermissions:(CLAuthorizationStatus)systemStatus 67{ 68 EXPermissionStatus status; 69 70 switch (systemStatus) { 71 case kCLAuthorizationStatusAuthorizedAlways: { 72 status = EXPermissionStatusGranted; 73 break; 74 } 75 case kCLAuthorizationStatusDenied: 76 case kCLAuthorizationStatusRestricted: { 77 status = EXPermissionStatusDenied; 78 break; 79 } 80 case kCLAuthorizationStatusAuthorizedWhenInUse: { 81 if (_wasAsked) { 82 status = EXPermissionStatusDenied; 83 } else { 84 status = EXPermissionStatusUndetermined; 85 } 86 break; 87 } 88 case kCLAuthorizationStatusNotDetermined: 89 default: { 90 91 status = EXPermissionStatusUndetermined; 92 break; 93 } 94 } 95 96 return @{ @"status": @(status) }; 97} 98 99@end 100