0

Creating a recurring event programmatically is killing me (I need to do it without the Calendar Intent). I've been reading a lot of posts but nothing seems to completely works for me. This is my current code:

    Calendar beginTime = Calendar.getInstance();
    Calendar endTime = Calendar.getInstance();
    Calendar reminderBeginTime = Calendar.getInstance();
    long startMillis = 0;
    long endMillis = 0;


    ContentResolver cr = getContentResolver();
    ContentValues values = new ContentValues();

    long calID = 1;
    values.put(CalendarContract.Events.CALENDAR_ID, calID);
    values.put(CalendarContract.Events.TITLE, title);
    values.put(CalendarContract.Events.EVENT_TIMEZONE, "Europe/London");
    beginTime.set(2015, 0, 16, 9, 00);
    startMillis = beginTime.getTimeInMillis();
    endTime.set(2015, 0, 16, 24, 00);
    endMillis = endTime.getTimeInMillis();
    values.put(CalendarContract.Events.DTSTART, startMillis);
    values.put(CalendarContract.Events.DTEND, endMillis);
    values.put(CalendarContract.Events.RRULE, "FREQ=WEEKLY;UNTIL=20160116");
Uri eventUri = cr.insert(CalendarContract.Events.CONTENT_URI, values);

The result of this code is a bit unpredictable. In the recurring rule I am setting the recurring final date to 16/2/2016, however it only creates recurring events until...may of 2015, or august, sometimes september, april...no idea why.

According to the official documentation:

For recurring events, you must include a DURATION in addition to RRULE or RDATE. Note that this rule does not apply if you're inserting an event through the INSERT Intent, described in Using an intent to insert an event—in that scenario, you can use an RRULE in conjunction with DTSTART and DTEND, and the Calendar application converts it to a duration automatically.

So, I remove "Until=..." from the RRULE and add the duration for 10 weeks for example:

values.put(CalendarContract.Events.DURATION, "P10W");

But the app crash, logging this:

Cannot have both DTEND and DURATION in an event

In a way, I understand DTEND as the moment when a particular event ends, which I don't see why I have to delete it...anyway, if I delete it, it set reminders EVERY DAY and FOREVER.

Cœur
  • 37,241
  • 25
  • 195
  • 267
Rafag
  • 719
  • 3
  • 11
  • 27

1 Answers1

0

Probably a bit late, but I'll leave the answer here for anyone who is still stuck in this problem.

As you stated:

For recurring events, you must include a DURATION in addition to RRULE or RDATE. Note that this rule does not apply if you're inserting an event through the INSERT Intent, described in Using an intent to insert an event—in that scenario, you can use an RRULE in conjunction with DTSTART and DTEND, and the Calendar application converts it to a duration automatically.

But according to your quote,

In a way, I understand DTEND as the moment when a particular event ends, which I don't see why I have to delete it...anyway, if I delete it, it set reminders EVERY DAY and FOREVER.

it seems you are not understanding what the field CalendarContract.Event.DURATION stands for.

In a recurring event the DTEND of each instance is calculated adding the CalendarContract.Instance.DTSTART + CalendarContract.Instance.DURATION. This is because the calendar provider only uses DTSTART to get instances of the recurring event and calculates the DTEND dynamically.

So when you set the CalendarContract.Instance.DURATION to "P10w" you are asking the calendar provider to get an event which starts in CalendarContract.Instance.DTSTART start point and ends 10 weeks after.

A solution to the problem would be to set the duration to the difference in miliseconds between CalendarContract.Instance.DTSTART and CalendarContract.Instance.DTEND using as CalendarContract.Instance.DURATION P'difference/1000'S

Alex Cuadrón
  • 638
  • 12
  • 19