Zubair Ahmed
Zubair Ahmed

Reputation: 2897

How to set Alarm for working days in android

I have a scenario

Setting alarm for (Monday to Friday)

Let say I choose time that is: hour = 9, minutes = 15, am_pm = "AM".

Now I want to set Alarm for every Monday to Friday at 9:15 AM

Code below I tried but not getting desired result.

if(choice.equals("Week Days (Mon-Fri)"))
{
    for(int a = 2; a <= 5; a++) //here I am assuming a is from 2 to 5 (calendar DAY_OF_WEEK from Monday to Friday)
    {
        Calendar alarmCalendar = Calendar.getInstance();

        alarmCalendar.set(Calendar.HOUR_OF_DAY, _hourOfDay);

        alarmCalendar.set(Calendar.MINUTE, _minute);

        alarmCalendar.set(Calendar.SECOND, 0);

        alarmCalendar.set(Calendar.MILLISECOND, 0);

        if(am_pm.equals("AM"))
        {
            alarmCalendar.set(Calendar.AM_PM, 0);
        }
        else
        {
            alarmCalendar.set(Calendar.AM_PM, 1);
        }


        alarmCalendar.set(Calendar.DAY_OF_WEEK, a);

        Long alarmTime = alarmCalendar.getTimeInMillis();

        alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, 
                alarmTime, 24 * 60 * 60 * 1000 , pendingIntent);
    }

    Toast.makeText(ActivityReminder.this, "Meeting Reminder Set on Week Days (Mon-Fri)", 
                        Toast.LENGTH_LONG).show();
}

I've used BroadcastReceiver like:

public class AlarmReceiver extends BroadcastReceiver
{
    NotificationManager mNotificationManager;

    Context context;

    public static final String TAG = "Reminder...";

    @Override
    public void onReceive(Context context, Intent intent)
    {
        this.context = context;

        String subject = "<h3>Meeting Reminder: </h3>" + intent.getStringExtra("subject");

        Toast.makeText(context, Html.fromHtml(subject), Toast.LENGTH_LONG).show();

        showNotification(subject);
    }

    @SuppressWarnings("deprecation")
    private void showNotification(String msg) 
    {
        Intent notificationIntent = new Intent(context.getApplicationContext(),
                ActivityMainScreen.class);

        TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);

        stackBuilder.addParentStack(ActivityMainGeofence.class);

        stackBuilder.addNextIntent(notificationIntent);

        String arrivalTime = TimeUtil.toString(Calendar.getInstance().getTime(), 
                "dd-MM-yyyy hh:mm:ss a");

        notificationIntent.putExtra("subject", msg)
        .putExtra("time", arrivalTime).putExtra("type", "Meetings/Reminder");

        PendingIntent notificationPendingIntent = stackBuilder
                .getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);

        Notification notification = new Notification();
        notification.icon = R.drawable.app_icon;

        notification.setLatestEventInfo(context.getApplicationContext(), 
                "WFM Meeting Reminder", Html.fromHtml(msg), notificationPendingIntent);

        notification.flags |= Notification.FLAG_AUTO_CANCEL;

        notification.defaults |= Notification.DEFAULT_SOUND;

        notification.defaults |= Notification.DEFAULT_VIBRATE;

        NotificationManager mNotificationManager = (NotificationManager) 
                context.getSystemService(Context.NOTIFICATION_SERVICE);

        mNotificationManager.notify(0, notification);

    }
}

Finally in Manifest:

<receiver android:name="com.my_package_name.AlarmReceiver" >
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED" />
            </intent-filter>
</receiver>

EDITED: Here I want to tell that One Time Alarm worked for me but for above choice Week Days (Mon-Fri) is not working correctly

The working code is:

if(choice.equals("One Time"))
{
    alarmManager.set(AlarmManager.RTC_WAKEUP, PERIOD, pendingIntent); // here PERIOD is the time selected by me in milliseconds...

    Toast.makeText(ActivityReminder.this, "Meeting Reminder Set One Time", 
            Toast.LENGTH_LONG).show();
}

Where am I doing wrong. Any help would be appreciated.

Upvotes: 6

Views: 5185

Answers (4)

Chitrang
Chitrang

Reputation: 5097

) First of all you can not have for loop for same pending intent, it will cancel the previous instances.

) Solution is to set alarm again through broadcast receiver inside onReceive method, after completion of alarm.

) Here is an idea of how to achieve this, include rest of the code as per your requirement. I have used calendar class to set alarm, and on friday skip 2 days in between.

void setAlarm() {
    AlarmManager alarmManager = (AlarmManager) context
            .getSystemService(Context.ALARM_SERVICE);
    if (choice.equals("One Time")) {
        alarmManager.set(AlarmManager.RTC_WAKEUP, PERIOD, pendingIntent);

        Toast.makeText(context, "Meeting Reminder Set One Time",
                Toast.LENGTH_LONG).show();
    } else if (choice.equals("Week Days (Mon-Fri)")) {
        Calendar calendar = Calendar.getInstance();
        int day = calendar.get(Calendar.DAY_OF_WEEK);

        switch (day) {
        case Calendar.MONDAY:
            alarmManager
                    .set(AlarmManager.RTC_WAKEUP, PERIOD, pendingIntent);
        case Calendar.TUESDAY:
            alarmManager
                    .set(AlarmManager.RTC_WAKEUP, PERIOD, pendingIntent);
        case Calendar.WEDNESDAY:
            alarmManager
                    .set(AlarmManager.RTC_WAKEUP, PERIOD, pendingIntent);
        case Calendar.THURSDAY:
            alarmManager
                    .set(AlarmManager.RTC_WAKEUP, PERIOD, pendingIntent);
        case Calendar.FRIDAY:
            alarmManager.set(AlarmManager.RTC_WAKEUP, PERIOD * 3,
                    pendingIntent);
        }
    }
}

) For "choice" in if-else condition you might have to store these value somewhere like SharedPreferences.

Upvotes: 2

Jitty Aandyan
Jitty Aandyan

Reputation: 2004

Try this code its worked for me...

    for (int k = 2; k < 5; k++) {
                    int sday = k;
                    Calendar today = Calendar.getInstance();
                    Calendar AlarmDate = Calendar.getInstance();
                    AlarmDate.set(Calendar.HOUR_OF_DAY, inputH);
                    AlarmDate.set(Calendar.MINUTE, inputM);
                    AlarmDate.set(Calendar.SECOND, 0);
                    while (today.after(AlarmDate)) {
                        AlarmDate.add(Calendar.DAY_OF_MONTH, 1);
                    }
                    while (AlarmDate.get(Calendar.DAY_OF_WEEK) != sday) {
                        AlarmDate.add(Calendar.DAY_OF_MONTH, 1);
                    }

                    Intent i = new Intent(this, AlertPopUpActivity.class);
                    i.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
                    i.putExtra("uid", k + (alert.getId() * 1000)); //a unique id for alram
                    i.putExtra("id", alert.getId());
                    i.putExtra("msg", alert.getEventName());

                    if (minute < 10)
                        i.putExtra("time", hour + ":0" + minute);
                    else
                        i.putExtra("time", hour + ":" + minute);
                    i.putExtra("ampm", inputAMPM);
                    PendingIntent pi = PendingIntent.getActivity(this,
                            k + (alert.getId() * 1000), i,         //same unique id (used to update alram if canceled)
                            PendingIntent.FLAG_UPDATE_CURRENT);

                    am.set(AlarmManager.RTC_WAKEUP, AlarmDate.getTimeInMillis(), pi);
                    System.out.println("Set Time :" + AlarmDate.getTime());
                }

Upvotes: 3

A J
A J

Reputation: 1120

I would assume that the alarm only gets set for Friday at 9:15? This should be because of the following line in the AlarmManager docs:

If there is already an alarm scheduled for the same IntentSender, it will first be canceled. http://developer.android.com/reference/android/app/AlarmManager.html#setRepeating(int, long, long, android.app.PendingIntent)

In order to do what you want, you'd either want 5 PendingIntents or just set an alarm for the first event, and when that alarm is received, you set the alarm for the next day and so on.

I'd probably go with the second option, since in the first method you'd need 5 different PendingIntents, which means that their requestCode or backing Intent must be different (with different type, action, or category).

Upvotes: 5

Chris
Chris

Reputation: 240

Check out the page for AlarmManager, and look at the note in setRepeating(). As of API 19, the repeating functions are inexact. To get the proper repetition you have to handle the alarm each time and reschedule it.

Upvotes: 2

Related Questions