0

In my app, I want to do a certain task everyday and after that task is completed I want to trigger multiple notifications at different times (these times will be calculated while doing that task). After googling I found out that using AlarmManager is my best option:

This class provides access to the system alarm services. These allow you to schedule your application to be run at some point in the future. When an alarm goes off, the Intent that had been registered for it is broadcast by the system, automatically starting the target application if it is not already running. Registered alarms are retained while the device is asleep (and can optionally wake the device up if they go off during that time), but will be cleared if it is turned off and rebooted.

My problems are: 1. Notification is shown only for that first time, not after that. 2. AlarmManager is triggered every time I restart that app and that past notification is shown.

PS.: I am a newbie in android and any help is appreciated

Here is what I tried:

Funtion in my activity from I am setting up this Alarm:

    private void handleNotification() {

    Intent alarmIntent = new Intent(this, AlarmReciever.class);
    PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, alarmIntent, PendingIntent.FLAG_CANCEL_CURRENT);
    AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);

    Calendar calendar = Calendar.getInstance();
    calendar.setTimeInMillis(System.currentTimeMillis());
    calendar.set(Calendar.HOUR_OF_DAY, 0);
    calendar.set(Calendar.MINUTE, 0);

    alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pendingIntent);
}

This is my AlarmReciever class:

public class AlarmReciever extends BroadcastReceiver {

@Override
public void onReceive(Context context, Intent intent) {

    ArrayList<String> times = new ArrayList();
    GPSTracker gpsTracker = new GPSTracker(context);

    //calculate the times arraylist

    DateFormat format;
    Date date = null;
    for (String s : times) {
        if (hour12) {
            format = new SimpleDateFormat("hh:mm a", Locale.ENGLISH);
            try {
                date = format.parse(s);
            } catch (ParseException e) {
            }
        } else {
            format = new SimpleDateFormat("hh:mm", Locale.ENGLISH);
            try {
                date = format.parse(s);
            } catch (ParseException e) {
            }
        }
        Intent alarmIntent = new Intent(context, NotificationReciever.class);
        PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, alarmIntent, 0);
        AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);

        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);

        Log.d(Constants.LOG_TAG, calendar.getTime().toString());

        if (Build.VERSION.SDK_INT < 19) {
            alarmManager.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);
        } else {
            alarmManager.setExact(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);
        }
    }
}

}

And this is my NotificationReciever class:

public class NotificationReciever extends BroadcastReceiver {

@Override
public void onReceive(Context context, Intent intent) {

    if (Constants.D) Log.d(Constants.LOG_TAG, "NOTIFICATION RECIEVER");

    NotificationCompat.Builder mBuilder =
            new NotificationCompat.Builder(context)
                    .setSmallIcon(R.drawable.sc_logo_final)
                    .setContentTitle(context.getResources().getString(R.string.app_name))
                    .setContentText(context.getResources().getString(R.string.app_name));
    Intent resultIntent = new Intent(context, NavigationDrawerActivity.class);
    TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
    stackBuilder.addParentStack(NavigationDrawerActivity.class);
    stackBuilder.addNextIntent(resultIntent);
    PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
    mBuilder.setContentIntent(resultPendingIntent);
    NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
    mNotificationManager.notify(1, mBuilder.build());

}

}

In my AndroidManifest.xml,

    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

        <receiver android:name=".AlarmReciever">
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED" />
        </intent-filter>
    </receiver>
    <receiver android:name=".NotificationReciever">
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED" />
        </intent-filter>
    </receiver>
Saeed Jassani
  • 1,079
  • 2
  • 11
  • 27

1 Answers1

3

First of all, this code is most likely setting up an alarm to happen at midnight of the current day, which is almost certainly in the past compared to the current time, which means you'll receive the alarm very quickly:

Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);

According to the javadoc for setRepeating():

If the stated trigger time is in the past, the alarm will be triggered immediately, with an alarm count depending on how far in the past the trigger time is relative to the repeat interval.

Your Alarm does not repeat because you're using the flag INTERVAL_DAY, which only works with setInexactRepeating().

If you want to run something at midnight of the next day, you will need to add one day to the calendar. You might also consider setting the seconds field to 0 as well.

If you're registering the alarm every time the app starts, you'll keep getting that early alarm every time. Also according to the javadoc:

If there is already an alarm scheduled for the same IntentSender, it will first be canceled.

The alarm is not repeating because you're passing an interval that is only valid for setInexactRepeating().

Doug Stevenson
  • 297,357
  • 32
  • 422
  • 441
  • Any idea why the notifications are not triggered for the rest of the times? – Saeed Jassani Mar 21 '16 at 02:44
  • Please clear one more thing... I am registering alarm after getting location permission (and the overrided method is called every time the app starts)... so ideally when should i register alarm? i tried to do this way: http://stackoverflow.com/a/10836555/4451655 but it did not help.... – Saeed Jassani Mar 21 '16 at 03:32
  • I'm not sure what you're asking. You can register any time you're ready to start receiving your alarms at midnight. You can re-register if you're not certain if it's already registered because it will just cancel the old one. – Doug Stevenson Mar 21 '16 at 03:48
  • but in that case past notification will be re-received... i.e in case of i restart the app – Saeed Jassani Mar 21 '16 at 03:49
  • Just don't schedule alarms to occur in the past unless that's what you really want. Schedule for the next future midnight instead. – Doug Stevenson Mar 21 '16 at 03:50
  • You should replace all that Calendar setup with GregorianCalendar calendar = new GregorianCalendar(); which instantiates a Calendar on the current day at 00:00:00 with the user's Locale. – devrocca Mar 22 '16 at 09:05