diff --git a/plugin.xml b/plugin.xml
index 5904d24..a2eb9dc 100644
--- a/plugin.xml
+++ b/plugin.xml
@@ -212,19 +212,19 @@
- We use your data to create an automatic trip diary
+ OpenPATH requires "Precise" location access allowed "Always" to create an automatic trip diary
- We use your data to create an automatic trip diary
+ OpenPATH also requires "Always" location access to track your trips in the background
- We use your data to create an automatic trip diary
+ OpenPATH requires "Precise" location access allowed "While Using App" to create an automatic trip diary
- Our app uses the motion sensors to determine the transportation mode for the sections of your trip
+ OpenPATH uses your phone's motion sensors to determine the modes of transportation during your trips
@@ -232,7 +232,7 @@
- We need Bluetooth access to interact with BLE beacons for the fleet version of the app.
+ OpenPATH requires Bluetooth access to interact with BLE beacons for the fleet version of the app
diff --git a/src/ios/Verification/SensorControlForegroundDelegate.m b/src/ios/Verification/SensorControlForegroundDelegate.m
index 3de0c7e..082d4a0 100644
--- a/src/ios/Verification/SensorControlForegroundDelegate.m
+++ b/src/ios/Verification/SensorControlForegroundDelegate.m
@@ -153,6 +153,16 @@ - (void) didChangeAuthorizationStatus:(CLAuthorizationStatus)status
CDVPluginResult* result = [CDVPluginResult
resultWithStatus:CDVCommandStatus_OK];
[commandDelegate sendPluginResult:result callbackId:callbackId];
+ } else if (status == kCLAuthorizationStatusAuthorizedWhenInUse) {
+ if (IsAtLeastiOSVersion(@"13.4")) {
+ NSLog(@"iOS >=13.4 detected and 'whenInUse' authorized, need second step to request 'always'");
+ [[TripDiaryStateMachine delegate] registerForegroundDelegate:self];
+ [[TripDiaryStateMachine instance].locMgr requestAlwaysAuthorization];
+ if ([[UIApplication sharedApplication] applicationState] != UIApplicationStateInactive) {
+ NSLog(@"App is active, i.e. request did not launch (happens if the user chose 'Allow Once' in step 1). Launching app settings to manually enable 'Always'");
+ [self openAppSettings];
+ }
+ }
} else {
[LocalNotificationManager addNotification:[NSString stringWithFormat:@"status %d != always %d, returning error", status, kCLAuthorizationStatusAuthorizedAlways]];
NSString* msg = NSLocalizedStringFromTable(@"location_permission_off_app_open", @"DCLocalizable", nil);
@@ -281,25 +291,39 @@ - (void) didRegisterUserNotificationSettings:(UIUserNotificationSettings*)newSet
}
-(void)promptForPermission:(CLLocationManager*)locMgr {
- if (IsAtLeastiOSVersion(@"13.0")) {
- NSLog(@"iOS 13+ detected, launching UI settings to easily enable always");
+ if (IsAtLeastiOSVersion(@"13.4")) {
+ NSLog(@"iOS >=13.4 detected, using two-step approach of 'when in use' first and then 'always'");
+ if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusNotDetermined) {
+ NSLog(@"Current location authorization = %d, when in use = %d, requesting when in use",
+ [CLLocationManager authorizationStatus], kCLAuthorizationStatusAuthorizedWhenInUse);
+ [[TripDiaryStateMachine delegate] registerForegroundDelegate:self];
+ [locMgr requestWhenInUseAuthorization];
+ } else if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusAuthorizedWhenInUse) {
+ NSLog(@"Current location authorization = %d, always = %d, requesting always",
+ [CLLocationManager authorizationStatus], kCLAuthorizationStatusAuthorizedAlways);
+ [[TripDiaryStateMachine delegate] registerForegroundDelegate:self];
+ [locMgr requestAlwaysAuthorization];
+ if ([[UIApplication sharedApplication] applicationState] != UIApplicationStateInactive) {
+ NSLog(@"App is active, i.e. request did not launch (happens if the user chose 'Allow Once' in step 1). Launching app settings to manually enable 'Always'");
+ [self openAppSettings];
+ }
+ } else {
+ [[TripDiaryStateMachine delegate] registerForegroundDelegate:self];
+ [self openAppSettings];
+ }
+ } else if (IsAtLeastiOSVersion(@"13.0")) {
+ NSLog(@"iOS >=13,<13.4 detected, launching UI settings to manually enable 'always'");
// we want to leave the registration in the prompt for permission, since we don't want to register callbacks when we open the app settings for other reasons
[[TripDiaryStateMachine delegate] registerForegroundDelegate:self];
[[TripDiaryStateMachine instance].locMgr startUpdatingLocation];
[self openAppSettings];
- }
- else {
+ } else {
+ NSLog(@"iOS <13 detected, simply requesting 'always'");
if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusNotDetermined) {
- if ([CLLocationManager instancesRespondToSelector:@selector(requestAlwaysAuthorization)]) {
- NSLog(@"Current location authorization = %d, always = %d, requesting always",
- [CLLocationManager authorizationStatus], kCLAuthorizationStatusAuthorizedAlways);
- [[TripDiaryStateMachine delegate] registerForegroundDelegate:self];
- [locMgr requestAlwaysAuthorization];
- } else {
- // TODO: should we remove this? Not sure when it will ever be called, given that
- // requestAlwaysAuthorization is available in iOS8+
- [LocalNotificationManager addNotification:@"Don't need to request authorization, system will automatically prompt for it"];
- }
+ NSLog(@"Current location authorization = %d, always = %d, requesting always",
+ [CLLocationManager authorizationStatus], kCLAuthorizationStatusAuthorizedAlways);
+ [[TripDiaryStateMachine delegate] registerForegroundDelegate:self];
+ [locMgr requestAlwaysAuthorization];
} else {
// we want to leave the registration in the prompt for permission, since we don't want to register callbacks when we open the app settings for other reasons
[[TripDiaryStateMachine delegate] registerForegroundDelegate:self];
@@ -346,11 +370,12 @@ - (void)locationManager:(CLLocationManager *)manager
if (foregroundDelegateList.count > 0) {
[LocalNotificationManager addNotification:[NSString stringWithFormat:@"%lu foreground delegates found, calling didChangeAuthorizationStatus to return the new value %d", (unsigned long)foregroundDelegateList.count, status]];
+ int originalDelegateCount = (int)foregroundDelegateList.count;
for (id currDelegate in foregroundDelegateList) {
[currDelegate didChangeAuthorizationStatus:(CLAuthorizationStatus)status];
}
- [LocalNotificationManager addNotification:[NSString stringWithFormat:@"Notified all foreground delegates, removing all of them"]];
- [foregroundDelegateList removeAllObjects];
+ [LocalNotificationManager addNotification:[NSString stringWithFormat:@"Notified all foreground delegates, removing %d delegates", originalDelegateCount]];
+ [foregroundDelegateList removeObjectsInRange:NSMakeRange(0, originalDelegateCount)];
} else {
[LocalNotificationManager addNotification:[NSString stringWithFormat:@"No foreground delegate found, calling SensorControlBackgroundChecker from didChangeAuthorizationStatus to verify location service status and permission"]];
[SensorControlBackgroundChecker checkAppState];