Search Unity

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

Discussion in 'Assets and Asset Store' started by Vuopaja, Jun 4, 2020.

  1. Vuopaja

    Vuopaja

    Joined:
    Mar 21, 2020
    Posts:
    17


    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:
    Code (CSharp):
    1. // Start invoking a C# callback when the app goes to the background
    2. void OnApplicationPause(bool paused)
    3. {
    4.    if (paused)
    5.    {
    6.        // Start a task that invokes once every second (1000 milliseconds)
    7.        taskID = Vuopaja.TaskInvoker.StartTask(1000, onInvoke);
    8.    } else {
    9.        // Stop the running task when the app is returned to the foreground
    10.        Vuopaja.TaskInvoker.StopTask(taskID);
    11.    }
    12. }
    13.  
    14. void onInvoke(int taskId)
    15. {
    16.     // Do stuff while in the background
    17. }

     
    Last edited: Nov 13, 2020
  2. MateAndor

    MateAndor

    Joined:
    Nov 5, 2014
    Posts:
    70
    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
     
  3. Vuopaja

    Vuopaja

    Joined:
    Mar 21, 2020
    Posts:
    17
    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.
     
  4. Luchunpen_0

    Luchunpen_0

    Joined:
    Aug 7, 2014
    Posts:
    58
    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 ^).
     
  5. Luchunpen_0

    Luchunpen_0

    Joined:
    Aug 7, 2014
    Posts:
    58
    1000 apologies, it was my mistake, cause I used notifications manager with update.
    All works perfect ))
     
  6. Vuopaja

    Vuopaja

    Joined:
    Mar 21, 2020
    Posts:
    17
    No problem, I'm glad to hear you got it working!
     
  7. MickeyJ_88

    MickeyJ_88

    Joined:
    Nov 21, 2019
    Posts:
    6
    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.
     
  8. Vuopaja

    Vuopaja

    Joined:
    Mar 21, 2020
    Posts:
    17
    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.
     
    MickeyJ_88 likes this.
  9. Luchunpen_0

    Luchunpen_0

    Joined:
    Aug 7, 2014
    Posts:
    58
    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 ?
     
    Last edited: Mar 10, 2021
  10. Luchunpen_0

    Luchunpen_0

    Joined:
    Aug 7, 2014
    Posts:
    58
    For p.2 example:

    Code (CSharp):
    1.  void SomeRequestSequence(int task_id)
    2. {
    3.  
    4.             UnityWebRequest request = CreateJsonRequest(r_data);
    5.  
    6.             ResponceDataJson responce = null;
    7.  
    8.             WebRequestWrapper webRequestWrapper = new WebRequestWrapper();
    9.             Action<WrappedRequest> completeHandler = (wrapper) =>
    10.             {
    11.                 string json_text = wrapper.Request.downloadHandler.text;
    12.                 responce = new ResponceDataJson(wrapper.Request.url, wrapper.Request.responseCode, json_text);
    13.             };
    14.             Action<WrappedRequest, string> failHandler = (wrapper, reason) =>
    15.             {
    16.                 responce =  new ResponceDataJson(wrapper.Request.url, wrapper.Request.responseCode, "");
    17.             };
    18.  
    19.             webRequestWrapper.Completed += completeHandler;
    20.             webRequestWrapper.Failed += failHandler;
    21.  
    22.             webRequestWrapper.Send(request, 100);
    23.  
    24.             webRequestWrapper.Completed -= completeHandler;
    25.             webRequestWrapper.Failed -= failHandler;
    26.  
    27.            //Then create another request with handlers dependent on previous request result
    28.            //......
    29. }
    30.  
     
  11. Vuopaja

    Vuopaja

    Joined:
    Mar 21, 2020
    Posts:
    17
    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
    Code (CSharp):
    1. List<UnityWebRequest> requests = new List<UnityWebRequest>();
    2. int elapsedTime;
    3.  
    4. void StartSequence()
    5. {
    6.     createRequests();
    7.     requests[0].SendWebRequest();
    8.     TaskInvoker.StartTask(1000, onInvoke);
    9. }
    10.  
    11. void createRequests(){
    12.     requests.Add(UnityWebRequest.Get("url"));
    13.     requests.Add(UnityWebRequest.Get("url"));
    14.     requests.Add(UnityWebRequest.Get("url"));
    15. }
    16.  
    17. // Called once per second
    18. void onInvoke(int taskId)
    19. {
    20.     if (requests.Count > 0 && requests[0].isDone) {
    21.         // Handle completed request here
    22.         // ....
    23.         requests.RemoveAt(0);
    24.  
    25.         // Start next one
    26.         if (requests.Count > 0) requests[0].SendWebRequest();
    27.         else TaskInvoker.StopTask(taskId);
    28.     }
    29.    
    30.     // Redo everything 60 seconds after sequence was done
    31.     if (requests.Count == 0) elapsedTime++;          
    32.     if (elapsedTime >= 60) {
    33.         createRequests();
    34.         requests[0].SendWebRequest();
    35.         elapsedTime = 0;
    36.     }
    37. }
    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.
     
  12. Luchunpen_0

    Luchunpen_0

    Joined:
    Aug 7, 2014
    Posts:
    58
    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 ?
     
    Last edited: Mar 11, 2021
  13. Vuopaja

    Vuopaja

    Joined:
    Mar 21, 2020
    Posts:
    17
    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:
    Code (CSharp):
    1. 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.
     
  14. gwiasdeczka2

    gwiasdeczka2

    Joined:
    Sep 27, 2015
    Posts:
    4
    Hi,

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

    Cheers
     
  15. Vuopaja

    Vuopaja

    Joined:
    Mar 21, 2020
    Posts:
    17
    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.
     
  16. JuanJSAR

    JuanJSAR

    Joined:
    Feb 21, 2014
    Posts:
    47
    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.
     
  17. Vuopaja

    Vuopaja

    Joined:
    Mar 21, 2020
    Posts:
    17
    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:

    Code (CSharp):
    1. void onInvoke(int taskID) {
    2.     // Handle the orientation
    3.     Debug.Log(Input.acceleration);
    4. }
    5.  
    6. // Start a task with a repeating delay
    7. Vuopaja.TaskInvoker.StartTask(1000, onInvoke);
    EDIT: Please note that by default the Input.acceleration is not updated while the app is in the background
     
    Last edited: May 28, 2021
  18. Utarastas

    Utarastas

    Joined:
    Jul 27, 2017
    Posts:
    11
    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.
     
  19. Vuopaja

    Vuopaja

    Joined:
    Mar 21, 2020
    Posts:
    17
  20. cdcv

    cdcv

    Joined:
    Jul 29, 2020
    Posts:
    1
    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
     
    Last edited: May 27, 2021
  21. Vuopaja

    Vuopaja

    Joined:
    Mar 21, 2020
    Posts:
    17
    Hey, thank you for the purchase. It seems that Unitys implementation of the Input.acceleration is indeed not updated while the app is in the background and I had not realized that before. I guess the only way around that is to write a native implementation as you suggested but I'm afraid I'm unable to take on more projects at this time. You could try to build on top of the included source code to access the sensors natively or if you feel like you want a refund please send me email at contact@vuopaja.com with your invoice number. I'm sorry for the inconvenience and I hope you are able to get it working.
     
  22. Utarastas

    Utarastas

    Joined:
    Jul 27, 2017
    Posts:
    11
    I used task invoker for wrapping Unity web requests, I found it extremely easy to use and adjust your code too. Documentation proved to be very useful.
     
  23. Veteran66

    Veteran66

    Joined:
    Jul 12, 2015
    Posts:
    50
    hi i just buy your Task Invoker.
    i am a Unity beginner
    how use your assets to run my android app in background?
     
  24. Vuopaja

    Vuopaja

    Joined:
    Mar 21, 2020
    Posts:
    17
  25. shai1983

    shai1983

    Joined:
    Jul 26, 2020
    Posts:
    1
    I purchased the plugin a while ago and it's working as expected. I just wonder if it is possible to run unity activity regularly for a short period of time (30 seconds) instead of specifying certain methods to run.
     
  26. Vuopaja

    Vuopaja

    Joined:
    Mar 21, 2020
    Posts:
    17
    Hey, thank you for the purchase! Running Unity activity periodically is unfortunately not supported. The way the plugin is built doesn't really work for periodic updates.
     
  27. irfan-shah

    irfan-shah

    Joined:
    Feb 21, 2018
    Posts:
    2
    hello @Vuopaja :
    need a quick answer of my question :
    my Game is connected to socket, and i received responses from socket and execute it on Unity side when the Game is Active .
    now my question is , as i decided to brought ur asset , so when i use your Asset .
    does it help me to execute Socket responses? when my App is in Background ?
    please let me .
     
  28. Vuopaja

    Vuopaja

    Joined:
    Mar 21, 2020
    Posts:
    17
    Hey, thank you for the purchase. I replied to your email about this too but in short you can start a task when going to background and try to check for responses inside the onInvoke method as shown in the documentation. There are some possible limitations as I wrote in the email.
     
  29. Steopushkin

    Steopushkin

    Joined:
    May 13, 2016
    Posts:
    4
    Any updates on it?
     
  30. Steopushkin

    Steopushkin

    Joined:
    May 13, 2016
    Posts:
    4
    @Vuopaja ?
     
  31. Vuopaja

    Vuopaja

    Joined:
    Mar 21, 2020
    Posts:
    17
    Hey, sorry but there has been no progress on this as I am preoccupied with other projects at this time.
     
  32. shefyg

    shefyg

    Joined:
    Oct 29, 2014
    Posts:
    4
    Hi,

    It seems that I we can't use async await on functions that were invoked by task invoker.
    Can you confirm, and tell us if there is a way to make it work?

    Thanks. Regards
    Shefy
     
  33. Vuopaja

    Vuopaja

    Joined:
    Mar 21, 2020
    Posts:
    17
    Hey, I replied to your email in more detail but in short Task Invoker will always schedule the task on the Unity main thread and so using other threads would require changes in the native code. Also async methods on the main thread like coroutines are not updated because the Unity PlayerLoop is not updating when the app is in the background.
     
  34. tomkail_betterup

    tomkail_betterup

    Joined:
    Nov 17, 2021
    Posts:
    106
    Hey! We have an app that allows users to record videos and uses the AWS SDK to upload them to an S3 bucket. However, the upload pauses when the user backgrounds the app. We'd like the upload to continue - is this possible using your plugin? I'm guessing you can't move execution from the main thread to another when Unity becomes backgrounded, so would we need to perform all upload tasks in a second thread?
     
  35. Vuopaja

    Vuopaja

    Joined:
    Mar 21, 2020
    Posts:
    17
    Hey! I took a quick look at the AWS SDK docs and it seems it's not running the upload on the main thread. This means my plugin won't work with this SDK as the plugin always runs on the main thread.
     
  36. tomkail_betterup

    tomkail_betterup

    Joined:
    Nov 17, 2021
    Posts:
    106
    Ah! Thanks very much for looking into it! Is it something you believe would be possible? I had thought that other threads don't pause by default, so perhaps it'll just work if we enable background tasks in XCode?
    Have DM'd you in case you'd be interested in helping us on a contractor basis!
     
  37. Blacklister001

    Blacklister001

    Joined:
    Jun 13, 2016
    Posts:
    11
    Hey @Vuopaja ! So I am developing a multiplayer game using photon pun 2. I don't face any issue on android but on iPhone I am unable to keep the connection alive on a separate thread. Will your asset help me out in this regard?
    Thanks in advance.
     
  38. Vuopaja

    Vuopaja

    Joined:
    Mar 21, 2020
    Posts:
    17
    Hey! Unfortunately this asset is not suitable for that use case.
     
  39. Ehtis

    Ehtis

    Joined:
    Nov 2, 2020
    Posts:
    3
    Hey I have just purchased the asset and built and ran the sample scene on my ios device. The background tasks are not running when the app is in background. Any reason why?