Closed shankari closed 5 years ago
It looks like we have a couple of potential choices if the localStorage shows consented but the native usercache does not:
I think that 1. has the potential to be confusing because going to the reconsent state after already going to the users' actual state may be confusing. This is particularly true if this takes a while. I was in profile, suddenly I go back to the consent. Then after going through that, I go back to metrics.
Also, would we need to think through what will happen in the very first case? In that case, there is no consent even in the localstorage, so this won't even be invoked.
Regardless, I am going to go with (2) since it is the least confusing, and will fall back to (1) if (2) fails.
The reason for 1 can be seen from this repro log, uploaded with consent. real_repro-upgrade-fix.log.gz
When the UI is launched, then all plugins are launched, as evidenced by this statement
- (void)pluginInitialize
{
// TODO: We should consider adding a create statement to the init, similar
// to android - then it doesn't matter if the pre-populated database is not
// copied over.
NSLog(@"UnifiedLogger:pluginInitialize singleton -> initialize native DB");
[[DBLogging database] log:@"finished init of iOS native code" atLevel:@"INFO"];
[[DBLogging database] truncateObsolete];
}
But when the background sync is launched, it looks like the plugins are NOT launched.
First launch
0,1475866995.87,2016-10-07 12:56:15.865810-07:00,finished init of iOS native code
125,1475867106.03,2016-10-07 12:58:06.033280-07:00,Application went to the background
Next background sync
126,1475870408.65,2016-10-07 13:53:08.646500-07:00,"Received background sync call when useRemotePush = 1, about to check whether a trip has ended"
132,1475870408.7,2016-10-07 13:53:08.698160-07:00,backgroundSync called
151,1475870408.82,2016-10-07 13:53:08.818070-07:00,"Received background sync call when useRemotePush = 1, about to check whether a trip has ended"
157,1475870408.87,2016-10-07 13:53:08.867820-07:00,backgroundSync called
177,1475870408.99,2016-10-07 13:53:08.992890-07:00,"Finished refreshing token in background, new expiry is 2016-10-07 21:00:08 +0000"
186,1475870409.04,2016-10-07 13:53:09.041810-07:00,"Finished refreshing token in background, new expiry is 2016-10-07 21:00:08 +0000"
Next background sync
231,1475874004.5,2016-10-07 14:53:04.504950-07:00,backgroundSync called
251,1475874004.93,2016-10-07 14:53:04.931290-07:00,"Finished refreshing token in background, new expiry is 2016-10-07 22:00:04 +0000"
267,1475874022.1,2016-10-07 14:53:22.095960-07:00,"Received background sync call when useRemotePush = 1, about to check whether a trip has ended"
274,1475874022.21,2016-10-07 14:53:22.213480-07:00,"Finished refreshing token in background, new expiry is 2016-10-07 22:00:04 +0000"
276,1475874022.23,2016-10-07 14:53:22.232890-07:00,"Finished refreshing token in background, new expiry is 2016-10-07 22:00:04 +0000"
278,1475874022.27,2016-10-07 14:53:22.266390-07:00,backgroundSync called
Then, the application went to the background (not before this?) and again, it was launched without any plugins being initialized.
473,1475877603.1,2016-10-07 15:53:03.100710-07:00,"Received background sync call when useRemotePush = 1, about to check whether a trip has ended"
480,1475877603.16,2016-10-07 15:53:03.162850-07:00,"Finished refreshing token in background, new expiry is 2016-10-07 22:47:34 +0000"
482,1475877603.21,2016-10-07 15:53:03.212260-07:00,"Finished refreshing token in background, new expiry is 2016-10-07 22:47:34 +0000"
484,1475877603.24,2016-10-07 15:53:03.240740-07:00,backgroundSync called
502,1475877605.58,2016-10-07 15:53:05.575370-07:00,"Received background sync call when useRemotePush = 1, about to check whether a trip has ended"
509,1475877605.63,2016-10-07 15:53:05.626210-07:00,"Finished refreshing token in background, new expiry is 2016-10-07 22:47:34 +0000"
511,1475877605.68,2016-10-07 15:53:05.683430-07:00,"Finished refreshing token in background, new expiry is 2016-10-07 22:47:34 +0000"
513,1475877605.71,2016-10-07 15:53:05.713850-07:00,backgroundSync called
561,1475877638.4,2016-10-07 15:53:38.403590-07:00,Application went to the background
And our notification that it is suspended is at, which is never launched from the background.
- (void)pluginInitialize
{
// TODO: We should consider adding a create statement to the init, similar
// to android - then it doesn't matter if the pre-populated database is not
// copied over.
NSLog(@"BEMDataCollection:pluginInitialize singleton -> initialize statemachine and delegate");
StatsEvent* se = [[StatsEvent alloc] initForEvent:@"app_launched"];
[[BuiltinUserCache database] putMessage:@"key.usercache.client_nav_event" value:se];
// NOTE: This CANNOT be part of a background thread because when the geofence creation, and more importantly,
// the visit notification, are run as part of a background thread, they don't work.
// I tried to move this into a background thread as part of a18f8f9385bdd9e37f7b412b386a911aee9a6ea0 and had
// to revert it because even visit notification, which had been the bedrock of my existence so far, stopped
// working although I made an explicit stop at the education library on the way to Soda.
NSString* reqConsent = [self settingForKey:@"emSensorDataCollectionProtocolApprovalDate"];
BOOL isConsented = [ConfigManager isConsented:reqConsent];
if (isConsented) {
[self initWithConsent];
} else {
[LocalNotificationManager showNotification:@"New data collection terms - collection paused until consent"];
}
}
Solutions:
So I can definitely add a consent check to the remotePush delegate, and potentially to the visit delegate as well, since that is the one constant in an unfeeling universe.
Should I try to initialize the TripDiaryStateMachine as well? It seems like I should - all of the pre-consent testing had the TripDiaryStateMachine init happening as part of the AppDelegate, IIRC.
But that seems like a pretty big change for now, and the iOS phones seem to be working pretty well for me so far. Should also see when the tracking stopped last time. If we check the consent on plugin load, when did we detect no consent and turn things off?
Tracking worked until this.
768,1475974983.9,2016-10-08 18:56:03.901400-07:00,"In TripDiaryStateMachine, received transition T_TRIP_ENDED in state STATE_ONGOING_TRIP"
769,1475974983.94,2016-10-08 18:56:03.944830-07:00,Moved from STATE_ONGOING_TRIP to STATE_WAITING_FOR_TRIP_START
820,1475975141.85,2016-10-08 18:58:41.851210-07:00,"In TripDiaryStateMachine, received transition T_DATA_PUSHED in state STATE_WAITING_FOR_TRIP_START"
Then the UI launched.
821,1475979151.08,2016-10-08 20:05:31.076470-07:00,finished init of iOS native code
822,1475979151.08,2016-10-08 20:05:31.082440-07:00,truncating obsolete entries before 1473387151.082153
823,1475979153.6,2016-10-08 20:05:33.597220-07:00,About to set theme from preference
824,1475979153.61,2016-10-08 20:05:33.607340-07:00,preferred theme = dark_theme
825,1475979153.61,2016-10-08 20:05:33.614240-07:00,set dark_theme = true
826,1475979153.69,2016-10-08 20:05:33.688110-07:00,About to navigate to preferred tab
827,1475979154.06,2016-10-08 20:05:34.055330-07:00,"required consent version = {""protocol_id"":""2014-04-6267"",""approval_date"":""2016-07-14""}"
828,1475979154.07,2016-10-08 20:05:34.065800-07:00,changing state to root.main.metrics
829,1475979156.11,2016-10-08 20:05:36.113940-07:00,CommunicationHelper.execute called!
830,1475979156.12,2016-10-08 20:05:36.123090-07:00,"currAuth = null, reading the current value from the keychain"
831,1475979156.14,2016-10-08 20:05:36.136370-07:00,"currAuth = GTMOAuth2Authentication 0x1702e5700: {refreshToken=""1/abNzx-3k2gy48HNhmiBmptDpf5NsELbvi7_crr_-g6c""}, canAuthorize = YES, expiresIn = (null), expirationDate = (null), expired = YES"
832,1475979156.14,2016-10-08 20:05:36.143710-07:00,"token has expired, refreshing it"
833,1475979156.15,2016-10-08 20:05:36.150680-07:00,beginning refresh of token expiring at (null)
834,1475979214.08,2016-10-08 20:06:34.080110-07:00,Ionic Deploy: Update available: false
and then tracking stopped!
836,1476048197.77,2016-10-09 15:16:17.766930-07:00,Application will enter the foreground
837,1476048214.44,2016-10-09 15:16:34.435150-07:00,"after stopping tracking, state is STATE_START"
Only instance of that string in the code is here. So we reconfigured? But then why didn't the restart work? We don't check for consent here?
- (void) restartCollection {
if (self.tripDiaryStateMachine.currState == kTrackingStoppedState) {
[LocalNotificationManager addNotification:[NSString stringWithFormat:
@"in restartCollection, state is already TRACKING_STOPPED, early return"]];
return;
}
[[NSNotificationCenter defaultCenter] postNotificationName:CFCTransitionNotificationName
object:CFCTransitionForceStopTracking];
[LocalNotificationManager addNotification:[NSString stringWithFormat:
@"after stopping tracking, state is %@",
[TripDiaryStateMachine getStateName:self.tripDiaryStateMachine.currState]]];
// This may take a while to complete, but we don't care
[[NSNotificationCenter defaultCenter] postNotificationName:CFCTransitionNotificationName
object:CFCTransitionStartTracking];
}
There is also no indication that we received a STOP_TRACKING
notification.
821,1475979151.08,2016-10-08 20:05:31.076470-07:00,finished init of iOS native code
822,1475979151.08,2016-10-08 20:05:31.082440-07:00,truncating obsolete entries before 1473387151.082153
823,1475979153.6,2016-10-08 20:05:33.597220-07:00,About to set theme from preference
824,1475979153.61,2016-10-08 20:05:33.607340-07:00,preferred theme = dark_theme
825,1475979153.61,2016-10-08 20:05:33.614240-07:00,set dark_theme = true826,1475979153.69,2016-10-08 20:05:33.688110-07:00,About to navigate to preferred tab
827,1475979154.06,2016-10-08 20:05:34.055330-07:00,"required consent version = {""protocol_id"":""2014-04-6267"",""approval_date"":""2016-07-14""}"
828,1475979154.07,2016-10-08 20:05:34.065800-07:00,changing state to root.main.metrics
829,1475979156.11,2016-10-08 20:05:36.113940-07:00,CommunicationHelper.execute called!
830,1475979156.12,2016-10-08 20:05:36.123090-07:00,"currAuth = null, reading the current value from the keychain"
831,1475979156.14,2016-10-08 20:05:36.136370-07:00,"currAuth = GTMOAuth2Authentication 0x1702e5700: {refreshToken=""1/abNzx-3k2gy48HNhmiBmptDpf5NsELbvi7_crr_-g6c""}, canAuthorize = YES, expiresIn = (null), expirationDate = (null), expired = YES"832,1475979156.14,2016-10-08 20:05:36.143710-07:00,"token has expired, refreshing it"
833,1475979156.15,2016-10-08 20:05:36.150680-07:00,beginning refresh of token expiring at (null)
834,1475979214.08,2016-10-08 20:06:34.080110-07:00,Ionic Deploy: Update available: false
835,1475979217.09,2016-10-08 20:06:37.093650-07:00,"Error Error Domain=NSURLErrorDomain Code=-1001 ""The request timed out."" UserInfo={NSUnderlyingError=0x170249d80 {Error Domain=kCFErrorDomainCFNetwork Code=-1001 ""(null)"" UserInfo={_kCFStreamErrorCodeKey=-2102, _kCFStreamErrorDomainKey=4}}, NSErrorFailingURLStringKey=https://www.googleapis.com/oauth2/v4/token, NSErrorFailingURLKey=https://www.googleapis.com/oauth2/v4/token, _kCFStreamErrorDomainKey=4, _kCFStreamErrorCodeKey=-2102, NSLocalizedDescription=The request timed out.} while refreshing token, need to retry"
836,1476048197.77,2016-10-09 15:16:17.766930-07:00,Application will enter the foreground
837,1476048214.44,2016-10-09 15:16:34.435150-07:00,"after stopping tracking, state is STATE_START"
Change to move the TripDiaryStateMachine initialization from didFinishLaunchingWithOptions
to
pluginInitialize
happened back in Feb 2016. We've tested it multiple times since then, so I am not keen to revert it. I will add the consent check and push a new release, and then continue testing to see if the TripDiaryStateMachine init changes have made a difference.
https://github.com/e-mission/e-mission-data-collection/pull/96
Another thing to note wrt the logs in https://github.com/e-mission/e-mission-phone/issues/181#issuecomment-258766187, the app stopped receiving remote push notifications on the 15th, roughly a week after the install.
,ts,dt,message
0,1475866995.87,2016-10-07 12:56:15.865810-07:00,finished init of iOS native code
1084,1476547227.98,2016-10-15 09:53:27.975180-07:00,"Received background sync call when useRemotePush = 1, about to check whether a trip has ended"
1070,1476543605.42,2016-10-15 08:53:05.415710-07:00,"Received background sync call when useRemotePush = 1, about to check whether a trip has ended"
1098,1476550805.36,2016-10-15 10:53:05.363390-07:00,"Received background sync call when useRemotePush = 1, about to check whether a trip has ended"
1105,1476554405.85,2016-10-15 11:53:05.847370-07:00,"Received background sync call when useRemotePush = 1, about to check whether a trip has ended"
Is that a common pattern? If so, why does it occur.
It looks like as long as the app is launched to deal with location events, the plugin init is called.
As expected, after the 8th, every time we init the code, we change state to metrics.
But sometimes before that, we see this pattern, with no manual init involved.
562,1475913612.19,2016-10-08 01:53:12.189100-07:00,finished init of iOS native code
564,1475913612.27,2016-10-08 01:53:12.267880-07:00,initializing TripDiaryStateMachine with state = STATE_WAITING_FOR_TRIP_START
566,1475913612.58,2016-10-08 01:53:12.577290-07:00,"In TripDiaryStateMachine, received transition T_EXITED_GEOFENCE in state STATE_WAITING_FOR_TRIP_START"
568,1475913612.65,2016-10-08 01:53:12.648380-07:00,"In TripDiaryStateMachine, received transition T_TRIP_STARTED in state STATE_WAITING_FOR_TRIP_START"
572,1475913612.74,2016-10-08 01:53:12.740890-07:00,"In TripDiaryStateMachine, received transition T_TRIP_STARTED in state STATE_ONGOING_TRIP"
575,1475913612.79,2016-10-08 01:53:12.793350-07:00,"In TripDiaryStateMachine, received transition T_TRIP_RESTARTED in state STATE_ONGOING_TRIP"
579,1475913612.9,2016-10-08 01:53:12.900660-07:00,"In TripDiaryStateMachine, received transition T_VISIT_ENDED in state STATE_ONGOING_TRIP"
648,1475913888.53,2016-10-08 01:57:48.527880-07:00,"In TripDiaryStateMachine, received transition T_VISIT_STARTED in state STATE_ONGOING_TRIP"
658,1475913888.67,2016-10-08 01:57:48.667740-07:00,"In TripDiaryStateMachine, received transition T_TRIP_END_DETECTED in state STATE_ONGOING_TRIP"
668,1475913890.8,2016-10-08 01:57:50.804990-07:00,"In TripDiaryStateMachine, received transition T_END_TRIP_TRACKING in state STATE_ONGOING_TRIP"
670,1475913890.95,2016-10-08 01:57:50.953970-07:00,"In TripDiaryStateMachine, received transition T_TRIP_ENDED in state STATE_ONGOING_TRIP"
708,1475913899.54,2016-10-08 01:57:59.537340-07:00,"In TripDiaryStateMachine, received transition T_DATA_PUSHED in state STATE_WAITING_FOR_TRIP_START"
Note that sometimes, we handle the location events without the iOS init. I wonder if that is the difference between background -> foreground and killed.
709,1475973760.09,2016-10-08 18:35:40.087690-07:00,"In TripDiaryStateMachine, received transition T_EXITED_GEOFENCE in state STATE_WAITING_FOR_TRIP_START"
711,1475973760.13,2016-10-08 18:35:40.125140-07:00,"In TripDiaryStateMachine, received transition T_TRIP_STARTED in state STATE_WAITING_FOR_TRIP_START"
715,1475973760.2,2016-10-08 18:35:40.197140-07:00,"In TripDiaryStateMachine, received transition T_TRIP_STARTED in state STATE_ONGOING_TRIP"
718,1475973760.22,2016-10-08 18:35:40.224250-07:00,"In TripDiaryStateMachine, received transition T_TRIP_RESTARTED in state STATE_ONGOING_TRIP"
725,1475973840.26,2016-10-08 18:37:00.262820-07:00,"In TripDiaryStateMachine, received transition T_VISIT_ENDED in state STATE_ONGOING_TRIP"
751,1475974983.01,2016-10-08 18:56:03.009410-07:00,"In TripDiaryStateMachine, received transition T_VISIT_STARTED in state STATE_ONGOING_TRIP"
756,1475974983.1,2016-10-08 18:56:03.104620-07:00,"In TripDiaryStateMachine, received transition T_TRIP_END_DETECTED in state STATE_ONGOING_TRIP"
766,1475974983.87,2016-10-08 18:56:03.867870-07:00,"In TripDiaryStateMachine, received transition T_END_TRIP_TRACKING in state STATE_ONGOING_TRIP"
768,1475974983.9,2016-10-08 18:56:03.901400-07:00,"In TripDiaryStateMachine, received transition T_TRIP_ENDED in state STATE_ONGOING_TRIP"
820,1475975141.85,2016-10-08 18:58:41.851210-07:00,"In TripDiaryStateMachine, received transition T_DATA_PUSHED in state STATE_WAITING_FOR_TRIP_START"
Tried to reproduce the bug by clearing only the usercache from the UI while keeping the localStorage. Left the app running after that with the screen closed. At the next remote push, saw the notification.
On sliding the notification, went back to the consent page of the app. It was now consented (probably because of the sync which pulled from the server).
no_consent_notify_iphone_logs.log.gz
Deleting again and killing the app as well this time.
After deleting and killing the app, did not receive any remote notifications for 5 hours. no_consent_notify_iphone_after_kill.log.gz
wrt https://github.com/e-mission/e-mission-phone/issues/181#issuecomment-258855775, this is expected behavior. But it should be relaunched on geofence exit or significant location changes.
https://developer.apple.com/reference/uikit/uiapplicationdelegate/1623013-application?language=objc
However, the system does not automatically launch your app if the user has force-quit it. In that situation, the user must relaunch your app or restart the device before the system attempts to launch your app automatically again.
wrt https://github.com/e-mission/e-mission-phone/issues/181#issuecomment-258858737
But it should be relaunched on geofence exit or significant location changes.
Yup, it did! It looks like the app was launched and generated the consent required message.
But then it looks like the launch of the UI caused the consent to get overwritten. Because by the time that I came back, the consent was fine again.
Nov 7 08:40:52 ucb-sdb-iphone-4 emission[906] <Warning>: Apache Cordova native platform version 4.1.1 is starting.
Nov 7 08:40:52 ucb-sdb-iphone-4 emission[906] <Warning>: Multi-tasking -> Device: YES, App: YES
Nov 7 08:40:52 ucb-sdb-iphone-4 emission[906] <Warning>: Using UIWebView
Nov 7 08:40:52 ucb-sdb-iphone-4 emission[906] <Warning>: [CDVTimer][handleopenurl] 0.344038ms
Nov 7 08:40:52 ucb-sdb-iphone-4 emission[906] <Warning>: [CDVTimer][intentandnavigationfilter] 6.796002ms
Nov 7 08:40:52 ucb-sdb-iphone-4 emission[906] <Warning>: [CDVTimer][gesturehandler] 0.471950ms
Nov 7 08:40:52 ucb-sdb-iphone-4 emission[906] <Warning>: [CDVTimer][keyboard] 2.927005ms
Nov 7 08:40:52 ucb-sdb-iphone-4 emission[906] <Warning>: UnifiedLogger:pluginInitialize singleton -> initialize native DB
Nov 7 08:40:52 ucb-sdb-iphone-4 emission[906] <Warning>: no cloud sync at path: /var/mobile/Containers/Data/Application/2BF61CF3-AED5-4B2D-94FC-384D311904A1/Library/LocalDatabase
Nov 7 08:40:52 ucb-sdb-iphone-4 emission[906] <Warning>: INFO: finished init of iOS native code
Nov 7 08:40:52 ucb-sdb-iphone-4 emission[906] <Warning>: INFO: truncating obsolete entries before 1475944852.275303
Nov 7 08:40:52 ucb-sdb-iphone-4 emission[906] <Warning>: [CDVTimer][unifiedlogger] 263.894975ms
Nov 7 08:40:52 ucb-sdb-iphone-4 emission[906] <Warning>: BEMUserCache:pluginInitialize singleton -> initialize native DB
Nov 7 08:40:52 ucb-sdb-iphone-4 emission[906] <Warning>: no cloud sync at path: /var/mobile/Containers/Data/Application/2BF61CF3-AED5-4B2D-94FC-384D311904A1/Library/LocalDatabase
Nov 7 08:40:52 ucb-sdb-iphone-4 emission[906] <Warning>: Database is <BuiltinUserCache: 0x13452cf10>
Nov 7 08:40:52 ucb-sdb-iphone-4 emission[906] <Warning>: [CDVTimer][usercache] 3.107965ms
Nov 7 08:40:52 ucb-sdb-iphone-4 emission[906] <Warning>: creating new AuthCompletionHandler sharedInstance
Nov 7 08:40:52 ucb-sdb-iphone-4 emission[906] <Warning>: [CDVTimer][jwtauth] 0.744998ms
Nov 7 08:40:52 ucb-sdb-iphone-4 emission[906] <Warning>: BEMDataCollection:pluginInitialize singleton -> initialize statemachine and delegate
Nov 7 08:40:52 ucb-sdb-iphone-4 emission[906] <Warning>: data has 114 bytes, str has size 114
Nov 7 08:40:52 ucb-sdb-iphone-4 emission[906] <Warning>: reqConsent = 2016-07-14, currConfig.approval_date = 2016-07-14
Nov 7 08:40:52 ucb-sdb-iphone-4 emission[906] <Warning>: DEBUG: reqConsent = 2016-07-14, currConfig.approval_date = 2016-07-14
Nov 7 08:40:52 ucb-sdb-iphone-4 emission[906] <Warning>: isConsented = YES
Nov 7 08:40:52 ucb-sdb-iphone-4 emission[906] <Warning>: initializing TripDiaryStateMachine with state = STATE_ONGOING_TRIP
Nov 7 08:40:52 ucb-sdb-iphone-4 emission[906] <Warning>: initializing TripDiaryStateMachine with state = STATE_ONGOING_TRIP
Nov 7 08:40:52 ucb-sdb-iphone-4 emission[906] <Warning>: DEBUG: initializing TripDiaryStateMachine with state = STATE_ONGOING_TRIP
Nov 7 08:40:52 ucb-sdb-iphone-4 locationd[64] <Notice>: client 'edu.berkeley.eecs.emission' starting significant location changes
Nov 7 08:40:52 ucb-sdb-iphone-4 emission[906] <Warning>: started fine location tracking with accuracy = -1 and distanceFilter = 50
Nov 7 08:40:52 ucb-sdb-iphone-4 emission[906] <Warning>: DEBUG: started fine location tracking with accuracy = -1 and distanceFilter = 50
Nov 7 08:40:52 ucb-sdb-iphone-4 emission[906] <Warning>: Current location authorization = 3, always = 3
Nov 7 08:40:52 ucb-sdb-iphone-4 emission[906] <Warning>: Initialized remote push notification handler <BEMRemotePushNotificationHandler: 0x1346888e0>, finished registering for notifications
Nov 7 08:40:52 ucb-sdb-iphone-4 emission[906] <Warning>: DEBUG: Initialized remote push notification handler <BEMRemotePushNotificationHandler: 0x1346888e0>, finished registering for notifications
Nov 7 08:40:52 ucb-sdb-iphone-4 emission[906] <Warning>: [CDVTimer][datacollection] 370.804012ms
Nov 7 08:40:52 ucb-sdb-iphone-4 emission[906] <Warning>: [CDVTimer][file] 3.372967ms
Nov 7 08:40:52 ucb-sdb-iphone-4 emission[906] <Warning>: VERSION LABEL: 1.4.0:1478501022:
Nov 7 08:40:52 ucb-sdb-iphone-4 emission[906] <Warning>: [CDVTimer][ionicdeploy] 0.796020ms
Nov 7 08:40:52 ucb-sdb-iphone-4 emission[906] <Warning>: [CDVTimer][socialsharing] 71.231008ms
Nov 7 08:40:52 ucb-sdb-iphone-4 emission[906] <Warning>: [CDVTimer][TotalPluginStartup] 733.393013ms
Ok so the current behavior is:
The one corner case that I can think of is:
Then, we won't get location updates, and we won't get silent push notifications. Probably we should send a real remote push notification in that case, which should cause the user to launch the app (this time with consent turned on) and so then everything should work again.
Will that actually work? Maybe I should just send a non-silent push notification to all users and ask them to check out the leaderboard or something. After I push the update, that should fix all the consent issues...
Let's test that with the following use case:
So I set the sync config = 10 mins, deleted consent and killed the app. Then I left it running for a few hours. As expected, the app was not launched. Instead, we got a bunch of messages like so:
ov 7 12:10:03 ucb-sdb-iphone-4 SpringBoard[58] <Warning>: High Priority Push: edu.berkeley.eecs.emission - App killed
Nov 7 12:20:07 ucb-sdb-iphone-4 SpringBoard[58] <Warning>: High Priority Push: edu.berkeley.eecs.emission - App killed
Nov 7 12:23:41 ucb-sdb-iphone-4 SpringBoard[58] <Warning>: High Priority Push: edu.berkeley.eecs.emission - App killed
Nov 7 12:30:03 ucb-sdb-iphone-4 SpringBoard[58] <Warning>: High Priority Push: edu.berkeley.eecs.emission - App killed
which apparently mean that the app was not launched because it was killed. https://forums.developer.apple.com/thread/36776
Now, sending a manual, non-silent notification to the 10 min channel.
That didn't work the first time, but did work the second time.
Nov 7 14:00:08 ucb-sdb-iphone-4 SpringBoard[58] <Warning>: High Priority Push: edu.berkeley.eecs.emission - App killed
Nov 7 14:00:08 ucb-sdb-iphone-4 SpringBoard[58] <Warning>: High Priority Push: edu.berkeley.eecs.emission - App killed
Nov 7 14:01:11 ucb-sdb-iphone-4 SpringBoard[58] <Warning>: High Priority Push: edu.berkeley.eecs.emission - App killed
the new code also seems to crash a lot
0 libobjc.A.dylib 0x0000000182545b9c objc_msgSend + 28
1 emission 0x0000000100167890 -[AppDelegate(notification) launchTripEndCheckAndRemoteSync:] (BEMAppDelegate.m:178)
2 emission 0x0000000100166e4c -[AppDelegate(notification) application:didReceiveRemoteNotification:fetchCompletionHandler:] (BEMAppDelegate.m:87)
3 UIKit 0x00000001882d20b8 -[UIApplication _handleNonLaunchSpecificActions:forScene:withTransitionContext:completion:] + 2676
4 UIKit 0x00000001882bfe94 -[UIApplication workspace:didReceiveActions:] + 136
0 libobjc.A.dylib 0x0000000182545b9c objc_msgSend + 28
1 emission 0x000000010016324c -[TripDiaryDelegate locationManager:didVisit:] (TripDiaryDelegate.m:247)
2 CoreLocation 0x0000000189c1b5dc 0x189c0c000 + 62940
3 CoreLocation 0x0000000189c14aac 0x189c0c000 + 35500
Going to try to fix that, and then will try option 1 again.
Appear to have fixed it by fixing the method signature. Next step: investigate Sam's log file to see if there's another change we need to squeeze in. Then, test while on the way to/from karate. Then submit fix tonight.
Investigated Sam's log file, not related. That's a different consent issue and is really different from any issue I have seen before.
What I see from the logs is that his data seems to be collected fine until the 21st, but then I get this error.
6876,1477093581.19,2016-10-21 17:39:21.188500-07:00,"New authorization status = 2, always = 3"
6877,1477093581.26,2016-10-21 17:39:21.261360-07:00,"Location tracking failed with error Error Domain=kCLErrorDomain Code=1 ""The operation couldn’t be completed. (kCLErrorDomain error 1.)"""
Then, the app was launched again on the 28th, but the authorization status was still not good enough.
6883,1477689395.14,2016-10-28 15:09:35.138530-07:00,"New authorization status = 2, always = 3"
6884,1477689395.42,2016-10-28 15:09:35.417620-07:00,"Location tracking failed with error Error Domain=kCLErrorDomain Code=1 ""The operation couldn’t be completed. (kCLErrorDomain
error 1.)"""
6885,1477689395.46,2016-10-28 15:09:35.463490-07:00,"Location tracking failed with error Error Domain=kCLErrorDomain Code=1 ""The operation couldn’t be completed. (kCLErrorDomain error 1.)"""
And then he launched it on the 3rd, at which point it seems to be fine again.
6970,1478204908.04,2016-11-03 14:21:28.042590-07:00,finished init of iOS native code
6975,1478204910.82,2016-11-03 14:21:30.817260-07:00,"New authorization status = 3, always = 3"
6976,1478204911.89,2016-11-03 14:21:31.886450-07:00,"Recieved location <> +/- 65.00m (speed -1.00 mps / course -1.00) @ 11/3/16, 1:28:28 PM Pacific Daylight Time, ongoing trip = true"
I looked at the source code and 2 is denied.
typedef NS_ENUM(int, CLAuthorizationStatus) {
// User has not yet made a choice with regards to this application
kCLAuthorizationStatusNotDetermined = 0,
// This application is not authorized to use location services. Due
// to active restrictions on location services, the user cannot change
// this status, and may not have personally denied authorization
kCLAuthorizationStatusRestricted,
// User has explicitly denied authorization for this application, or
// location services are disabled in Settings.
kCLAuthorizationStatusDenied,
// User has granted authorization to use their location at any time,
// including monitoring for regions, visits, or significant location changes.
kCLAuthorizationStatusAuthorizedAlways NS_ENUM_AVAILABLE(NA, 8_0),
denied for this service, or in settings. unsure what to do with this. probably the best thing to do is to send a push notification requesting you to turn on again. We should also probably log a client error for this.
I will deal with that as part of the next change since I want to keep this change as simple as possible.
Final test before the kids get here.
Check again now
Tried this a couple of more times - they were successful. Probably ready to submit to the store now...
Just for completeness, I looked at what would happen on android in a similar situation. The steps were:
However, everything was fine. We didn't even get the alert because the sync pulled the config from the server.
Seems to be fixed now.
I probably should not be commenting on a closed issue - but is there a way to completely delete the consent process? Since I could not find a simple way to do this in my custom client, I marked consent in the code, but it still expects user consent to re-start data collection when data collection is paused. What are the different scenarios when data collection is paused? Sorry if my questions are redundant. It would be of great help if you could point me to related issues/relevant documentation.
@MythriNagaraju yeah can you just file a new issue? Maybe with a subject like "How to skip the consent screen in the UI?" Would also be great if you could provide more details - e.g.
After investigating and fixing https://github.com/e-mission/cordova-jwt-auth/issues/8, we found that it had at least two occurrences in the real world. Furthermore, the users reported that:
We just really need to make the consent thing a lot better.