简体   繁体   中英

Background processing in modern Android

I have implemented some background task with WorkManager and with usage this Guide . One time I needed to use CoroutineWorker . I find these guide pretty good but every time I need new requirement for background processing I start new research for what I need. So my question is what is the correct way to address the following use cases with modern Android. Also please consider that different phone brands kill background task defiantly (Some brands more harsh on background processing). And when do I need to use persistent notification and when it is not required, and when to use AlarmManger . Please write for each the best way to implement and if Persistent notification required.

Use cases:

1. Downloading large file (500mb)

a. Once a day on exact time

b Once a day when the OS can, in any time

2. Downloading small file (5k)

a. Once a day on exact time

b Once a day when the OS can, in any time

3. Setting alarm at exact time

4. Sync DB with server (large data about 5min runtime)

a. Every 15 min ( Minimal time ?)

b. Once a Day

5. Sync DB with server (small data less than 1sec runtime)

a. Every 5 min

b. Every 15 min

c. Once a Day

Please check the answer I gave here for more information:

Android recommended and reliable API for periodic background work?

1. Downloading a large file (500mb)

a. Once a day on exact time - you can set an alarm here to be exact, but then you hit the Android 12 limitation for starting services from the Background(more on this in the other comment). So it depends on the use case. I just would not go there.

b Once a day when the OS can, in any time - go with the WorkManager, but in theory it depends on the Power Buckets so if you go in the lower ones you might go a little above a day. Also, it is different to start and to finish. You might start hitting the 10min per day limitation. (more on this in the other comment)

2. Downloading small file (5k) a. Once a day on exact time - as a large file.

b Once a day when the OS can, in any time - as a large file.

3. Setting alarm at exact time - it depends on what you do. I don't understand this

4. Sync DB with server (large data about 5min runtime) - you need WorkManager for stuff like this.

For all the above - the 15min comes from Doze mode. But even it comes in "2 flavors". This 15min is just on theory. In reality it might be even more. WorkManager has the concept of a "periodic work". In reality there is no such a thing. WorkManager uses the concept of constraints. So you have the constraint that you need a Network, you are constrained that you need a device to be charging and you have a "time constrain". So you see - a "periodic work" of 24 hours is just a work with an extra constrain: "do not start in less than 24 hours". But it doesn't mean "every 24 hours". In theory 24 might have passed, the timing constrain is satisfied and then for other reason you are executed successfully in 1 week and the work is rescheduled again with another 24 hours time constrain.

For stuff like "every 5min, 15min, 15min" - just raise a Service with the following text in the Service notification: "Our application hates your battery", never stop it, and do whatever you need :) But is totally against the new Android concept.

Even if you use push notifications if they are not a high priority you will effectively fall back to WorkManager to do the work later.

Even like I said: "once a day" means "most likely once a day"

a. Every 15 min (Minimal time?)

b. Once a Day

5. Sync DB with server (small data less than 1sec runtime)

a. Every 5 min

b. Every 15 min

c. Once a Day

According to this reference of WorkManager, there are three types of persistent work you can schedule through it,

  • Immediate : Tasks that must begin immediately and complete soon. May be expedited.
  • Long Running : Tasks which might run for longer, potentially longer than 10 minutes.
  • Deferrable : Scheduled tasks that start at a later time and can run periodically.

This means most of your use cases are achievable by using WorkManager except two cases where you require it to run "Every 5 min" & "Setting alarm at exact time".

It is recommended from here that if you want to set alarm at exact time then WorkManager shouldn't be used, instead use AlarmManager which will wake device even from doze mode at specified time.


Checkout all possible executions that work manager provides: WorkManager 流程 (Courtesy of WorkManager guide )

Hence, following are all possible approach you can use according to your use-cases:

  1. Downloading large file (500mb)

    a. Once a day on exact time

    Answer: You can use PeriodicWork here scheduled for every 24 hours from given start time, since it's long running operation you can make it expedited/foreground to track ongoing progress. Although bear in mind that downloading requires active internet connection and at specified interval if it's not available then it will be scheduled for delayed/later execution.

     PeriodicWorkRequestBuilder<LongRunningWorker>(1, TimeUnit.DAYS) .setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST) // Additional configuration .build() //Calling setForeground() from doWork() will show ongoing notification

    b. Once a day when the OS can, in any time

    Answer: This is the best example where you can execute some task indeterminately using PeriodicWork. Here you can make it deferrable since it's not required to be executed at specific time.

     PeriodicWorkRequestBuilder<LongRunningWorker>(1, TimeUnit.DAYS) // Additional configuration .build() //Calling setForeground() from doWork() will show ongoing notification
  2. Downloading small file (5k)

    a. Once a day on exact time

    Answer: It can be PeriodicWork with immediate execution (expedited work) scheduled for 24 hours, since it won't take long to download small file.

     PeriodicWorkRequestBuilder<ShortSpanWorker>(1, TimeUnit.DAYS) .setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST) // Additional configuration .build()

    b. Once a day when the OS can, in any time

    Answer: It can be PeriodicWork with deferrable execution that can be scheduled at 24 hours.

     PeriodicWorkRequestBuilder<ShortSpanWorker>(1, TimeUnit.DAYS) // Additional configuration .build()
  3. Setting alarm at exact time

    Answer: For setting alarm to be executed on exact time, you should use AlarmManager. This usecase is not possible with WorkManager because, it doesn't interrupt Doze mode (Device's deep sleep).

  4. Sync DB with server (large data about 5min runtime)

    a. Every 15 min (Minimal time?)

    Answer: This can be PeriodicWork scheduled every 15 mins being foreground work since it is long running.

     PeriodicWorkRequestBuilder<SyncToServerWorker>(15, TimeUnit.MINUTES) // Additional configuration .build() //Calling setForeground() from doWork() will show ongoing notification

    b. Once a Day

    Answer: This can be PeriodicWork scheduled every 24 hours being foreground work since it is long running.

     PeriodicWorkRequestBuilder<SyncToServerWorker>(1, TimeUnit.DAYS) // Additional configuration .build() //Calling setForeground() from doWork() will show ongoing notification
  5. Sync DB with server (small data less than 1sec runtime)

    a. Every 5 min

    Answer: This use-case is not achievable since minimum time-frame for WorkManager's periodic work is 15 mins. Hence, it is suggested to manage this periodic work manually by foreground service/alarm manager combination.

    b. Every 15 min

    Answer: This is achievable by PeriodicWork scheduled for every 15 mins which can either expedited or deferrable based on how urgent/relaxed it is required.

     PeriodicWorkRequestBuilder<SyncDataWorker>(15, TimeUnit.MINUTES) .setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST) // Decide whether to make it expedited or deferrable here conditionally // Additional configuration .build()

    c. Once a Day

    Answer: This is example of PeriodicWork scheduled for every 24 hours which can either expedited or deferrable based on how urgent/relaxed it is required.

     PeriodicWorkRequestBuilder<SyncDataWorker>(1, TimeUnit.DAYS) .setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST) // Decide whether to make it expedited or deferrable here conditionally // Additional configuration .build()

Reference for creating long running workers: https://developer.android.com/topic/libraries/architecture/workmanager/advanced/long-running#long-running

Hope this helps!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM