Android Calendar Provider (An Untold Story about Recurring Events and Event Exceptions)

I was building an android library, which sync’s calendar events data from server to android local calendar (In short, CalDav Client for Android). At start it was pretty much easy with the help of Android Developer Docs. But then the nightmare begins, I need to sync Recurring events (which is also simple by setting RRULE in Events Table) and Exceptions or Overridden Instances of original recurring events. So, I started to search online and found nothing.

Recurring Events:

  • Recurring events are those repeats based on RRULE specified. (If you want to meet a person every week monday for 3 times, then its a recurring event)

Event Exception for Recurring Event:

Consider a case, that you need to meet “Jerry at the Tower park” between 10 to 11 am for 4 consecutive days. And you had recorded the event in your android calendar, then jerry called you and changed meeting spot to “Station” on the 3rd day. So now you need to add an exception for your recurring event on the 3rd day alone to meet “Jerry at the Station”.

How Android handles Exception Events ?

Android persist both normal events and exceptional or overridden events in CalendarContracts.Events.

Exceptional event can be identified with the help of ORIGINAL_SYNC_ID column, orginal_sync_id will be null for all normal events. And for every exceptional event “_SYNC_ID” column will be null

_SYNC_ID Column in Events Table:

_SYNC_ID is an unique id for every event in a calendar, which is not _ID assigned locally by providers. Instead _SYNC_ID is an unique id generated (locally or returned from server, depends on the type of calendar service provider) after syncing the event with server.

Inshort, _SYNC_ID of an event will be common for both local android calendar provider and the application server.

Until the events are synced, _SYNC_ID will return null and no exception for the recurring event can be added.

So, How to insert repeating event and an exception in it?

Simply insert the repeating event with RRULE in CalendarContracts.Events table and for an exception of it, insert another in CalendarContracts.Events table with ORIGINAL_SYNC_ID as _SYNC_ID of the repeating event and ORIGINAL_INSTANCE_ID as the dtstart of particular instance in the repeating event.

Again, lets see the above mentioned case of “Meeting jerry at the Tower park, between 10am to 11am every day from 19th sept,2015 until 22nd sept,2015”.

So we can insert a repeating event with RRULE:FREQ=DAILY;COUNT=4 , _SYNC_ID and all other event data in Events Table.

Then consider, jerry call you to change the meeting spot to “The Staion” on the 3rd day of meeting (ie, 21st sept, 2015). Now you need to set an exception for the previously added repeating event only on the 3rd day.

To do that, insert another event leaving _SYNC_ID as null and set ORIGINAL_SYNC_ID column with the _SYNC_ID specified for the repeating event. And also set the value for ORIGINAL_INSTANCE_TIME, which is the start time of the particular instance from the repeating event. In our case, the ORIGINAL_INSTANCE_TIME will be 10am on 21st sept, 2015 (in milli’s).

Code reference for the case illustrated above.