Search code examples
xamarin.iosnsurlsessionbackgrounding

Submitting data from Xamarin iOS when backgrounded


I have a weird problem in our current Xamarin project. As the app sends a larger chunk of data to the server, to protect it when app gets backgrounded, we're starting a long-running task (using the UIApplication.SharedApplication.BeginBackgroundTask / UIApplication.SharedApplication.EndBackgroundTask API). What's weird is that this works great when I build and run from my machine but several of my colleagues get a timeout error when running the exact same scenario when the app was build/deployed from their machines.

As far as I understand it running stuff in a long-running task like this should work. I should not have to specify backgrounding capabilities in info.plist. Also, as the HttpClient employ NSUrlSession for sending/receiving it should be protected from interruptions when the app gets backgrounded, right?

I can't figure out why the same code yields different behavior on the same device when built with different Macs. Could there be some setting somewhere in VS that could be local to the machine that would affect this behavior?

I'm out of ideas now so any hints would be greatly appreciated.

This is an example of code that works/fails depending on the Mac that built/deployed it:

public async Task Submit()
{
    // ... some irrelevant code
    BackgroundTask.Run(async () => await submitAsync()); // Form-level encapsulation of the UIApplication.SharedApplication.BeginBackgroundTask API
    // ... more irrelevant code
}

private async Task submitAsync()
{
    if (!IsSubmitAllowed)
        return;

    IsBusy = true;
    IsGoBackAllowed = IsGoNextAllowed = false;
    var statusIndicator = new StatusIndicator();
    await PopupNavigation.Instance.PushAsync(statusIndicator);
    try
    {
        statusIndicator.Status = "Saving TI";
        statusIndicator.Progress = 0.1;

        var submitted = await _service.SubmitAsync(Model); // ERROR! causes timeout exception for some
        var submittedId = submitted.BackendId;
    // ... etc.

Solution

  • Both of your assumptions seem to be wrong.

    First, beginBackgroundTaskWithExpirationHandler: doesn't grant unlimited background activity. Most notably:

    https://developer.apple.com/documentation/uikit/uiapplication/1623031-beginbackgroundtaskwithexpiratio?language=objc

    Apps running background tasks have a finite amount of time in which to run them

    Second, NSURLSession isn't enabled by default in the HttpClient, and overal NSURLSession is not something that handles transfers in the background by default, that is just possibility and it would be natural that HttpClient doesn't use this mode. Again check the documentation: https://developer.apple.com/documentation/foundation/nsurlsession