Prevent background fetch starting up app UI

Finlay Brown 1 Reputation point
2022-09-27T23:24:59.09+00:00

This issue exists in both Android and iOS

iOS
Background fetch is triggering the app to start up normally, i.e. running the AppDelegate.FinishedLaunching method.

this method along with initialization of syncfusion controls creates an instance of the app
LoadApplication(new App());

The follow through of this is that it also creates an instance of my regular app pages, and then runs the OnAppearing methods which download data from the web.
Meanwhile this is happening the background fetch is running as intended from AppDelegate.PerformFetch.

However the background fetch finishes before the OnAppearing web request completes, the background fetch then suspends the app.
A second background fetch starts later and only runs the AppDelegate.PreformFetch which seems to resume the app and causes the HttpClient from the original OnAppearing request to throw a timeout error.
The user then opens the app later and is presented with the exception dialog

The AppDelegate.FinishedLaunching method has a parameter UIApplication this has the property BackgroundTimeRemaining.
When the app is run normally this property is set to Double.MaxValue, however when manually running a background fetch via setting iOS Run Options, Execution Mode to BackgroundFetch this property is closer to 30.0, matching the 30 seconds to run a background fetch.
Despite this in the scenario I described above the BackgroundTimeRemaining is Double.MaxValue when the background fetch is triggered as above

How can I prevent the app from starting as described, is there a property I can check to see if the app is only trying to do a background fetch, or adjust the fetch to never also launch the FinishedLaunching method.

Android
I have so far been unable to as accurately diagnose, however it seems to be the same issue

MainActivty.OnCreate starts the app with
LoadApplication(new App());
while the JobScheduler has started my DownloadService to run a web request similar to the iOS PreformFetch method

Hopefully that fully explains my issue, if not I can clarify further

Sequence of events

public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate  
{  
    public Action BackgroundSessionCompletionHandler { get; set; }  
  
    //App starts here  
    public override bool FinishedLaunching(UIApplication app, NSDictionary options)  
    {  
        global::Xamarin.Forms.Forms.Init();  
        bool isInBackground = false;  
        if (app.BackgroundTimeRemaining != double.MaxValue) //This check is failing  
        {  
            isInBackground = true;  
        }  
        else  
        {  
            //3rd party initialization  
            UIApplication.SharedApplication.SetMinimumBackgroundFetchInterval(UIApplication.BackgroundFetchIntervalMinimum);  
        }  
        LoadApplication(new App(isBackground: isInBackground));  
        return base.FinishedLaunching(app, options);  
    }  
  
    //App gets to here later  
    public override async void PerformFetch(UIApplication application, Action<UIBackgroundFetchResult> completionHandler)  
    {   
        DataSync dataSync = new DataSync();   
        await dataSync.RunBackgroundSync();  
    }  
}  




public partial class App : Xamarin.Forms.Application  
{  
    public App(bool isBackground = false)  
    {  
        InitializeComponent();  
        IsInBackgroud = isBackground;  
        Database.Initialize();  
        if (!IsInBackgroud)  
        {  
            MainPage = new FlyoutPage();   
            //Flyout page the creates instances of my regular views,   
            //Once those pages are created this chain of events ends  
            //Then a race condition begins for the OnAppearing method which runs a web request  
            //And the AppDelegete PreformFetch Method  
        }  
    }  
}  
Xamarin
Xamarin
A Microsoft open-source app platform for building Android and iOS apps with .NET and C#.
5,293 questions
{count} votes