Fun with alarms Part 1: Alarms without services
Overview
(Video) (Source code for first part)
· Android allows you to set alarms
· When the alarm goes off, the OS sends your application an intent.
· However, receiving these intents is a bit tricky.
· Consequently, this approach is probably not sufficient for most applications.
· We’ll need to use services, which is Part 2
· Note that Handler is also used to make things happen in the future. Thus, one should consider using it instead of AlarmManager.
o Note: The Alarm Manager is intended for cases where you want to have your application code run at a specific time, even if your application is not currently running. For normal timing operations (ticks, timeouts, etc) it is easier and much more efficient to use Handler.
Starting
· Start with a new Android project
o called FunWithAlarms
o with a button and button listener, and
o TextView, called textView
· Make a new class, we’ll call OneShotAlarmReceiver, derived from android.content.BroadcastReceiver
o Note, it must be a new class. It cannot be a local class of FunWithAlarms.
o As we will see, some BroadcastReceivers can be local classes.
· In OneShotAlarmReceiver, add function onReceive(Context context, Intent intent)
· In this function, add Log.d("OneShotAlarmReceiver ","Alarm Expired");
· In the manifest, with the application section (as far as I know, everything must be in the application section), add
o <receiver android:name=". OneShotAlarmReceiver "> </receiver>
o Note, this is the name we gave our broadcast receiver
Setting the
alarm
· In FunWithAlarms, within the button onClick listener add
o Intent intent = new Intent(context, OneShotAlarmReceiver.class); // again, our broadcast receiver
o PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_ONE_SHOT); // other flags make other types of alarms, like periodic alarms
o AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
o alarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + (5 * 1000), pendingIntent); // (5*1000) so the alarm will expire in 5 seconds
o Log.d(“FunWithAlarms1”,”Alarm is set”);
Run program
· Press button
· Note that all log shows things worked as expected
Problems
(Video) (Source code for second part)
· How to run the main activity?
· We can’t directly access the FunWithAlarms object.
· Instead we’ll use another intent to trigger a BroadcastReceiver that is part of FunWithAlarms
o Why not make OneShotAlarmReceiver part of FunWithAlarms?
o Maybe one can, but I couldn’t get it to work.
Add BroadcastReceiver
to FunWithAlarms
· In FunWithAlarms, add local class
o
public BroadcastReceiver receiver=new
BroadcastReceiver() {
o
public
void onReceive(Context context, Intent intent) {
o
Log.d("FunWithAlarms
","Received TimesUp message");
o
}
o };
· Register this BroadcastReceiver
o In FunWithAlarms.onCreate add
§ registerReceiver(receiver, new IntentFilter("com. FunWithAlarms.TIMESUP ")); // note that this name com. FunWithAlarms.TIMESUP must be the same as the name above (It is better to use a single string constant.).
· We must also unregister this broadcast receiver in onPause
o In FunWithAlarms, add
§
public void onPause () {
§ super.onPause();
§
Log.d(“FunWithAlarms1”,”onPause”);
§
unregisterReceiver(receiver);
§ }
· And reregister in onResume
o In FunWithAlarms, add
§ public void onPause () {
§ super.onPause();
§ Log.d(“FunWithAlarms1”,”onResume”);
§ registerReceiver(receiver, new IntentFilter("com. FunWithAlarms.TIMESUP ")); // that same constant again!
§ }
· Call this BroadcastReceiver from OneShotAlarmReceiver
o In OneShotAlarmReceiver.onReceive add
§ Intent broadcast=new Intent("com.FunWithAlarms.TIMESUP "); // the same name again, we really should use a constant!
§ context.sendBroadcast(broadcast);
· Note: now we have two BroadcastReceivers. One is registered in the manifest and one is registered in the code.
Run program
· The log shows that things run as expected
· Now test what happens if the phone sleeps before the alarm goes off. The alarm expires so that first BroadcastReceiver is called.
· But the activity is not running, so it is not called.
· In some cases, this behavior might be fine.
· However, if you want to catch this event, you must use a service