The recommended pattern for Android's equivalent to cron
jobs and Windows scheduled tasks is to use AlarmManager
.
This works well when coupled with an IntentService
, as the
service will do its work on a background thread and shut down
when there is no more work to do.
There's one small problem: IntentService
does nothing to keep
the device awake. If the alarm was a WAKEUP
variant, the phone
will only stay awake on its own while the BroadcastReceiver
handling the alarm is in its onReceive()
method. Otherwise,
the phone may fall back asleep.
WakefulIntentService
attempts to combat this by combining
the ease of IntentService
with a partial WakeLock
.
This is available as a JAR file from the downloads area of this GitHub repo. The project itself is set up as an Android library project, in case you wish to use the source code in that fashion.
NOTE: WakefulIntentService
v0.4.0 and newer requires Android 2.0+, so it
can take advantage of onStartCommand()
for better handling of
crashed services. Use earlier versions of WakefulIntentService
if
you wish to try to use it on older versions of Android, though this
is not supported.
Any component that wants to send work to a
WakefulIntentService
subclass needs to call either:
WakefulIntentService.sendWakefulWork(context, MyService.class);
(where MyService.class
is the WakefulIntentService
subclass)
or:
WakefulIntentService.sendWakefulWork(context, intentOfWork);
(where intentOfWork
is an Intent
that will be used to call
startService()
on your WakefulIntentService
subclass)
Implementations of WakefulIntentService
must override
doWakefulWork()
instead of onHandleIntent()
. doWakefulWork()
will be processed within the bounds of a WakeLock
. Otherwise,
the semantics of doWakefulWork()
are identical to onHandleIntent()
.
doWakefulWork()
will be passed the Intent
supplied to
sendWakefulWork()
(or an Intent
created by the sendWakefulWork()
method, depending on which flavor of that method you use).
And that's it. WakefulIntentService
handles the rest.
NOTE: this only works with local services. You have no means
of accessing the static WakeLock
of a remote service.
NOTE #2: Your application must hold the WAKE_LOCK
permission.
NOTE #3: If you get an "WakeLock
under-locked" exception, make sure
that you are not starting your service by some means other than
sendWakefulWork()
.
If you want to slightly simplify your use of WakefulIntentService
in conjunction with AlarmManager
, you can do the following:
-
Implement your
WakefulIntentService
anddoWakefulWork()
as described above. -
Create a class implementing the
WakefulIntentService.AlarmListener
interface. This class needs to have a no-argument public constructor in addition to the interface method implementations. One method isscheduleAlarms()
, where you are passed in anAlarmManager
, aPendingIntent
, and aContext
, and your mission is to schedule your alarms using the suppliedPendingIntent
. You also implementsendWakefulWork()
, which is passed aContext
, and is where you callsendWakefulWork()
upon yourWakefulIntentService
implementation. -
Create an XML metadata file where you identify the class that implements
WakefulIntentService.AlarmListener
from the previous step, akin to:
-
Register
com.commonsware.cwac.wakeful.AlarmReceiver
as a<receiver>
in your manifest, set to respond toACTION_BOOT_COMPLETED
broadcasts, and with acom.commonsware.cwac.wakeful
<meta-data>
element pointing to the XML resource from the previous step, akin to: -
When you wish to manually set up the alarms (e.g., on first run of your app), create an instance of your
AlarmListener
and callscheduleAlarms()
on theWakefulIntentService
class, passing in theAlarmListener
and aContext
(e.g., the activity that is trying to set up the alarms).
Over time, this portion of the framework will be expanded further to help consolidate a good usage pattern for managing alarms.
None.
This is version v0.5.0 of this module, meaning it is proving to be surprisingly popular.
In the demo/
project directory and com.commonsware.cwac.wakeful.demo
package you will find
an AppListener
, which is an implementation of AlarmListener
,
and AppService
, which
extends WakefulIntentService
. AppService
pretends to do some work in a background
thread. All of this is set up via a DemoActivity
(required
to move the application out of the "stopped" state on Android 3.1+),
and if needed on a reboot.
Note that when you build the JAR via ant jar
, the sample
activity is not included, nor any resources -- only the
compiled classes for the actual library are put into the JAR.
The code in this project is licensed under the Apache Software License 2.0, per the terms of the included LICENSE file.
If you have questions regarding the use of this code, please post a question
on StackOverflow tagged with commonsware
and android
. Be sure to indicate
what CWAC module you are having issues with, and be sure to include source code
and stack traces if you are encountering crashes.
- v0.5.0: added the
AlarmListener
portion of the framework - v0.4.5: completed switch to
Application
as theContext
for theWakeLock
- v0.4.4: switched to
Application
as theContext
for theWakeLock
- v0.4.3: added better recovery from an
Intent
redelivery condition - v0.4.2: added
volatile
keyword to staticWakeLock
for better double-checked locking implementation - v0.4.1: added
setIntentRedelivery()
call, nuked extraneous permissions check - v0.4.0: switched to
onStartCommand()
, requiring Android 2.0+ (API level 5 or higher) - v0.3.0: converted to Android library project, added test for
WAKE_LOCK
permission