Search code examples
androidservicebroadcastreceiver

AlarmManager only lets one Service through when used with setRepeating in Android


I've been struggling with this for a couple of days. What I want to do is run a service periodically, about 2-3 minutes apart. I have an Activity that is responsible for the interface and setting up the first alarm.

The alarm is configured by a BroadcastReceiver which looks like this:

public class Receiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
          String message = "Alarm worked";
          Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
          setAlarm(context);
    }

    public void setAlarm(Context context){
        AlarmManager am = (AlarmManager) context.
                              getSystemService(Context.ALARM_SERVICE);
        Intent intent = new Intent(context, Receiver.class);
        PendingIntent pi = PendingIntent.getBroadcast(context, 
                              0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
        Intent dailyUpdater = new Intent(context, DiscoveryService.class);
        context.startService(dailyUpdater);
        am.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() 
                              + (1000 * 30) , pi);
    }
}

I've tried using setRepeating for AlarmManager, but it still has the same effect. What happens is that the AlarmManager works how it should, it fires an Intent which the receiver gets and executes onReceive periodically, as it should. However, it executes the service only the first time. After the first time, the alarms still go off, but the service is not executed.

I read some threads from people with similar problems, and one of them mentioned that PendingIntent lasts for only one send. Thus, I opted out to setting the alarm every time so I can set pendingIntent flag for updating every time.

I tried making my service an intentService, which is fine, but then my bluetooth scanner inside the service does not work because intentService thread terminates without waiting for my bluetooth discovery to finish.

Anyone have any idea what can help me?

Here is part of my service:

public class DiscoveryService extends Service {
    public void onCreate() {
        super.onCreate();
        Toast.makeText(this, "MyAlarmService.onCreate()", 
                                 Toast.LENGTH_LONG).show();
        findEverything();
    }
}

EDIT: This is the code that I currently have.

public void onReceive(Context context, Intent intent) {
      String message = "Alarm worked";
      Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
      Intent dailyUpdater = new Intent(context, DiscoveryService.class);
      context.startService(dailyUpdater);
}

public void setAlarm(Context context){
    // get a Calendar object with current time
    AlarmManager am=(AlarmManager)context. 
                             getSystemService(Context.ALARM_SERVICE);
    Intent intent = new Intent(context, Receiver.class);
    PendingIntent pi = PendingIntent.getBroadcast(context, 0, intent,
                             PendingIntent.FLAG_UPDATE_CURRENT);
    am.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 
                             (1000 * 30) , pi);
}

Solution

  • What happens is that the AlarmManager works how it should, it fires an Intent which the reciever gets and executes onReceive periodically, as it should. However, it executes the service only the first time. After the first time, the alarms still go off, but the service is not executed.

    You are calling startService() once when you are scheduling the alarm. You are not calling startService() at all from your BroadcastReceiver. Yet you are scheduling the alarm via the BroadcastReceiver. Hence, when the alarm goes off, the service will not be sent a command, because you are not sending it a command.

    I read some threads from people with similar problems, and one of them mentioned that PendingIntent lasts for only one send.

    That is only if you use FLAG_ONE_SHOT.

    Anyone have any idea what can help me?

    Call startService() from your onReceive() method, instead of from your setAlarm() method. Also, add in all the WakeLock management logic, since you are using a _WAKEUP alarm and you are not able to use my WakefulIntentService.