/// <summary> /// Set up push notification and periodagent. /// </summary> private async Task<bool> SetUpAfterLogin() { App.ShowProgressOverlay(AppResources.Login_SettingUp); bool result = true; try { await ParseUser.CurrentUser.FetchAsync(); //If does not contain one of the keys, initialize the user settings if (!ParseUser.CurrentUser.ContainsKey(ParseContract.UserTable.TRACKING_ENABLED)) { await InitializeUserSettings(); } //Start the periodic agent even when the user does not navigate to the settings page. if (ParseUser.CurrentUser.Get<Boolean>(ParseContract.UserTable.TRACKING_ENABLED)) App.StartPeriodicAgent(); //Start the push notification channel. try { await SetUpChannel(); } catch (Exception e) { Debug.WriteLine(e.ToString()); MessageBox.Show(AppResources.SOS_FailToSetUpPush); } //Send the unsent location data to the server. UnsentLocationQueue queue = new UnsentLocationQueue(ParseUser.CurrentUser.Username); await queue.SendLocations(ParseUser.CurrentUser); } catch (Exception e) { Debug.WriteLine(e.ToString()); login_username_textbox.Text = ParseUser.CurrentUser.Username; login_password_textbox.Password = DUMMY_PASSWORD; MessageBox.Show(AppResources.App_ConnectionError); result = false; } App.HideProgressOverlay(); return result; }
/// <summary> /// Load user settings from the server. /// Does not take care of exception handling. /// This method will intialize the user setting /// on the server if no user setting data exist /// on the server. /// </summary> public async override Task LoadSettings(CancellationToken tk) { await ParseUser.CurrentUser.FetchAsync(tk);//Sync first because settings can be updated in the background. //Get the data used to populate UI. trackingEnabled = ParseUser.CurrentUser.Get<bool>(ParseContract.UserTable.TRACKING_ENABLED); interval = ParseUser.CurrentUser.Get<int>(ParseContract.UserTable.UPDATE_INTERVAL); notifyByEmailStranger = ParseUser.CurrentUser.Get<bool>(ParseContract.UserTable.NOTIFY_BY_EMAIL_STRANGER); notifyBySMSStranger = ParseUser.CurrentUser.Get<bool>(ParseContract.UserTable.NOTIFY_BY_SMS_STRANGER); notifyByPushStranger = ParseUser.CurrentUser.Get<bool>(ParseContract.UserTable.NOTIFY_BY_PUSH_STRANGER); OnPropertyChanged("intervalRadio0"); OnPropertyChanged("intervalRadio1"); OnPropertyChanged("intervalRadio2"); OnPropertyChanged("intervalRadio3"); OnPropertyChanged("intervalRadio4"); int lastUpdateIndex = ParseUser.CurrentUser.Get<int>(ParseContract.UserTable.LAST_LOCATION_INDEX); queue = new UnsentLocationQueue(ParseUser.CurrentUser.Username); if (ParseUser.CurrentUser.ContainsKey(ParseContract.UserTable.LOCATION(lastUpdateIndex))) { ParseObject lastLocation = ParseUser.CurrentUser.Get<ParseObject>(ParseContract.UserTable.LOCATION(lastUpdateIndex)); //Need to download the object first. await lastLocation.FetchIfNeededAsync(tk); DateTime l = lastLocation.Get<DateTime>(ParseContract.LocationTable.TIME_STAMP); lastUpdate = l.ToShortDateString() + " " + l.ToShortTimeString(); //Sync the local data. queue.LastUpdate = lastLocation.Get<DateTime>(ParseContract.LocationTable.TIME_STAMP); } else { lastUpdate = ""; queue.LastUpdate = DateTime.MinValue; } queue.UpdateInterval = interval; queue.Save(); }
/// <summary> /// Agent that runs a scheduled task /// </summary> /// <param name="task"> /// The invoked task /// </param> /// <remarks> /// This method is called when a periodic or resource intensive task is invoked /// </remarks> protected override async void OnInvoke(ScheduledTask task) { Utilities.WriteToExceptionLog("invoked log", DateTime.Now, new Exception("invoked")); ParseUser user = null; //Get the user credentials. String[] credential = Utilities.GetParseCredential(); //Get the location sending info stored in the phone, this does not require internet connection UnsentLocationQueue queue = new UnsentLocationQueue(credential[0]); DateTime lastUpdate = queue.LastUpdate;//The lastUpdate stored in the phone, should be the same as the one in the server. int interval = queue.UpdateInterval;//The update interval stored in the phone, should be the same as the one in the server. int unsentSize = queue.QueueSize(); Debug.WriteLine("Background task invoked:\ninterval: " + interval + "\nlast update: " + lastUpdate + "\nunsent size: " + unsentSize); if (unsentSize > 0)//First try to send the unsent locations if there is any. { try { ParseClient.Initialize(ParseContract.applicationID, ParseContract.windowsKey); Debug.WriteLine("Background agent logging in using: " + credential[0] + " " + credential[1]); await ParseUser.LogInAsync(credential[0], credential[1]); user = ParseUser.CurrentUser; await queue.SendLocations(user); } catch (Exception e) { Debug.WriteLine("Login failed in the background:"); Debug.WriteLine(e.ToString()); Utilities.WriteToExceptionLog("ScheduledAgent logging in", DateTime.Now, e); } } if (queue.QueueSize() > 0)//Display message when there are unsent locations. { //Utilities.ShowToast("WeAssist", "Failed to upload location data.", new Uri("/LoginPage.xaml", UriKind.Relative)); Debug.WriteLine("Sending unsent location failed"); } if (interval == 30 || IsTimeToSendData(interval, lastUpdate))//Then try to update the current location to the server. { //First get the new location. GeoPosition<GeoCoordinate> newLocation = await Utilities.getCurrentGeoPosition(); if (newLocation == null) { //Utilities.ShowToast("CitySafe", "Failed to obtain location data.", new Uri("/LoginPage.xaml", UriKind.Relative)); return; } if (queue.QueueSize() == 0)//Only send new data when previous data was sent. { try { if (user == null)//Only log in when ParseUser is not already logged in { ParseClient.Initialize(ParseContract.applicationID, ParseContract.windowsKey); Debug.WriteLine("Background agent logging in using: " + credential[0] + " " + credential[1]); await ParseUser.LogInAsync(credential[0], credential[1]); user = ParseUser.CurrentUser; } ////Get the update interval and lastUpdate from the server, they should be the same as the ones stored in the phone //int interval = user.Get<int>(ParseContract.UserTable.UPDATE_INTERVAL); ////Querying the database for the time of the last update, used to determine whether we should update now. //ParseObject lastLocation = user.Get<ParseObject>(ParseContract.UserTable.LOCATION(lastLocationIndex)); //await lastLocation.FetchIfNeededAsync(); //DateTime lastUpdate = lastLocation.Get<DateTime>(ParseContract.LocationTable.TIME_STAMP); Utilities.SaveLocationToParseUser(user, newLocation); await user.SaveAsync(); queue.LastUpdate = newLocation.Timestamp.DateTime; Debug.WriteLine("Location updated to the server for user: "******"CitySafe", "Failed to upload location data.", new Uri("/LoginPage.xaml", UriKind.Relative)); Debug.WriteLine("Failed to send location data to the server, stored it to the local location queue:"); Debug.WriteLine(e.ToString()); Utilities.WriteToExceptionLog("ScheduledAgent sending data", DateTime.Now, e); queue.Enqueue(newLocation); } } else//If the unsent data was not sent, just add the current location to the unsent data. queue.Enqueue(newLocation); } queue.Save(); #if DEBUG_AGENT ScheduledActionService.LaunchForTest(task.Name, TimeSpan.FromSeconds(60)); #endif NotifyComplete(); }