Services with Alarms

Overview (Video for part 1) (Source code for part 1)

·         A service is required for an alarm to be processed when the system is sleeping.

·         The idea is as follows

o   The activity starts the service. A button triggers the service to set the alarm

o   The alarm calls the OneShotAlarmReceiver,

o   which calls a BroadcastReceiver that is part of the service

o   Since the service is always able to receive broadcasts, it will be triggered even if the system is sleeping

·       One complication is that we need to make sure that the system stays awake long enough to call the service.

Merge FunWithLocalServices and FunWithAlarms1

·         Start with a service developed in the FunWithLocalServices tutorial

·         Open the FunWithAlarms1 files for reference

·         Merge FunWithLocalServices and FunWithAlarms1

o   Make new class OneShotAlarmReceiver

§  Same as in FunWithAlarms1

§  onReceive with (note new name of action is changed to com.FunWithServices.MyService.TIMESUP

·         Log.d("OneShotAlarmReceiver","Alarm Expired");

·         Intent broadcast=new Intent("com.FunWithServices.MyService.TIMESUP");

·         context.sendBroadcast(broadcast);

·          

o   In manifest,

§  add entry for receiver OneShotAlarmReceiver

o   In MyService, add broadcast receiver

§  From FunWithAlarms1, copy public BroadcastReceiver receiver=new BroadcastReceiver() {…  

o   In MyService, add function to set the alarm and register the BroadcastReceiver

§  public void startAlarm()

§  {

§              registerReceiver(receiver, new IntentFilter("com.FunWithServices.MyService.TIMESUP"));

§              Intent intent = new Intent(this, OneShotAlarmReceiver.class);

§              PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_ONE_SHOT);

§              AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);

§              alarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + (5 * 1000), pendingIntent);

§              Log.d("MyService","Alarm is set");

§  }

o   In MyService.onDestroy(), add

§  unregisterReceiver(receiver);

o   In FunWithLocalServices, call startAlarm from button onClickListener

§  Add myService.startAlarm();

·         Run

 

 

Problem with sleeping (Video for part 2) (Source code for part 2)

·         When an activity or service is running, the system might sleep at any time

·         In order to keep the system awake, WakeLocks are used

·         So, when the alarm goes off and the service’s broadcast receiver is triggered, it should set a WakeLock.

·         The alarm’s BroadcastReceiver does not need a WakeLock, the AlarmManager keeps a WakeLock so the system does not sleep before the BroadcastReceiver.onReceive is complete

·         However, the system is allowed to sleep as soon as the alarms BroadcastReceiver is finished.

·         It might go to sleep before the service is able set its WakeLock

·         We need to call a WakeLock from the alarm’s BroadcastReceiver.onReceive, but then release it from the services BroadcastReceiver.

·         One way to solve this is to make a class with static member variables and functions.

MyStaticWakeLock class

·         Make new class call MyStaticWakeLock

o   public class MyStaticWakeLock {

o               private static PowerManager.WakeLock wl = null;

o               public static void lockOn(Context context) {

o                           PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);

o                           if (wl== null)               

o                                       wl = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK, "MyStaticWakeLock");

o                           wl.acquire();                                       

o               }

o               public static void lockOff(Context context) {

o                           PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);

o                           if (wl != null)              

o                                       wl.release();                           

o               }

o   }

·         Note, this class has two functions, one for setting the WakeLock and one for releasing

·         In OneShotAlarmReceiver.onReceive, add

o   MyStaticWakeLock.lockOn();

·         At the end of MyService.receiver.onReceive(), add

o   MyStaticWakeLock.lockOff();

·         Run