Android Calendar Intent

Myrick Chow
ITNEXT
Published in
10 min readNov 10, 2019

--

Calendar is the most common application that user uses daily. User can add his / her daily plans into it. Calendar can notice user for the upcoming events automatically. It is useful if an application can add an event to the Calendar app and remind user for the future event.

Android provides mainly two approaches to work on calendar event. One is using Calendar Provider and the another one is handing off it to the system Calendar app.

Calendar Provider provides us all the functionalities, including inserting, querying, updating and deleting existing calendar events. However, the steps are tedious and must require user’s runtime permissions (android.permission.READ_CALENDAR and android.permission.WRITE_CALENDAR) to read and write the sensitive calendar information. It is easy to make a mistake with this approach.

Quoted from Google official documentation of Calendar Provider

Therefore, Google officially recommends developer to use the second approach, i.e. handing off all the calendar operations to system Calendar app by using Intent. Calendar app is opened right after requested by our app and user is automatically redirected back to our app after user finishes his / her calendar actions. In system Calendar app, there has already been a well-designed UI for user to fill in necessary calendar information. Good UI and UX can then be guaranteed.

Example of system Calendar app in my Samsung device

This article will briefly cover:

  1. Limitation of Intent approach
  2. Structure of Android Calendar database
  3. Idea of Content Provider
  4. Coding 1) : Inserting new calendar event
  5. Coding 2): Viewing events on a specific date
  6. Coding 3): View an event details by event id
  7. Coding 4): Update an event by event id
  8. Recurrence Rule (RRule) definition
  9. Calendar field: Invitees

Limitation of Intent approach

Not all calendar operations are available for Intent approach. See the above table. As stated mentioned at the Calendar Intent official documentation, Calendar Intent can only view, edit and create a calendar event. Deletion is not an option. In order to delete an existing one, Calendar Provider has to be used and lots of tedious codes have to be added. See here.

Calendar structure

Android Calendar structure

In Android system, there are mainly 5 tables under Calendar structure and can be divided into 3 levels in Android calendar structure. They are:

  1. Calendar
  2. Event
  3. Attendee, Reminder and Instance

There is also a Time table which will be covered at the later session.

In each device, one or more calendar accounts can be added, e.g. Google, Apple and Microsoft. Under each calendar, there can be a list of event. At the same time, there can be a list of attendees, reminders and instance under each event.

The concept of event and instance is likely confusing. Let’s explain with a calendar example:

Event: Every Tuesday from 1st January, 2019 to 31st December, 2019.

Instance:

  1. (Tuesday) 1st January, 2019
  2. (Tuesday) 8th January, 2019,

53. (Tuesday) 31st December, 2019

There are totally 53 instances under a single weekly event.

Calendar provider

Calendar provider is one of the content providers which store data in a relational database model and expose them to other applications through unique public URIs (Uniform Resource Identifier). As mentioned above, there are mainly 5 tables controlled by Calendar Provider and thus there are 5 public URIs.

  1. Calendars table URI: content://com.android.calendar/calendars
  2. Events table URI: content://com.android.calendar/events
  3. Attendees table URI: content://com.android.calendar/attendees
  4. Reminders table URI: content://com.android.calendar/reminders
  5. Instances table URI: content://com.android.calendar/instances

Every Content Provider provides URI with a special format. URI must start with content:// and followed by the class of provider. The last parameter is the name of table.

Coding part

Coding part will be split into four parts:

  1. Inserting new calendar event
  2. Viewing a list of calendar event by a given time
  3. Viewing an existing calendar event by event id
  4. Updating an existing calendar event

Parts of the codes are shared between each category.

Coding 1) : Inserting new calendar event

Step 1: Define an Intent

As mentioned before, app hands off the calendar action to the system Calendar app. Therefore, the only way to pre-fill the information at the system Calendar app is to pass it through Intent.

The 1st parameter to be set is the action of Intent. There are three possible choices:

  1. Intent.ACTION_INSERT
    (Used for creating a new Calendar event)
  2. Intent.ACTION_VIEW
    (Used for viewing an existing Calendar event either by event id or event time)
  3. Intent.ACTION_EDIT
    (Used for editing an existing Calendar event)

The 2nd thing to be set is the CONTENT_URI of the table we are now editing to. As mentioned above, there are mainly 5 different tables under Calendar structure. To view, edit and create a calendar event, it should point to the Events table which stores the information of all calendar events.

Step 2: Add extra data to Intent

Calendar information can be passed to Calendar app by Intent through extra. See the above image for all the available keys.

Most of the parameters are self-explanatory except the RRULE which stands for “Recurrence Rule”. It is just like SQL statement which defines the query rules for system to filter specific days. It will be explained in details in the coming session.

Step 3: Open system calendar app

Calendar app can be triggered by using the simplest function startActivity(intent: Intent).

Coding 2): Viewing events on a specific date

Screenshot of result of viewing events by date

The 2nd calendar feature is viewing events on a specific date. The date cell specified by the the provided timestamp is highlighted on Calendar app. The above sample code is using timestamp 1546300800000 which is 1st January, 2019.

One important thing is that the URI used this time is content://com.android.calendar/time/1546300800000. It is pointing to a table of Time instead of the Calendar, Events, Attendees, Reminders and Instances. Since Time does not provide a public URI, the URI has to be constructed with Uri.Builder.

The second important thing is that Intent action is no longer Intent.ACTION_INSERT and should be changed to Intent.ACTION_VIEW. By definition, Intent.ACTION_VIEW is used for displaying data to the user and Intent.ACTION_INSERT is used for inserting an empty item into the given container.

Coding 3): View an event details by event id

Android provides an approach to view the event details by event id which can only be queried from Calendar Provider. Due to the sensitive user information, read calendar permission (android.permission.READ_CALENDAR) must be granted at runtime.

Step 1: Request android.permission.READ_CALENDAR permission

RxPermission is recommended to be used for requesting permission at runtime due to its simplicity for requesting permission and checking the status.

Step 2: Get event id from Calendar Content Provider

At the above function, both the event_id and title columns are queried for demonstration. Actually all fields in an event can be queried.

Step 3: Construct an URI with event ID

This time we could use the withAppendedId() function to construct the URI since Events table provides the public CONTENT_URI. The final URI format is content://com.android.calendar/events/{event_id}.

Step 4: Set Intent action to Intent.ACTION_VIEW

Same as the session before, Intent.ACTION_VIEW has to be used since it is now viewing a record instead of creating a new record. The following page, which has only share and delete functions, of the event is eventually shown:

Coding 4): Update an event by event id

The final available calendar action provided by Android is updating an existing event. Like the one for viewing an event by its event id, the URI is in format of content://com.android.calendar/events/{event_id}. However, the Intent action has to be changed to Intent.ACTION_EDIT which provides explicit editable access to the given data. All event fields added at the “Coding 1)” can be updated here with the same extra keys.

Get the response from user

User can either perform or cancel the calendar functions (insert and update). App can detect this result at the onActivityResult() callback.

Result code can be either Activity.RESULT_OK (value: -1)when user has performed the action successfully or Activity.RESULT_CANCELED (value: 0) when user canceled the actions.

Moreover, there is only data returned when an event is inserted or updated. There are only three fields stored in the returned Intent:

Key: timezone; Value: Asia/Hong_Kong
Key: allday; Value: false
Key: go_to_millis; Value: 1573365600000

Recurrence rule

Recurrence rule defines the repeating pattern for recurring events. It is in form of string. For example, FREQ=WEEKLY;BYDAY=MO;COUNT=3 represents a pattern repeating 3 times on every Monday weekly, i.e. Monday, 2019-Nov-05 & 12 & 19.

The rule is written in the format of {rule_name}={rule_value} and concatenated with others with semicolon ;.

There are lots of global standard recurrence rules. Here are the four common rules which could be able to handle most cases — FREQ, UNTIL, COUNT and BYDAY.

1. FREQ (Frequency)

Frequency defines how often the pattern is repeated. It accepts the following parameters:

  1. DAILY
  2. WEEKLY
  3. MONTHLY
  4. YEARLY

Example: FREQ=DAILY

2. UNTIL

UNTIL defines the end date of the frequency. It accepts a value in date format of yyyyMMdd'T'HHmmss'Z', e.g. “20191105T000000Z”

Example: FREQ=DAILY;UNTIL=20191105T000000Z means repeating the event every day until the 5th November, 2019.

3. COUNT

COUNT defines the number of occurrence of the frequency. It accepts an integer value.

Example: FREQ=DAILY;COUNT=10 means repeating the event every day for 10 rounds, i.e. 10 days.

4. BYDAY

BYDAY defines the list of weekday that the repeating pattern should be applied. It accepts the following parameters:

  1. MO (Monday)
  2. TU (Tuesday)
  3. WE (Wednesday)
  4. TH (Thursday)
  5. FR (Friday)
  6. SA (Saturday)
  7. SU (Sunday)

Example: FREQ=WEEKLY;BYDAY=MO,FR means the pattern repeats on every Monday and Friday weekly.

Practical examples:

  1. Repeat yearly on the upcoming 3 years
    FREQ=YEARLY;COUNT=3
  2. Repeat monthly until 1st January, 2020
    FREQ=MONTHLY;UNTIL=20200101T000000Z
  3. Repeat every Monday and Thursday on the upcoming 3 weeks. Count is 6 since total occurrence is 2x3 = 6.
    FREQ=WEEKLY;BYDAY=MO,TH;COUNT=6
  4. Repeat weekly on Monday until 1st January, 2020 FREQ=WEEKLY;BYDAY=MO,TU;UNTIL=20200101T000000Z

Trick on Recurrence Rule

UNTIL and COUNT contradict with each other. UNTIL defines the end date of the frequency. COUNT defines the number of occurrence of the frequency.

Android would ignore the presence of COUNT if UNTIL is presented, i.e. FREQ=DAILY;COUNT=10;UNTIL=20191105T000000Z equals to FREQ=DAILY;UNTIL=20191105T000000Z

Calendar field: Invitees

Invitee is a special field in Calendar information. It accepts either an email address or a list of email addresses separated with comma. See below example:

Automatic invitation email

An email will be automatically sent to all invitees right after the calendar is created, updated and deleted. See below for the email templates:

Screenshot of the newly invited event
Screenshot of the updated event
Screenshot of the deleted event

Automatic confirmation email

If invitee accepts or declines the user’s invitation, a confirmation email is sent to the user automatically. See below for the templates:

Invitee accepts the invitation
Invitee declines the invitation
Invitee is not sure if he / she can attend the event

Add to invitee’s calendar (Both Android & iOS )

Together with the email, there is an invite.ics attachment which is readable in both Android and iOS. The invitee can click on this attachment and system would automatically pop up the calendar app to insert the calendar events.

Summary

  1. Android provides two approaches to handle Calendar operation and the recommended approach is handing off the operation to system Calendar app. Using Intent approach can reduce the risk on handling calendar operations since trustable UI and UX are provided by system
  2. There are mainly 6 tables controlled under calendar structure. They are Calendars, Events, Attendees, Reminders, Instances and Time. But Time does not provide a public URI.
  3. Different operations have to use different Intent action. Intent.ACTION_INSERT should be used when event is going to be created. Intent.ACTION_EDIT should be used when event is going to be updated. Intent.ACTION_VIEW should be used when event is going to be viewed.
  4. android.permission.READ_CALENDAR has to be requested and event id has to be retrieved before editing or viewing an existing record.
  5. Recurrence rule is a SQL like statement. The most usefully codes are FREQ (Frequency), UNTIL (End time of repeat pattern), COUNT(number of occurrence) and BYDAY (Specific days).
  6. Automatic invitation emails are sent to all invitees and confirmation emails are sent back to user when invitees make their choices on the invited event. Invitee can add the event to calendar by the email attachment (Invite.ics).

Hope this article could give you more understanding on Android Calendar. Have a nice day~ Cheer! 😉

--

--

Mobile Lead @REAL Messenger Inc. https://real.co Focus on Android & iOS Native programming.