public override void DidEnterBackground (UIApplication application) { ourTask = application.BeginBackgroundTask(delegate { //this is the action that will run when the task expires if (ourTask != 0) //this check is because we want to avoid ending the same task twice { application.EndBackgroundTask(ourTask); //end the task ourTask = 0; //reset the id } }); //we start an asynchronous operation //so that we make sure that DidEnterBackground //executes normally new System.Action(delegate { MonoGameGame.EnterBackground(); //Since we are in an asynchronous method, //we have to make sure that EndBackgroundTask //will run on the application's main thread //or we might have unexpected behavior. application.BeginInvokeOnMainThread(delegate { if (ourTask != 0) //same as above { application.EndBackgroundTask(ourTask); ourTask = 0; } }); }).BeginInvoke(null, null); }
/// <Docs>Reference to the UIApplication that invoked this delegate method.</Docs> /// <remarks>Application are allocated approximately 5 seconds to complete this method. Application developers should use this /// time to save user data and tasks, and remove sensitive information from the screen.</remarks> /// <altmember cref="M:MonoTouch.UIKit.UIApplicationDelegate.WillEnterForeground"></altmember> /// <summary> /// Dids the enter background. /// </summary> /// <param name="application">Application.</param> public override void DidEnterBackground(UIApplication application) { Console.WriteLine("DidEnterBackground called..."); // Ask iOS for additional background time and prepare upload. taskId = application.BeginBackgroundTask(delegate { if (taskId != 0) { application.EndBackgroundTask(taskId); taskId = 0; } }); new System.Action(async delegate { await PrepareUpload(); application.BeginInvokeOnMainThread(delegate { if (taskId != 0) { application.EndBackgroundTask(taskId); taskId = 0; } }); }).BeginInvoke(null, null); }
/// <Docs>Reference to the UIApplication that invoked this delegate method.</Docs> /// <remarks>Application are allocated approximately 5 seconds to complete this method. Application developers should use this /// time to save user data and tasks, and remove sensitive information from the screen.</remarks> /// <altmember cref="M:MonoTouch.UIKit.UIApplicationDelegate.WillEnterForeground"></altmember> /// <summary> /// Dids the enter background. /// </summary> /// <param name="application">Application.</param> public override void DidEnterBackground (UIApplication application) { Console.WriteLine("DidEnterBackground called..."); // Ask iOS for additional background time and prepare upload. taskId = application.BeginBackgroundTask (delegate { if (taskId != 0) { application.EndBackgroundTask(taskId); taskId = 0; } }); new System.Action (async delegate { await PrepareUpload(); application.BeginInvokeOnMainThread(delegate { if (taskId != 0) { application.EndBackgroundTask(taskId); taskId = 0; } }); }).BeginInvoke (null, null); }
public override void DidEnterBackground(UIApplication application) { ourTask = application.BeginBackgroundTask(delegate { //this is the action that will run when the task expires if (ourTask != 0) //this check is because we want to avoid ending the same task twice { application.EndBackgroundTask(ourTask); //end the task ourTask = 0; //reset the id } }); //we start an asynchronous operation //so that we make sure that DidEnterBackground //executes normally new System.Action(delegate { MonoGameGame.EnterBackground(); //Since we are in an asynchronous method, //we have to make sure that EndBackgroundTask //will run on the application's main thread //or we might have unexpected behavior. application.BeginInvokeOnMainThread(delegate { if (ourTask != 0) //same as above { application.EndBackgroundTask(ourTask); ourTask = 0; } }); }).BeginInvoke(null, null); }
public void SetUpApp(UIApplication app) { try { Strings.Culture = new System.Globalization.CultureInfo(NSLocale.CurrentLocale.LanguageCode); } catch (Exception ex) { LogManager.Shared.Log($"Error setting Culture {System.Threading.Thread.CurrentThread.CurrentCulture}"); } SimpleAuth.OnePassword.Activate(); ApiManager.Shared.Load(); App.AlertFunction = (t, m) => { new UIAlertView(t, m, null, "Ok").Show(); }; App.Invoker = app.BeginInvokeOnMainThread; App.OnPlaying = () => { if (playingBackground != 0) { return; } playingBackground = app.BeginBackgroundTask(() => { app.EndBackgroundTask(playingBackground); playingBackground = 0; }); }; App.OnStopped = () => { if (playingBackground == 0) { return; } app.EndBackgroundTask(playingBackground); playingBackground = 0; }; App.OnShowSpinner = (title) => { BTProgressHUD.ShowContinuousProgress(title, ProgressHUD.MaskType.Clear); }; App.OnDismissSpinner = BTProgressHUD.Dismiss; App.OnCheckForOffline = (message) => { var tcs = new System.Threading.Tasks.TaskCompletionSource <bool>(); new AlertView(Strings.DoYouWantToContinue, message) { { Strings.Continue, () => tcs.TrySetResult(true) }, { Strings.Nevermind, () => tcs.TrySetResult(false), true }, }.Show(window.RootViewController); return(tcs.Task); }; NotificationManager.Shared.LanguageChanged += (s, e) => { window.RootViewController = new RootViewController(); }; #pragma warning disable 4014 App.Start(); #pragma warning restore 4014 AutolockPowerWatcher.Shared.CheckStatus(); }
// This method should be used to release shared resources and it should store the application state. // If your application supports background exection this method is called instead of WillTerminate // when the user quits. public async override void DidEnterBackground(UIApplication uiApplication) { nint enterBackgroundTaskId = uiApplication.BeginBackgroundTask(() => { // not much to do if we run out of time. just report it. string message = "Ran out of background time while entering background."; SensusServiceHelper.Get().Logger.Log(message, LoggingLevel.Normal, GetType()); SensusException.Report(message); }); iOSSensusServiceHelper serviceHelper = SensusServiceHelper.Get() as iOSSensusServiceHelper; // if the callback scheduler is timer-based and gps is not running then we need to request remote notifications if (SensusContext.Current.CallbackScheduler is iOSTimerCallbackScheduler scheduler) { bool gpsIsRunning = SensusServiceHelper.Get().GetRunningProtocols().SelectMany(x => x.Probes).OfType <ListeningLocationProbe>().Any(x => x.Enabled); await scheduler.RequestNotificationsAsync(gpsIsRunning); } // save app state await serviceHelper.SaveAsync(); uiApplication.EndBackgroundTask(enterBackgroundTaskId); }
public override void DidEnterBackground(UIApplication application) { // Console.WriteLine ("AppDelegate.DidEnterBackground method fired."); nint taskID = 0; Action backgroundTimerExpired = delegate { application.EndBackgroundTask(taskID); taskID = UIApplication.BackgroundTaskInvalid; }; taskID = application.BeginBackgroundTask(backgroundTimerExpired); myLocationDelegate.DumpLocationsBufferToDatabase(); application.EndBackgroundTask(taskID); taskID = UIApplication.BackgroundTaskInvalid; }
public void SetUpApp(UIApplication app) { SimpleAuth.OnePassword.Activate(); ApiManager.Shared.Load(); App.AlertFunction = (t, m) => { new UIAlertView(t, m, null, "Ok").Show(); }; App.Invoker = app.BeginInvokeOnMainThread; App.OnPlaying = () => { if (playingBackground != 0) { return; } playingBackground = app.BeginBackgroundTask(() => { app.EndBackgroundTask(playingBackground); playingBackground = 0; }); }; App.OnStopped = () => { if (playingBackground == 0) { return; } app.EndBackgroundTask(playingBackground); playingBackground = 0; }; App.OnShowSpinner = (title) => { BTProgressHUD.ShowContinuousProgress(title, ProgressHUD.MaskType.Clear); }; App.OnDismissSpinner = BTProgressHUD.Dismiss; App.OnCheckForOffline = (message) => { var tcs = new System.Threading.Tasks.TaskCompletionSource <bool>(); new AlertView(Strings.DoYouWantToContinue, message) { { Strings.Continue, () => tcs.TrySetResult(true) }, { Strings.Nevermind, () => tcs.TrySetResult(false), true }, }.Show(window.RootViewController); return(tcs.Task); }; #pragma warning disable 4014 App.Start(); #pragma warning restore 4014 }
public override void WillEnterForeground(UIApplication application) { // Called as part of the transiton from background to active state. // Here you can undo many of the changes made on entering the background. if (_isInBackground) { application.EndBackgroundTask(_backgroundTaskId); _isInBackground = false; } }
public override void WillEnterForeground(UIApplication app) { Logger.Log("WillEnterForeground() - coming from background into foreground"); // End task, no longer needed. if (this.taskId != -1) { app.EndBackgroundTask(this.taskId); this.taskId = -1; } }
public override void WillEnterForeground(UIApplication app) { Logger.Log("WillEnterForeground() - coming from background into foreground"); // --------------------------------------------------------------- // Exercise-1 if (this.taskId != -1) { app.EndBackgroundTask(this.taskId); this.taskId = -1; } }
public override Thread RunInBackground(VoidDelegate task) { ParameterizedThreadStart pts = delegate { int ourTask = 0; UIApplication application = UIApplication.SharedApplication; if (UIDevice.CurrentDevice.IsMultitaskingSupported) { application.BeginBackgroundTask(delegate { //expired if (ourTask != 0) { application.EndBackgroundTask(ourTask); ourTask = 0; } }); } task(); if (ourTask != 0) { application.BeginInvokeOnMainThread(delegate { if (ourTask != 0) //same as above { application.EndBackgroundTask(ourTask); ourTask = 0; } }); } }; Thread t = new Thread(pts); t.Priority = ThreadPriority.Highest; t.IsBackground = true; t.Start(); return(t); }
public override void DidEnterBackground(UIApplication application) { Trace.WriteLine(Trace.kKinskyTouch, "AppDelegate.DidEnterBackground"); int task = 0; task = application.BeginBackgroundTask(delegate { if (task != 0) { application.EndBackgroundTask(task); task = 0; } }); Trace.WriteLine(Trace.kKinskyTouch, "AppDelegate.DidEnterBackground 1"); iScheduler.Schedule(() => { Trace.WriteLine(Trace.kKinskyTouch, "AppDelegate.DidEnterBackground 2"); if (iStackStarted) { Helper.Helper.Stack.Stop(); iStackStarted = false; } Trace.WriteLine(Trace.kKinskyTouch, "AppDelegate.DidEnterBackground 3"); application.BeginInvokeOnMainThread(delegate { Trace.WriteLine(Trace.kKinskyTouch, "AppDelegate.DidEnterBackground 4"); if (task != 0) { application.EndBackgroundTask(task); task = 0; } }); }); Trace.WriteLine(Trace.kKinskyTouch, "AppDelegate.DidEnterBackground 5"); }
public override void DidEnterBackground(UIApplication application) { bgTask = application.BeginBackgroundTask(() => { application.EndBackgroundTask(bgTask); bgTask = UIApplication.BackgroundTaskInvalid; }); DispatchQueue.GetGlobalQueue(DispatchQueuePriority.Default).DispatchAsync(() => { Console.WriteLine("Starting background task {0}", bgTask); // track some events and set some people properties var mixpanel = Mixpanel.SharedInstance; mixpanel?.RegisterSuperProperties(NSDictionary.FromObjectAndKey(new NSString("Background Super Property"), new NSString("Hi!"))); mixpanel?.Track("Background Event"); mixpanel?.People.Set("Background Property", new NSDate()); Console.WriteLine("Ending background task {0}", bgTask); application.EndBackgroundTask(bgTask); bgTask = UIApplication.BackgroundTaskInvalid; }); Console.WriteLine("Dispatched background task {0}", bgTask); }
public override async void RegisteredForRemoteNotifications(UIApplication application, NSData deviceToken) { // hang on to the token. we register for remote notifications after initializing the helper, // so this should be fine. iOSSensusServiceHelper serviceHelper = SensusServiceHelper.Get() as iOSSensusServiceHelper; serviceHelper.PushNotificationTokenData = deviceToken; // update push notification registrations. this depends on internet connectivity to S3 // so it might hang if connectivity is poor. ensure we don't violate execution limits. CancellationTokenSource cancellationTokenSource = new CancellationTokenSource(); nint updatePushNotificationRegistrationsTaskId = application.BeginBackgroundTask(cancellationTokenSource.Cancel); await serviceHelper.UpdatePushNotificationRegistrationsAsync(cancellationTokenSource.Token); application.EndBackgroundTask(updatePushNotificationRegistrationsTaskId); }
// This method should be used to release shared resources and it should store the application state. // If your application supports background exection this method is called instead of WillTerminate // when the user quits. public override void DidEnterBackground(UIApplication uiApplication) { (SensusContext.Current.CallbackScheduler as iOSCallbackScheduler).CancelSilentNotifications(); iOSSensusServiceHelper serviceHelper = SensusServiceHelper.Get() as iOSSensusServiceHelper; // save app state in background nint saveTaskId = uiApplication.BeginBackgroundTask(() => { // not much we can do if we run out of time... }); serviceHelper.SaveAsync().ContinueWith(finishedTask => { uiApplication.EndBackgroundTask(saveTaskId); }); }
// This method should be used to release shared resources and it should store the application state. // If your application supports background exection this method is called instead of WillTerminate // when the user quits. public override void DidEnterBackground(UIApplication uiApplication) { (SensusContext.Current.Notifier as IiOSNotifier).CancelSilentNotifications(); iOSSensusServiceHelper serviceHelper = SensusServiceHelper.Get() as iOSSensusServiceHelper; serviceHelper.IssuePendingSurveysNotificationAsync(true, true); // save app state in background nint saveTaskId = uiApplication.BeginBackgroundTask(() => { }); serviceHelper.SaveAsync(() => { uiApplication.EndBackgroundTask(saveTaskId); }); }
// This method should be used to release shared resources and it should store the application state. // If your application supports background exection this method is called instead of WillTerminate // when the user quits. public override void DidEnterBackground(UIApplication uiApplication) { iOSSensusServiceHelper serviceHelper = SensusServiceHelper.Get() as iOSSensusServiceHelper; // app is no longer active, so reset the activation ID serviceHelper.ActivationId = null; serviceHelper.IssuePendingSurveysNotificationAsync(true, true); // save app state in background nint saveTaskId = uiApplication.BeginBackgroundTask(() => { }); serviceHelper.SaveAsync(() => { uiApplication.EndBackgroundTask(saveTaskId); }); }
// This method should be used to release shared resources and it should store the application state. // If your application supports background exection this method is called instead of WillTerminate // when the user quits. public override void DidEnterBackground(UIApplication application) { iOSSensusServiceHelper serviceHelper = SensusServiceHelper.Get() as iOSSensusServiceHelper; // app is no longer active, so reset the activation ID serviceHelper.ActivationId = null; // leave the user a notification if a prompt is currently running if (iOSSensusServiceHelper.PromptForInputsRunning) serviceHelper.IssueNotificationAsync("Please open to provide responses.", null); // save app state in background nint saveTaskId = application.BeginBackgroundTask(() => { }); serviceHelper.SaveAsync(() => { application.EndBackgroundTask(saveTaskId); }); }
// This method should be used to release shared resources and it should store the application state. // If your application supports background exection this method is called instead of WillTerminate // when the user quits. public async override void DidEnterBackground(UIApplication uiApplication) { nint enterBackgroundTaskId = uiApplication.BeginBackgroundTask(() => { // not much to do if we run out of time. just report it. string message = "Ran out of background time while entering background."; SensusServiceHelper.Get().Logger.Log(message, LoggingLevel.Normal, GetType()); SensusException.Report(message); }); iOSSensusServiceHelper serviceHelper = SensusServiceHelper.Get() as iOSSensusServiceHelper; // cancel all silent notifications, which should never be presented to the user. if these notifications // are not cancelled and the app enters the background, then they will appear in the notification // tray and confuse the user. (SensusContext.Current.CallbackScheduler as iOSCallbackScheduler).CancelSilentNotifications(); // save app state await serviceHelper.SaveAsync(); uiApplication.EndBackgroundTask(enterBackgroundTaskId); }
public override bool FinishedLaunching(UIApplication uiApplication, NSDictionary launchOptions) { DateTime finishLaunchStartTime = DateTime.Now; UIDevice.CurrentDevice.BatteryMonitoringEnabled = true; SensusContext.Current = new iOSSensusContext { Platform = Sensus.Context.Platform.iOS, MainThreadSynchronizer = new MainConcurrent(), SymmetricEncryption = new SymmetricEncryption(SensusServiceHelper.ENCRYPTION_KEY), PowerConnectionChangeListener = new iOSPowerConnectionChangeListener() }; SensusContext.Current.CallbackScheduler = new iOSTimerCallbackScheduler(); // new UNUserNotificationCallbackScheduler(); SensusContext.Current.Notifier = new UNUserNotificationNotifier(); UNUserNotificationCenter.Current.Delegate = new UNUserNotificationDelegate(); // we've seen cases where previously terminated runs of the app leave behind // local notifications. clear these out now. any callbacks these notifications // would have triggered are about to be rescheduled when the app is actived. (SensusContext.Current.Notifier as iOSNotifier).RemoveAllNotifications(); // initialize stuff prior to app load Forms.Init(); FormsMaps.Init(); // initialize the syncfusion charting system #pragma warning disable RECS0026 // Possible unassigned object created by 'new' new SfChartRenderer(); #pragma warning restore RECS0026 // Possible unassigned object created by 'new' ZXing.Net.Mobile.Forms.iOS.Platform.Init(); // load the app, which starts crash reporting and analytics telemetry. LoadApplication(new App()); // we have observed that, if the app is in the background and a push notification arrives, // then ios may attempt to launch the app and call this method but only provide a few (~5) // seconds for this method to return. exceeding this time results in a fored termination by // ios. as we're about to deserialize a large JSON object below when initializing the service // helper, we need to be careful about taking up too much time. start a background task to // obtain as much background time as possible and report timeouts. needs to be after app load // in case we need to report a timeout exception. nint finishLaunchingTaskId = uiApplication.BeginBackgroundTask(() => { string message = "Ran out of time while finishing app launch."; SensusException.Report(message); Console.Error.WriteLine(message); }); // initialize service helper. must come after context initialization. desirable to come // after app loading, in case we crash. crash reporting is initialized when the app // object is created. nothing in the app creating and loading loop will depend on having // an initialized service helper, so we should be fine. SensusServiceHelper.Initialize(() => new iOSSensusServiceHelper()); // register for push notifications. must come after service helper initialization as we use // the serivce helper below to submit the remote notification token to the backends. if the // user subsequently denies authorization to display notifications, then all remote notifications // will simply be delivered to the app silently, per the following: // // https://developer.apple.com/documentation/uikit/uiapplication/1623078-registerforremotenotifications // UIApplication.SharedApplication.RegisterForRemoteNotifications(); #if UI_TESTING Forms.ViewInitialized += (sender, e) => { if (!string.IsNullOrWhiteSpace(e.View.StyleId)) { e.NativeView.AccessibilityIdentifier = e.View.StyleId; } }; Calabash.Start(); #endif uiApplication.EndBackgroundTask(finishLaunchingTaskId); // must come after app load base.FinishedLaunching(uiApplication, launchOptions); // record how long we took to launch. ios is eager to kill apps that don't start fast enough, so log information // to help with debugging. DateTime finishLaunchEndTime = DateTime.Now; SensusServiceHelper.Get().Logger.Log("Took " + (finishLaunchEndTime - finishLaunchStartTime) + " to finish launching.", LoggingLevel.Normal, GetType()); return(true); }
public override async void DidReceiveRemoteNotification(UIApplication application, NSDictionary userInfo, Action <UIBackgroundFetchResult> completionHandler) { UIBackgroundFetchResult remoteNotificationResult; // set up a cancellation token for processing within limits. the token will be cancelled // if we run out of time or an exception is thrown in this method. CancellationTokenSource cancellationTokenSource = null; nint?receiveRemoteNotificationTaskId = null; try { cancellationTokenSource = new CancellationTokenSource(); // we have limited time to process remote notifications: https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/pushing_updates_to_your_app_silently // start background task to (1) obtain any possible background processing time and (2) get // notified when background time is about to expire. we used to hard code a fixed amount // of time (~30 seconds per above link), but this might change without us knowing about it. SensusServiceHelper.Get().Logger.Log("Starting background task for remote notification processing.", LoggingLevel.Normal, GetType()); receiveRemoteNotificationTaskId = application.BeginBackgroundTask(() => { SensusServiceHelper.Get().Logger.Log("Cancelling token for remote notification processing due to iOS background processing limitations.", LoggingLevel.Normal, GetType()); cancellationTokenSource.Cancel(); }); NSDictionary aps = userInfo[new NSString("aps")] as NSDictionary; NSDictionary alert = aps[new NSString("alert")] as NSDictionary; PushNotification pushNotification = new PushNotification { Id = (userInfo[new NSString("id")] as NSString).ToString(), ProtocolId = (userInfo[new NSString("protocol")] as NSString).ToString(), Update = bool.Parse((userInfo[new NSString("update")] as NSString).ToString()), Title = (alert[new NSString("title")] as NSString).ToString(), Body = (alert[new NSString("body")] as NSString).ToString(), Sound = (aps[new NSString("sound")] as NSString).ToString() }; // backend key might be blank string backendKeyString = (userInfo[new NSString("backend-key")] as NSString).ToString(); if (!string.IsNullOrWhiteSpace(backendKeyString)) { pushNotification.BackendKey = new Guid(backendKeyString); } await SensusContext.Current.Notifier.ProcessReceivedPushNotificationAsync(pushNotification, cancellationTokenSource.Token); // even if the cancellation token was cancelled, we were still successful at downloading the updates. // any amount of update application we were able to do in addition to the download is bonus. updates // will continue to be applied on subsequent push notifications and health tests. remoteNotificationResult = UIBackgroundFetchResult.NewData; } catch (Exception ex) { SensusException.Report("Exception while processing remote notification: " + ex.Message + ". Push notification dictionary content: " + userInfo, ex); // we might have already cancelled the token, but we might have also just hit a bug. in // either case, cancel the token and set the result accordingly. try { cancellationTokenSource.Cancel(); } catch (Exception) { } remoteNotificationResult = UIBackgroundFetchResult.Failed; } finally { // we're done. ensure that the cancellation token cannot be cancelled any // longer (e.g., due to background time expiring above) by disposing it. if (cancellationTokenSource != null) { try { cancellationTokenSource.Dispose(); } catch (Exception) { } } // end the background task if (receiveRemoteNotificationTaskId.HasValue) { try { SensusServiceHelper.Get().Logger.Log("Ending background task for remote notification processing.", LoggingLevel.Normal, GetType()); application.EndBackgroundTask(receiveRemoteNotificationTaskId.Value); } catch (Exception) { } } } // invoke the completion handler to let ios know that, and how, we have finished. completionHandler?.Invoke(remoteNotificationResult); }