Search code examples
androidservicealarmmanager

Alarm only recieved when application is running


I have an Android application that allows a user to add an alarm that will log their location. For example, every day at 8am I want to log where I am. When the alarm is received, it starts a service that gets the user's location and saves it to a db. The feature works fine when the app is running (in the background or foreground).

The problem is, the alarm doesn't seem to go off if I go into the task manager and force the app to close. This is important as the user could reboot their phone and kill the app.

Here is the method that sets the alarm:

private void setNewAlarm(int hour, int minute, int id) {
    Intent alarmIntent = new Intent(AutoLoggerActivity.this, AlarmReciever.class);
    alarmIntent.putExtra(Constants.ALARMID_FIELD_NAME, id);
    PendingIntent sender = PendingIntent.getBroadcast(AutoLoggerActivity.this, id, alarmIntent, 0);

    Calendar alarmCal = Calendar.getInstance();
    alarmCal.set(Calendar.HOUR_OF_DAY, hour); // set user selection
    alarmCal.set(Calendar.MINUTE, minute); // set user selection
    alarmCal.set(Calendar.SECOND, 0);

    AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
    alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, alarmCal.getTimeInMillis(), 120000, sender);
}

Here is the BroadcastReceiver:

public class AlarmReciever extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        Bundle bundle = intent.getExtras();     
        int alarmId = bundle.getInt(Constants.ALARMID_FIELD_NAME);
        Toast.makeText(context, "Alarm Running: ID = " + alarmId, Toast.LENGTH_LONG).show();
        Log.d(TAG, "AlarmReceiver: onRecieve. ID = " + alarmId);

        Intent serviceIntent = new Intent(context, LocationRecordingService.class);
        serviceIntent.putExtra(Constants.ALARMID_FIELD_NAME, alarmId);
        context.startService(serviceIntent);
    }
}

Any idea why this is happening?


Solution

  • This is actually a design feature of the Android operating system, and isn't something you can cirumvent. An application that is in a "stopped" state cannot receive any broadcasts. It is only in this state under two conditions:

    1. When the application is first installed before it is ever launched
    2. When the user actively goes into Settings and does a force close

    The problem is, the alarm doesn't seem to go off if I go into the task manager and force the app to close. This is important as the user could reboot their phone and kill the app.

    This is not quite true, because if the device is rebooted the application is not considered to be in this state of being "stopped". However, alarms do not persist reboots, so your application will need to listen for ACTION_BOOT_COMPLETED broadcast by the system when the device starts up so you can reschedule any pending alarms.

    If the user actively kills your app, you must respect that choice of theirs.