General
This plugin makes it possible for an Unity mobile app to request additional background execution time to finish some task when the user or OS puts the app to the background. For example, while interacting with a server it can prevent the system from suspending your app while the operation is in progress.
The plugin consists of an Android .aar library, iOS .mm library and a C# implementation. The included C# TaskInvoker class handles starting and stopping the background tasks. Started tasks invoke a C# callback method periodically while Unity is in either the background or the foreground. This means that you can start doing work with Task Invoker tasks whenever and doing so ensures that the tasks keeps running in case the app is sent to the background. The C# callback methods are invoked on the Unity main thread so Unity components can be accessed as usual.
Note: These tasks are meant for light background work, not for running the whole game in the background. Tasks will not run indefinitely: the tasks will stop running if the app is killed by the user or the OS.
Usage
Using the TaskInvoker is simple. You can start a task by calling the StartTask method. It returns an integer that identifies the task. This ID can be used to stop the task later. Remember to always stop the task once it's finished to save device resources and battery. If the expired event is invoked the task is stopped by the plugin and no further call to stop the task is needed.
Here is the script reference for TaskInvoker C# class:
// Parameters:
// delay - delay before each callback invoke in milliseconds
// onInvoke - callback used to do work while the app is in the background
// onExpire - optional callback that is called if the task is expired by the OS
// Returns: integer ID of the started task
public static int StartTask(int delay, TaskEvent onInvoke, TaskEvent onExpire = null);
// Stops a task with the given taskID
// Parameters:
// taskID - the ID of the task to stop
public static void StopTask(int taskID);
// Stops all running tasks
public static void StopAllTasks();
// Delegate for the callbacks
// Parameters:
// taskID - the ID of the task invoking this callback
public delegate void TaskEvent(int taskId);
Here are the steps to setup a simple usage scenario that logs the taskID once and then stops the task:
// include the code to be run in the background
void onInvoke(int taskID)
{
// Log the taskID
Debug.Log("Task invoked with taskID: " + taskID);
// Stop the task
Vuopaja.TaskInvoker.StopTask(taskID);
}
// Call StartTask method with the created callback
// This can be called wherever inside the Unity application
// Set the delay to 1000 milliseconds
Vuopaja.TaskInvoker.StartTask(1000, onInvoke);
Android Details
The .aar library consists of an interface to be used with AndroidJavaProxy and a class to start and stop background tasks. The background tasks run as long as the process is alive. The tasks will stop invoking if the user or the OS kills the process. The Expired event present in the ITaskInvoker will not be invoked on Android because the killing of the process cannot be catched so that an event could still be invoked. Since the newer OS versions like Android 14 the background time is limited. Usually the tasks can run for about 10 minutes but that time will depend on the device and usage.
iOS Details
The iOS plugin uses beginBackgroundTaskWithExpirationHandler to run the background tasks. You can find more details about it in that link. The expiration handler invokes the Expired event in the TaskInvoker C# class so that the case where the operation being run was not completed in time before expiration can be handled.
Examples
There are two example scenes included in the package. One example runs a counter that invokes once per second while the app is in background and displays the elapsed background time in the UI. The other example has an input field in the UI and a button to send a GET request to the link written in the input field. This is to demonstrate that you can use the Task Invoker to start all your web requests with a task so that they will complete even if the app is sent to the background.
Counter Example
MonoBehaviour's OnApplicationPause method is invoked when the Unity application is sent to the background. This is used to start a new Task Invoker task that runs once per second. Then the task is stopped when the app is returned to the foreground.
void OnApplicationPause(bool paused)
{
// Start the counter on pause
if (paused)
{
// Start a task that invokes once every second (1000 milliseconds)
currentTaskID = TaskInvoker.StartTask(1000, onInvoke, onExpire);
}
else if (currentTaskID != -1)
{
// Stop the running task when entering foreground
TaskInvoker.StopTask(currentTaskID);
}
}
The onInvoke callback is simple. It counts the times it is invoked and calls a method to update the UI:
{
elapsedTime++;
updateUI();
}
WebRequest Example
This example shows how you can use the included utility class WebRequestWrapper to start all your web requests with a task so that they will complete even if the app is sent to the background.
An instance of the WebRequestWrapper is created and callbacks are registered to the events:
webRequestWrapper = new WebRequestWrapper();
webRequestWrapper.Completed += onCompleted;
webRequestWrapper.Failed += onFailed;
Using the wrapper is simple:
var request = UnityWebRequest.Get("https://www.vuopaja.com");
// Send the created request using the wrapper.
// The wrapper starts a TaskInvoker task so that if the user/OS sends the app to
// the background during this WebRequest it will continue running in the background.
// Takes milliseconds as a parameter that defines how often the wrapper
// checks for the progress of the request.
webRequestWrapper.Send(request, 100);
The wrapper invokes events when the request completes or fails:
{
// Handle completed WebRequest
Debug.Log("Download completed");
}
void onFailed(WrappedRequest wrappedRequest, string reason)
{
// Handle failure
Debug.LogError(reason);
}
Questions
Be sure to check out the Frequently Asked Questions for common questions about Task Invoker.
If you have any other questions click here for contact information.