⚡️ Task Invoker ⚡️ Run code while your app is in the background

Task Invoker - Run C# code while your mobile app is in the background

This asset allows your mobile app to keep running code when the user for example pushes the home button on their Android or iOS device, or when the app is interrupted by an incoming call.

Available in the Unity Asset Store

Features
• Runs C# code while the app is in the background
• Invokes a C# callback on a configurable interval
• Supports Android and iOS
• Runs on the Unity main thread so Unity components can be accessed as usual
• Includes utilities for wrapping UnityWebRequests with tasks so that they keep running even if the app is sent to the background

Compatible with most devices
• Android devices supported by Unity 2017 or newer
• iOS devices supported by Unity 2017 or newer
• Unity Editor support

Additional Notes
• 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
• More info in the Online Documentation

Using the asset is simple
Here is an example of starting a task when the application is paused:

// Start invoking a C# callback when the app goes to the background
void OnApplicationPause(bool paused)
{
   if (paused)
   {
       // Start a task that invokes once every second (1000 milliseconds)
       taskID = Vuopaja.TaskInvoker.StartTask(1000, onInvoke);
   } else {
       // Stop the running task when the app is returned to the foreground
       Vuopaja.TaskInvoker.StopTask(taskID);
   }
}

void onInvoke(int taskId)
{
    // Do stuff while in the background
}

:zap: Get it from the Asset Store :zap:
Also check out Climbinary!

Hello!

When I execute big tasks, my loading icon freeze. Can i use this, to add the loading to the main thread and avoid the freeze?

Thanks

Hey!

This plugin makes it possible for a 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. This asset is not made for spreading work over different threads so I cannot recommend it for your use case.

Hi !
I have a question: I create an application with notifications. I need to send notifications when the application is in the background, so I try to create delayed notifications in invokers thread. Method with the creation process work well, but notifications are not sent.

Can it be solved ?
Thanks ^).

1000 apologies, it was my mistake, cause I used notifications manager with update.
All works perfect ))

No problem, I’m glad to hear you got it working!

Hi there Vauopaja,
I am very interested in this asset. I have been able to get my audio to run in the background while application is out of focus/paused. I need to be able to stop the audio after a timer runs out. I am building a sleep timer function into my relaxation app. Do you think that your plugin will help me execute the method to stop the audio?
I also sent an email with the same question.

Hey, thanks for the interest! I just replied to your email with more details but the short answer is that on Android this use case can be done with this plugin. But on iOS there are more limitations and the length of the timer might not be long as long as you would like.

1 Like

Hello !
Have a question.
I need to make WebRequests sequence, consist of 3 UnityWebRequest in background periodicaly (for example every 60 sec).
I have two ways how to do it:

  1. Create TaskInvoker func and send UnityWebRequests one by one without your wrapper and handle results in this method. (Or won’t this method work ?)

  2. In your API has WebRequestWrapper, which creating TaskInvoker itself. Would it work, if I create some TaskInvoker method and set this sequence inside and execute it one by one ? Or every request will create another thread and I cant await for the result of each request and then send another like in sequence ?

How to better organise it, if this two methods will not worked ?

For p.2 example:

 void SomeRequestSequence(int task_id)
{

            UnityWebRequest request = CreateJsonRequest(r_data);

            ResponceDataJson responce = null;

            WebRequestWrapper webRequestWrapper = new WebRequestWrapper();
            Action<WrappedRequest> completeHandler = (wrapper) =>
            {
                string json_text = wrapper.Request.downloadHandler.text;
                responce = new ResponceDataJson(wrapper.Request.url, wrapper.Request.responseCode, json_text);
            };
            Action<WrappedRequest, string> failHandler = (wrapper, reason) =>
            {
                responce =  new ResponceDataJson(wrapper.Request.url, wrapper.Request.responseCode, "");
            };

            webRequestWrapper.Completed += completeHandler;
            webRequestWrapper.Failed += failHandler;

            webRequestWrapper.Send(request, 100);

            webRequestWrapper.Completed -= completeHandler;
            webRequestWrapper.Failed -= failHandler;

           //Then create another request with handlers dependent on previous request result
           //......
}

Hey! You can use the wrapper for this but it is intended as an way to send single web requests so that a separate task is started for each of them. This will allow the requests finish even if the app is sent to the background and each request stops their own task once they finish.

I would use method 1. you mentioned for this use case and start one task with the first request, then when that finishes instead of stopping the task you send the next one in the sequence.

Here’s untested example code of that

List<UnityWebRequest> requests = new List<UnityWebRequest>();
int elapsedTime;

void StartSequence()
{
    createRequests();
    requests[0].SendWebRequest();
    TaskInvoker.StartTask(1000, onInvoke);
}

void createRequests(){
    requests.Add(UnityWebRequest.Get("url"));
    requests.Add(UnityWebRequest.Get("url"));
    requests.Add(UnityWebRequest.Get("url"));
}

// Called once per second
void onInvoke(int taskId)
{
    if (requests.Count > 0 && requests[0].isDone) {
        // Handle completed request here
        // ....
        requests.RemoveAt(0);

        // Start next one
        if (requests.Count > 0) requests[0].SendWebRequest();
        else TaskInvoker.StopTask(taskId);
    }
   
    // Redo everything 60 seconds after sequence was done
    if (requests.Count == 0) elapsedTime++;           
    if (elapsedTime >= 60) {
        createRequests();
        requests[0].SendWebRequest();
        elapsedTime = 0;
    }
}

Please note that when the user puts the app to the background this sequence would have time to only run once on iOS as the execution time is limited after the app is sent to the background. On Android this would run as long as the app was not killed. Proper unrestricted periodic background fetch is something I’m working on as an update for this package.

For IOS, what do you mean “sequence would have time to only run once on iOS” ?
Does it mean that If I run TaskInvoker on IOS, it will be executed only once, not repeatly ?
So I can put infinity cycle inside, or goto, which wll return execution to the beginning of this func.

Or thread will be stopped after some time in any way and how many time it has ?

The callback is invoked repeatedly just like on Android. But when the app goes to the background it will have some time decided by the iOS to finish running as it uses beginBackgroundTaskWithExpirationHandler inside. This time is usually up to a minute and depends on the device status like battery etc. If the OS expires the task the onExpire callback is invoked and you can do some clean up etc in there. After that the app is suspended. You can register a callback with the optional parameter in the StartTask method:

StartTask(int delay, TaskEvent onInvoke, TaskEvent onExpire = null);

This limitation is the reason why I’m working on an update to provide a way to do periodic updates even when the app is suspended or not running at all. But this will still take some time for me to do.

Hi,

Have you made any progress on the suspended bg periodic execution? I would be interested mainly in that functionality.

Cheers

Hey, I have a working version on iOS but the Android side is still incomplete. I’m afraid I can’t give you any accurate estimation on when the update is done but I’ll post here as soon as it is.

Hello, I bought the “Task Invoker” how could I modify it to get the orientation of the “accelerometer” or “Input.acceleration” of Unity?

For example, create a new function that allows me to obtain the data from the “accelerometer” every X time if it is in the background.

Thank you for your attention.

Hey, thank you for the purchase! I replied to your email about this in more detail but in short you can create a callback method that reads the orientation and then start a task with a delay like so:

void onInvoke(int taskID) {
    // Handle the orientation
    Debug.Log(Input.acceleration);
}

// Start a task with a repeating delay
Vuopaja.TaskInvoker.StartTask(1000, onInvoke);

EDIT: Please note that by default the Input.acceleration is not updated while the app is in the background

I have yet to purchase this asset but I have read the F.A.Q already. I can see that you state that you are only able to access the last updated position and the position, by default, will not update when the app is in the background. Do you by any chance know any good resources on this topic? My plan is to access GPS location in the background and use task invoker to send some haptic feedback to the phone to signal the user that some event has occurred in the app.

I have only read the Android and iOS documentation about their background location access but I remember deciding not to add the support for them in this package because of how strict the operation systems are about it. I’m afraid I don’t have any better resources than that but here are a couple links:

Bought your asset. Is it possible to use this asset to read from a mobile device accelerometer at regular intervals while the app is in the background, and save the data? Here’s what is needed. Whether the app is in foreground or background (will mostly be background), at a fixed interval (like every 10 seconds) read data from the mobile accelerometer (on Android and iOS) and add it to an array, then every 5 minutes push the stored data array to a remote webserver.

We tried the approach that you suggested above, but we had a problem. We used this code:
void onInvoke(int taskId)
{
elapsedTime++;
ResultText.text += " elapsedTime: " + elapsedTime + " z: " + Input.acceleration.z + " ";
}

What we found was that the output ResultText shows the elapsedTime incrementing as expected, but the Input.acceleration.z repeats the same value as the first value for each period in background, and gets only one accelerometer data value for each period in background, not each time onInvoke is called. This means that we have not succeeded in reading the accelerometer at a fixed interval while in the background.

Also, to confirm, when we ran the code that you posted above:

void onInvoke(int taskID) {
// Handle the orientation
Debug.Log(Input.acceleration);
}

we got the same 3-tuple values logged every second during each background period, even if the device was moved.

Do you know a way to resolve this?

If it is going to require native code to read the accelerometer or other device sensors repeatedly, would you be interested in writing this code? I notice that many of the questions above in the forum relate to accessing the device sensors.

Thank you