简体   繁体   中英

Setting up Alarm Manager to trigger multiple notifications

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>

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() .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM