Xamarin Background Tasks

Background Tasks are a way to run a task, in the background, outside the lifecycle of your mobile app. This is different than running in a background thread, in some cases, it is running in a completely different process. Background tasks enable you to run code at specific intervals, or have tasks continue to run, even if the app is closed, which is useful in such situations as a large file download. Each platform has a different method of dealing with background tasks. We will also look into how to interact with them in Xamarin Forms.

I also created a GitHub repo BackgroundTasks, if you want to see some complete sample code.

Android Services

To run a background task in Android, you simply use a Service. Android generally classifies tasks as either Long Running Tasks or Periodic Tasks. Either of these, is reasonable grounds to create a Service. What type of Service you want to create, depends on your use, however for this example we will be looking at the Started Service. A Started Service, can be called via an external event or from an activity. This service will continue, regardless of the app state, until you tell it to stop.

[Service]
public class PeriodicService : Service
{ 
    public override IBinder OnBind(Intent intent)
    {
        return null;
    }

    public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)
    {
        // From shared code or in your PCL
        

        return StartCommandResult.NotSticky;
    }
}

You can start this service in your Android code, as follows.

var intent = new Intent (this, typeof(PeriodicService));
StartService(intent);

Or you can use the Alarm Manager to periodically call it.

Alarm Manager

If we want a periodic background task, the Alarm Manager provides an easy way to trigger your service at specified intervals. To setup your app to be called periodically, you need to add in this code.

Create a BroadcastReceiver

[BroadcastReceiver]
public class BackgroundReceiver : BroadcastReceiver
{
    public override void OnReceive(Context context, Intent intent)
    {
        PowerManager pm = (PowerManager)context.GetSystemService(Context.PowerService);
        PowerManager.WakeLock wakeLock = pm.NewWakeLock(WakeLockFlags.Partial, "BackgroundReceiver");
        wakeLock.Acquire();

        // Run your code here

        wakeLock.Release();
    } 
}

iOS Backgrounding

Check out Xamarin’s documentation on iOS Backgrounding for more details about each one. For this example I will be using Background Fetch.

First, enable Background Fetch. Go to Properties > iOS Application and Background Modes to enable Background Fetch.

Then in your AppDelegate.cs in FinishedLaunching add in the following line.

public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
    global::Xamarin.Forms.Forms.Init();
    LoadApplication(new App());

    UIApplication.SharedApplication.SetMinimumBackgroundFetchInterval(UIApplication.BackgroundFetchIntervalMinimum);

    return base.FinishedLaunching(app, options);
}

Then override PerformFetch to run code on each fetch.

public override void PerformFetch(UIApplication application, Action<UIBackgroundFetchResult> completionHandler)
{
    // Check for new data, and display it


    // Inform system of fetch results
    completionHandler(UIBackgroundFetchResult.NewData);
}

If you want to simulate a background fetch, you currently can’t do this through Visual Studio on Windows. You will need to do it via the Mac Build Host.

UWP Background Tasks

For background tasks in UWP, we need to create a new runtime component.

Add a reference to this new component from your UWP app.

Add a background task to your component.

public sealed class ExampleBackgroundTask : IBackgroundTask
{
    BackgroundTaskDeferral _deferral;
    public void Run(IBackgroundTaskInstance taskInstance)
    {
        _deferral = taskInstance.GetDeferral();
 
        // Run your background task code here

        _deferral.Complete();
    }
}

Now, we need to make sure we register the Background Task in the appxmanifest.

Finally, we need to trigger the background task. In your UWP app, create and register the background task.

private async Task BackgroundTask()
{

    BackgroundExecutionManager.RemoveAccess();

    await BackgroundExecutionManager.RequestAccessAsync();

    var builder = new BackgroundTaskBuilder();

    builder.Name = "BackgroundTask";
    builder.TaskEntryPoint = "UWPRuntimeComponent.BackgroundTask";
    builder.SetTrigger(new SystemTrigger(SystemTriggerType.InternetAvailable, false));

    BackgroundTaskRegistration task = builder.Register();

    task.Completed += Task_Completed;
}

private void Task_Completed(BackgroundTaskRegistration sender, BackgroundTaskCompletedEventArgs args)
{
    var settings = Windows.Storage.ApplicationData.Current.LocalSettings;
    var key = "BackgroundTask";
    var message = settings.Values[key].ToString();

    // Run your background task code here
    MessagingCenter.Send<object, string>(this, "UpdateLabel", message);
}

You also should check if it is registered, before trying to register it again, and deregistering it, if appropriate. You can do this with the following code.

private void Deregister()
{
    var taskName = "BackgroundTask";

    foreach (var task in BackgroundTaskRegistration.AllTasks)
        if (task.Value.Name == taskName)
            task.Value.Unregister(true);
}

private bool IsRegistered()
{
    var taskName = "BackgroundTask";

    foreach (var task in BackgroundTaskRegistration.AllTasks)
        if (task.Value.Name == taskName)
            return true;

 return false;
}

Xamarin Forms Integration

As you have just read, each platform is quite different in how it handles background tasks. If you want to call or integrate with Xamarin Forms, we will need to create a certain level of abstraction to start the service if needed and receive messages back.

Using an interface such as below, you can inject this into your Xamarin Forms application to start the service when needed.

public interface IBackgroundService
{
    void Start();
}

However, this will also be one of the very rare occasions, where I would recommend MessagingCenter as a possible alternative. But only when receiving information back, not for starting it. For example, from within the Service, AppDelegate or BackgroundTask add this code.

MessagingCenter.Send<object, string>(this, "UpdateLabel", "Hello from [Platform]");

And subscribe to it from within your Xamarin Forms application.

MessagingCenter.Subscribe<object, string>(this, "UpdateLabel", (s,e) => { 
    Device.BeginInvokeOnMainThread(() =>
    {
        BackgroundServiceLabel.Text = e;
    });
});

Resource Conflicts

As a word of caution, be aware of what service or application is accessing an application, for example a SQLite DB. Two processes can not access a file at the same time, unless read-only. Hence ensure only one process is performing actions on file’s or locked resources.


XAMARIN.FORMS MONTHLY NEWSLETTER

JOIN 1,200+ SUBSCRIBERS

  1. Don't miss out on updates
  2. The latest info from this site, Xamarin and the community
  3. Unsubscribe at any time*

* We use MailChimp, with double opt-in, and instant unsubscribe

Microsoft MVP | Xamarin MVP | Xamarin Certified Developer |
Exrin MVVM Framework | Xamarin Forms Developer | Melbourne, Australia

Related Posts

15 Comments

  1. My Helper

    Excellent. Thanks a bunch.

    I use MessagingCenter even to trigger a Background Task. However wondering how we can create a Background Task as a Dependency Service? Could you show an example/update your git sample repo? At lease for android, if you don’t have time for all.

    Thank you so much for your amazing contribution to the community!

    1. Adam Pedley

      You would create a new class and implement an interface, such as IBackgroundTask. Then inject that into your dependency injection framework. This will only start or stop the background task, but the task will run separately.

      1. My Helper

        Yep. Apologies. I am actually aware of how dependency services work. However what I meant is, what is the implementation code for IBackgroundTask. I am unable to find that out.

        public class BackgroundTask: IBackgroundTask
        {
        public void Start()
        {
        //how to call start service here? as we call in MainActivity..
        }
        }

        1. Adam Pedley

          You just need to add in the platform specific implementation. e.g. On Android you would have

          var intent = new Intent (this, typeof(PeriodicService));
          StartService(intent);

          inside the Start().

  2. My Helper

    Did you mean to have it implemented in the MainActivity?

    MainActivity: IBackgroundTask,

    (if android of course as an example)

  3. Enrico

    Hi, I have a question about background task, MessagingCenter and sending files. I want to send a lot of images from the app to my server. Is there a best practice?
    My procedure starts with a MessagingCenter.Send, another procedure catches the message and sends a new message and so on. The procedure is working until around 500 images and then the app crashes.

    1. Adam Pedley

      Each platform has a special task for background downloads (e.g. Background Fetch), I am going to assume this also caters for uploads as well, but I haven’t personally done this before.

      Also are you sure the app is crashing, or its just going to sleep. Each platform places its own rules on background tasks, and it doesn’t just let them run whenever they want. It may shut them down and start them up again later when resources are available.

  4. Hideyoshi

    Hi, Adam.
    I have an PCL app that is working on Android, iOS, UWP and WinPhone.
    on UWP and WinPhone I created and registered a background task as you mentioned above..the problem is that in the Run() method I need to call DependencyService..and it’s not working, it says that I need to initialize the Xamarin forms first.
    Do you know something about this?
    Thank you,
    Hideyoshi

  5. Greggz

    Hello! Great post, helped me a lot! For all of you out there that are clueless as me just adding that you need android permissions for WAKE_LOCK in manifest. Again thanks a lot Adam!

    1. Adam Pedley

      You would need to use something like the AlarmManager in Android to schedule this. For iOS, there is currently no way you can define it. You would have to do something like Silent Push Notifications, to trigger it. This would require you sending the notifications from your server, and I generally recommend you steer clear of this approach.

  6. Nguyen Thanh Liem

    Can you make a tutorial combine your Background Task topic with Toast Notification topic. To make a sample send toast notification from background task at specific time.
    Thank you!