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
How to Use Device Default Theme for App
Android Tabwidget Detect Click on Current Tab
How to Change Color of Listview Items on Focus and on Click
Enable and Disable Auto Rotate Programmatically
If I Call Getmeasuredwidth() or Getwidth() for Layout in Onresume They Return 0
Launch Android Application from a Browser Link
Multiple Count Down Timers in Recyclerview Flickering When Scrolled
Android 11 Action_Open_Document_Tree: Set Initial Uri to the Documents Folder
Custom Layout for Spinner Item
How to Record Video from Background of Application:Android
How to Get All Child's Data in Firebase Database
Detect If an App Is Installed from Play Store
Android Emulator Won't Run Application Started from Eclipse
Anr Keydispatchingtimedout Error
How to Add External Jar Libraries to an Android Project from the Command Line
How to Implement Image Gallery in Gridview in Android