Search code examples
androidservicebroadcastreceiveralarmmanagerintentservice

BroadcastReceiver from AlarmManager not getting called


I have a class that extends IntentService. The stuff in this class is called when my app reboots (and also on app startup). It loads some settings and does some stuff in the background (it's a productivity tool/utility).

This IntentService, when loading my, let's call it "stuff", decides whether or not to add some alarms via AlarmManager. I have a BroadcastReceiver that receives some different parameters and does some method based on those parameters. Here is the code in which I am scheduling the alarms:

public void addAlarm(int id, int hourFrom, int hourTo, int minuteFrom, int minuteTo)
{
    AlarmManager alarmManager = (AlarmManager) getBaseContext().getSystemService(Context.ALARM_SERVICE);
    // Enable
    Intent intent = new Intent(Controller.KEY_CONTROLLER_ACTION);
    intent.putExtra(Controller.KEY_CONTROLLER_ACTION, Controller.KEY_ACTION_ENABLE);
    intent.putExtra(Controller.KEY_CONTROLLER_ID, id);
    PendingIntent pendingIntent = PendingIntent.getBroadcast(
            this,
            id,
            intent,
            PendingIntent.FLAG_UPDATE_CURRENT);
    Calendar calendar = Calendar.getInstance();
    calendar.set(Calendar.HOUR_OF_DAY, hourFrom);
    calendar.set(Calendar.MINUTE, minuteFrom);
    calendar.set(Calendar.SECOND, 00);
    int hours_24 = 24 * 60 * 60 * 1000;
    alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), hours_24, pendingIntent);

    // Cancel
    Intent cancelIntent = new Intent(Controller.KEY_CONTROLLER_ACTION);
    intent.putExtra(Controller.KEY_Controller_ACTION, Controller.KEY_ACTION_END);
    intent.putExtra(Controller.KEY_Controller_ID, id);
    PendingIntent cancelPendingIntent = PendingIntent.getBroadcast(
            this,
            id,
            cancelIntent,
            PendingIntent.FLAG_UPDATE_CURRENT);
    calendar.set(Calendar.HOUR_OF_DAY, hourTo);
    calendar.set(Calendar.MINUTE, minuteTo);
    calendar.set(Calendar.SECOND, 00);
    alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), hours_24, cancelPendingIntent);

Here's the problem: The BroadcastReceiver (Controller class) only sometimes has its onReceive called. When it does, it's a few minutes delayed (no big deal; but it is a problem that many times it never gets called). The second alarm (cancelIntent) never gets called.

My Controller BroadcastReceiver is properly declared the manifest. I suspect it has something to do with both Intents being identical (both have extras for type of action, as well as an ID).

What am I doing wrong? Alternatively, what is the more proper way to go about have a from-to based alarm? By this, I mean I need some method to happen at a certain time, and a different method (in the same class; Controller BroadcastReceiver) at an "end" time.


Solution

  • I modified my manifest to take multiple action (real actions, rather than pseudo-actions that I was doing via addExtra).

    <receiver android:name="com.mycompany.myapp.Controller">
            <intent-filter>
                <action android:name="com.mycompany.myapp.Controller.START"/>
            </intent-filter>
            <intent-filter>
                <action android:name="com.mycompany.myapp.Controller.END" />
            </intent-filter>
        </receiver>
    

    Then, when I add the alarms with the Intent, I make sure to call setAction, specifying the String action. In the onReceive of the BroadcastReceiver I call getAction() (returns a String). And voila! Both alarms fire off as intended, and I can get the type of action and perform my associated methods.

    Note: Answered with the help of @Chitrang (via comments to the question). Pointed out that the Intent was getting canceled because there was already an alarm scheduled for the IntentSender.