Android: Running a Background Task Using Alarmmanager

android: running a background task using AlarmManager

Here is one complete example: http://android-in-practice.googlecode.com/svn/trunk/ch02/DealDroidWithService/

The pattern this example uses, and one that I've found that seems to work well, is to use a boot receiver to setup the AlarmManager (and of course also check to start the polling from your main Activity too, for the case when your app is installed and the system is not booted) and have the AlarmManager send an Intent for another receiver: http://android-in-practice.googlecode.com/svn/trunk/ch02/DealDroidWithService/src/com/manning/aip/dealdroid/DealBootReceiver.java

And then from the AlarmReceiver start an IntentService:
http://android-in-practice.googlecode.com/svn/trunk/ch02/DealDroidWithService/src/com/manning/aip/dealdroid/DealAlarmReceiver.java

From your IntentService then make your network call to poll for data, or whatever you need to do. IntentService automatically puts your work in a background thread, it's very handy:
http://android-in-practice.googlecode.com/svn/trunk/ch02/DealDroidWithService/src/com/manning/aip/dealdroid/DealService.java

Check the docs for these classes too, a lot of into in there.

The caveat with this example is that it does not deal with the wake lock gap (the excellent CommonsWare code does that if you need it), but it may give you some more ideas about how to potentially address the "poll using AlarmManager and Service" stuff.

UPDATE: the code is now here: https://github.com/charlieCollins/android-in-practice

Android background process loading data from webpage every minute

Easy with WorkManager, it's the most encouraged way for Scheduling Repeating background work in Android, see introduction.

As you say, the minimum repeating work request interval is restricted to 15 minutes, the only way to break it is to Repeatedly schedule the one-time work.

1. Setup Your Worker Class:

class ToastShower(context: Context, params: WorkerParameters) : CoroutineWorker(context, params) {
override suspend fun doWork(): Result {
withContext(Dispatchers.Main) { //ui related work must run in Main thread!!
Toast.makeText(applicationContext, "Hey, I'm Sam! This message will appear every 5 seconds.", Toast.LENGTH_SHORT).show()
}

return Result.success()
}
}

2. Setup Your Custom Application Class:

class WorkManagerApplication : Application() {
private val backgroundScope = CoroutineScope(Dispatchers.Default) //standard background thread
private val applicationContext = this

override fun onCreate() { //called when the app launches (same as Activity)
super.onCreate()

initWork()
}

private fun initWork() {
backgroundScope.launch { //all rnu in background thread
setupToastShowingWork(0) //no delay at first time

observeToastShowingWork() //observe work state changes, see below
}
}

private fun setupToastShowingWork(delayInSeconds: Long) { //must run in background thread
val constraints = Constraints.Builder()
.setRequiredNetworkType(NetworkType.UNMETERED) //when using WiFi
.build()

val oneTimeRequest = OneTimeWorkRequestBuilder<ToastShower>() //【for breaking 15 minutes limit we have to use one time request】
.setInitialDelay(delayInSeconds, TimeUnit.SECONDS) //customizable delay (interval) time
.setConstraints(constraints)
.build()

WorkManager.getInstance(applicationContext).enqueueUniqueWork( //【must be unique!!】
ToastShower::class.java.simpleName, //work name, use class name for convenient
ExistingWorkPolicy.KEEP, //if new work comes in with same name, discard the new one
oneTimeRequest
)
}

private suspend fun observeToastShowingWork() {
withContext(Dispatchers.Main) { //must run in Main thread for using observeForever
WorkManager.getInstance(applicationContext).getWorkInfosForUniqueWorkLiveData(ToastShower::class.java.simpleName).observeForever {
if (it[0].state == WorkInfo.State.SUCCEEDED) { //when the work is done
backgroundScope.launch { //prevent from running in Main thread
setupToastShowingWork(5) //every 5 seconds
}
}
}
}
}
}

3. Setup AndroidManifest File:

<manifest 
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.workmanagertest">

<application
android:name=".WorkManagerApplication" //【here, must!!!】

...

</application>

</manifest>

By setting up with above, the work (showing Toast in my example) will be executed (or more clearly, schedule and execute) every 5 seconds no matter the app is in foreground or background or killed by system. Only way to stop it is either uninstall or go inside the app's setting to force-close it.

Demo: https://youtu.be/7IsQQppKqFs

Android design : background long running service or AlarmManager?

while in case 2 register a Receiver for the alarm event and set the alarm manager up

Your receiver will already be registered via the manifest.

which would be the preferred approach ?

AlarmManager, assuming REGULAR_INTERVAL is typically decently long (e.g., over a few minutes). Ideally, that interval is user-configurable.

If you intend to do this even when the device is otherwise asleep, your option #1 simply will not work, unless you keep a WakeLock on all the time, which will cause your users to want to shoot you in the face with a shotgun.

Some skeleton code for this approach would be welcome.

Here is a sample app demonstrating the use of AlarmManager for non-_WAKEUP alarms (i.e., you only need these events to occur while the device is already awake for other reasons).

Here is a sample app demonstrating the use of AlarmManager for _WAKEUP alarms, using my WakefulIntentService. WakefulIntentService (or something like it) is necessary because AlarmManager does not keep the device awake very long (just long enough for onReceive() of a BroadcastReceiver), and so you need to take additional steps to keep the device awake long enough for you to do your work. Theoretically, your work might be quick enough to do just in onReceive() of a BroadcastReceiver, avoiding the need to mess with the WakefulIntentService. However, you will be doing disk I/O each of these times, which ideally should not be done on the main application thread, where onReceive() is called. And, when you go to upload your data, you may well need a WakefulIntentService then, anyway, if you are looking to do that in the background as well.

Alarm Manager or Work Manager for Recurring Background Work

For recurring background work, AlarmManger isn't suitable. As the name implies, it's intended to notify the system of an event at a precise time. Just like a physical alarm that wakes a person up even if the person sleeps, AlarmManager will wake up the device from doze mode which will result in more power usage. it is suitable for suitations like setting remainders such as for calender events which the users probably set by themselves.

On the other hand, WorkManager is intended to carry out background processing or work that would persist. Workmanager is much more efficient for recurring task especially as it allows you set constraints to determine when it should start or stop the background work.

check the link form the offical documentation on WorkManger:
workmanager architecture
tabular comparison between the two



Related Topics



Leave a reply



Submit