1

I've tested various backgrounding options (xamarin samples, xamarin blog articles, various sources) but I'd like some clarification on the pro/cons of each one, and if some are deprecated/obsolete.

My case is an app (wifi, on client premises) that should periodically poll a server for new data, or push collected data to the server as soon as it has connection (it should continue to collect data if no connection is available, but push to the server as soon as it has connection).

I want this sync to be in the background for the user, who in the meantime can continue to work. I would like the push (if data is present) to be done each 1 or 2 minutes, so I can just create a task in the background job with an infinite while that checks every 1/2 minutes.

I made some basic samples to test:

1) using a LongRunningTaskService : Service

2) using Firebase.JobDispatcher

3) using WorkManager (but scheduled jobs can't be less than 15 minutes)

4) looking at Shiny, but currently having trouble integrating with Prism (but I guess I'll make it work)(but don't understand if it is a wrapper of what exactly?)

Which solution do you think is appropriate for my use case? With all the 4 solutions, data should be pushed when the app is in foreground or background (right?)

In case I need to push data only when the app is in the foreground, would it be wrong to start my Task in App class?

UPDATE

Tried this in the OnInitialized() of the App.cs:

Task.Factory.StartNew(async () =>
            {
                while (true)
                {                    
                    await BackgroundTasks.TestPushDataRepeat();
                    await Task.Delay(60000);
                }
            }
            , TaskCreationOptions.LongRunning);

It works every minute when the app is in foreground (and doesn't block the UI), but unexpectedly works also when the app is backgrounded (that is a not needed plus, for my case). Not being a service, I thought it should have freezed, why is that?

I'm trying to better understand/separate how the TPL works with Xamarin on Android, and how Android backgrounding (services/workers etc) works, to see if this solution has drawbacks.

Mattia Durli
  • 757
  • 7
  • 19
  • In Xamarin, normally, we use service to receive and push data. You could use the 1) basic sample – Wendy Zang - MSFT Apr 23 '20 at 07:20
  • thanks @WendyZang-MSFT , I understood that JobDispatcher is the successor of the Service (more or less), and that WorkManager is the successor of JobDispatcher. Is it wrong? how do they compare then? what's the use case for each of them? – Mattia Durli Apr 23 '20 at 08:19
  • WorkManager is a new job management system in Jetpack, incorporates the features of Firebase Job Dispatcher (FJD) and Android’s JobScheduler. For the comparation, you could hceck the link below. https://stackoverflow.com/questions/50279364/android-workmanager-vs-jobscheduler – Wendy Zang - MSFT Apr 29 '20 at 08:05

1 Answers1

3

On Android, you cannot run a background task/job/worker every 30 seconds. Such behavior can have a negative impact on the battery and can only be achieved with a Foreground Service that requires a notification visible to the user.

The limit you see for WorkManager about the 15 minutes minimum interval is an OS constraint, not a library constraint. You have the same limit if you use JobScheduler. Also a Worker (or Job if you're using JobScheduler) can run only for 10 minutes.

So, you need to have a Foreground Service. You can still use WorkManager and its advanced features in this case, but you need to use WorkManager 2.3+ and "promote" your worker to a Foreground Service. WorkManager's documentation covers this use case.

This for native Android (Java/Kotlin). I don't know how the latest Xamarin binding cover this use case.

pfmaggi
  • 6,116
  • 22
  • 43
  • Thanks for the clarification (expecially the 10 minutes limit),and I understand that the contraint is in the OS. Since my priority is to to do the push every 1 or 2 minutes when the app is in the foreground, but transparently to the user (so in a background task of a foreground app), what are the cons of using a TaskFactory.StartNew with a loop and a delay of 1 minute between each push attempt? It shouldn't block the UI during the push, and it should stop when the app gets backgrounded (I still have to test it, but I wonder if is acceptable as a backgrounding solution for a foreground app). – Mattia Durli Apr 25 '20 at 22:09
  • Personally I'll look into using a foreground service. It is the safest and most future-proof way to handle something that needs to be running for prolonged time in the "background". Re-spinning a new task every 1-2 minutes may have a worse impact on the battery, but it is something you need to test. – pfmaggi Apr 26 '20 at 09:13
  • I tested the foreground service, and it works. But I have also tested with the code in my updated question, and it works too (even when app is backgrounded and I don't understand why). The TPL solution seems simpler, so I'm trying to understand if it has some drawbacks I'm unaware of. – Mattia Durli Apr 27 '20 at 11:44
  • Try to stress test the memory of the emulator and see if it makes any difference when Android try to find memory. Also, which Android version are you testing this on? – pfmaggi Apr 27 '20 at 15:18
  • I'm testing on the device (a Zebra TC25 with Android 8.1), how do I simulate an Android memory request? Also, it baffles me that when backgrounded my task continues to fire every 60 seconds. I know for sure by logcat logging and by the fact that it actually pushes my fake data to the server, when in background. I always understood that when backgrounded an app freezes, and only services/job/workers can continue in the background, not a mono/xamarin managed TPL task. – Mattia Durli Apr 27 '20 at 21:13
  • Android devices have different behavior if they are charging or not, if the user s actively using the device or not: https://developer.android.com/training/monitoring-device-state/doze-standby For testing low memory condition, you can start enabling the developer option: "don't keep activity". Also try to run some heavy application while your app is in the background: https://stackoverflow.com/questions/15588625/how-can-i-force-memory-pressure-for-android-debugging – pfmaggi Apr 30 '20 at 18:40
  • Ok, I tried to test the Task.Factory.StartNew with the real device, not in charge, with app backgrounded. The loop in the task continues to be executed every 60s, and makes a http req to my server app. If I activate the "don't keep activity" it stops, but it is understandable. It also stops under pressure, but it is ok because the app gets killed. What I don't get is why when simply backgrounded, instead of freezing, this Task.Factory that is a mono managed thread, continues to run. So my assumption that the app when backgrounded freezes (only services, jobs etc continue) is wrong. Is it? – Mattia Durli May 06 '20 at 15:31