Android Tutorial–Programming with Calendar

One of the popular apps on Android device is the Calendar application. As one of the android app development philosophy is to make use of functionalities of other apps, it is expected by many developers that we can access the calendar data easily. However, the truth is NO!

Android doesn’t provide an official API for read/write Calendar data, probably because Android is going to change the calendar data format in future release.

The good news is there’re workarounds, more than one. This tutorial will list out those methods and provide an example at the end of the tutorial.

1. Google Calendar APIs

Google doesn’t provide Calendar API specifically for Android, but it does provide an Calendar API for more general use. The API supports .NET, Java and Python, so it is expected that it can be used in Android.

However, this method requires the app to establish a network connection through Internet (probably requires some kind of authentication), and then access the calendar data. As android already has Calendar app built in, it sounds dumb that we’ll need to connect to Internet, create a connection and access the data.

This approach is not explored in detail here. Interested readers could refer reference 2 for more details.

2. Android Calendar Private APIs

Android is open source, so it’s not difficult to find out that android actually has undocumented APIs for calendar (it’s just not public APIs).

This part will cover how to get list of calendars, how to read event, and how to add event.

2.0 Permission Declaration

In order to read calendar data, one needs to declare the “READ_CALENDAR” permission in AndroidManifest.xml file.

<uses-permission android:name="android.permission.READ_CALENDAR"></uses-permission>

 

For write to Calendar, there’s a another “WRITE_CALENDAR” permission.

<uses-permission android:name="android.permission.WRITE_CALENDAR"></uses-permission>

 

You can refer to the complete code at the end of the tutorial for exact position of the declaration.

2.1 List Calendars

One may have multiple calendars created in Calendar application. For me, I have the default calendar, a Singapore Holiday Calendar, and a third calendar from my other Gmail account.

The code to get a list of all calendars are as below,

class MyCalendar {
    public String name;
    public String id;
    public MyCalendar(String _name, String _id) {
        name = _name;
        id = _id;
    }
    @Override
    public String toString() {
        return name;
    }
}
private MyCalendar m_calendars[];
private void getCalendars() {
    String[] l_projection = new String[]{"_id", "displayName"};
    Uri l_calendars;
    if (Build.VERSION.SDK_INT >= 8 ) {
        l_calendars = Uri.parse("content://com.android.calendar/calendars");
    } else {
        l_calendars = Uri.parse("content://calendar/calendars");
    }
    Cursor l_managedCursor = this.managedQuery(l_calendars, l_projection, null, null, null);    //all calendars
    //Cursor l_managedCursor = this.managedQuery(l_calendars, l_projection, "selected=1", null, null);   //active calendars
    if (l_managedCursor.moveToFirst()) {
        m_calendars = new MyCalendar[l_managedCursor.getCount()];
        String l_calName;
        String l_calId;
        int l_cnt = 0;
        int l_nameCol = l_managedCursor.getColumnIndex(l_projection[1]);
        int l_idCol = l_managedCursor.getColumnIndex(l_projection[0]);
        do {
            l_calName = l_managedCursor.getString(l_nameCol);
            l_calId = l_managedCursor.getString(l_idCol);
            m_calendars[l_cnt] = new MyCalendar(l_calName, l_calId);
            ++l_cnt;
        } while (l_managedCursor.moveToNext());
    }
}

The code essentially queries the android calendar content provider and goes through the calendar list returned. The name and calendar id are stored in m_calendars[].

For android version less than 8, the uri for query calendars is content://calendar/*, while content://com.android.calendar/* is used for android version 8 and above.

2.2 Read Events

To read a list of Calendar events, one can create another query as illustrated below,

private void getLastThreeEvents() {
    Uri l_eventUri;
    if (Build.VERSION.SDK_INT >= 8 ) {
        l_eventUri = Uri.parse("content://com.android.calendar/events");
    } else {
        l_eventUri = Uri.parse("content://calendar/events");
    }
    String[] l_projection = new String[]{"title", "dtstart", "dtend"};
    Cursor l_managedCursor = this.managedQuery(l_eventUri, l_projection, "calendar_id=" + m_selectedCalendarId, null, "dtstart DESC, dtend DESC");
    //Cursor l_managedCursor = this.managedQuery(l_eventUri, l_projection, null, null, null);
    if (l_managedCursor.moveToFirst()) {
        int l_cnt = 0;
        String l_title;
        String l_begin;
        String l_end;
        StringBuilder l_displayText = new StringBuilder();
        int l_colTitle = l_managedCursor.getColumnIndex(l_projection[0]);
        int l_colBegin = l_managedCursor.getColumnIndex(l_projection[1]);
        int l_colEnd = l_managedCursor.getColumnIndex(l_projection[1]);
        do {
            l_title = l_managedCursor.getString(l_colTitle);
            l_begin = getDateTimeStr(l_managedCursor.getString(l_colBegin));
            l_end = getDateTimeStr(l_managedCursor.getString(l_colEnd));
            l_displayText.append(l_title + "n" + l_begin + "n" + l_end + "n----------------n");
            ++l_cnt;
        } while (l_managedCursor.moveToNext() && l_cnt < 3);
        m_text_event.setText(l_displayText.toString());
    }
}

The method above get the last three events from the selected calendar. Note that m-selectedCalendarId variable and getDateTimeStr() method are defined by us. You can refer to code at the end of the tutorial for a complete picture.

2.3 Create an Event

Similarly, one can insert a new event into Calendar database.

/*add an event to calendar*/
private void addEvent() {
    ContentValues l_event = new ContentValues();
    l_event.put("calendar_id", m_selectedCalendarId);
    l_event.put("title", "roman10 calendar tutorial test");
    l_event.put("description", "This is a simple test for calendar api");
    l_event.put("eventLocation", "@home");
    l_event.put("dtstart", System.currentTimeMillis());
    l_event.put("dtend", System.currentTimeMillis() + 1800*1000);
    l_event.put("allDay", 0);
    //status: 0~ tentative; 1~ confirmed; 2~ canceled
    l_event.put("eventStatus", 1);
    //0~ default; 1~ confidential; 2~ private; 3~ public
    l_event.put("visibility", 0);
    //0~ opaque, no timing conflict is allowed; 1~ transparency, allow overlap of scheduling
    l_event.put("transparency", 0);
    //0~ false; 1~ true
    l_event.put("hasAlarm", 1);
    Uri l_eventUri;
    if (Build.VERSION.SDK_INT >= 8 ) {
        l_eventUri = Uri.parse("content://com.android.calendar/events");
    } else {
        l_eventUri = Uri.parse("content://calendar/events");
    }
    Uri l_uri = this.getContentResolver().insert(l_eventUri, l_event);
    Log.v("++++++test", l_uri.toString());
}

The code above simply create a ContentValues and insert it into the database URI.

3. Sending Intent to Calendar

This method doesn’t require the READ/WRITE_CALENDAR permission. It sends out an intent to calendar, and users will be redirected to Calendar app to create the event. Note that this is not a documented method either.

Below is a method that adds an event to Android Calendar.

/*add an event through intent, this doesn't require any permission
* just send intent to android calendar
*/
private void addEvent2() {
   Intent l_intent = new Intent(Intent.ACTION_EDIT);
   l_intent.setType("vnd.android.cursor.item/event");
   //l_intent.putExtra("calendar_id", m_selectedCalendarId);  //this doesn't work
   l_intent.putExtra("title", "roman10 calendar tutorial test");
   l_intent.putExtra("description", "This is a simple test for calendar api");
   l_intent.putExtra("eventLocation", "@home");
   l_intent.putExtra("beginTime", System.currentTimeMillis());
   l_intent.putExtra("endTime", System.currentTimeMillis() + 1800*1000);
   l_intent.putExtra("allDay", 0);
   //status: 0~ tentative; 1~ confirmed; 2~ canceled
   l_intent.putExtra("eventStatus", 1);
   //0~ default; 1~ confidential; 2~ private; 3~ public
   l_intent.putExtra("visibility", 0);
   //0~ opaque, no timing conflict is allowed; 1~ transparency, allow overlap of scheduling
   l_intent.putExtra("transparency", 0);
   //0~ false; 1~ true
   l_intent.putExtra("hasAlarm", 1);
   try {
       startActivity(l_intent);
   } catch (Exception e) {
       Toast.makeText(this.getApplicationContext(), "Sorry, no compatible calendar is found!", Toast.LENGTH_LONG).show();
   }
}

This method is used in my android app, Advanced Phone Log.

4. A Complete and Runnable Example

The code snippet shown above are retrieved from an example. You can download the source code here, or find it at github.

Below are screenshots of the app.

234

Figure 1. Screenshots of Calendar Sample App

Reference:

1. Working with the Android Calendar: http://www.developer.com/ws/article.php/3850276/Working-with-the-Android-Calendar.htm

2. Google Calendar APIs and Tools: http://code.google.com/apis/calendar/data/2.0/developers_guide.html

0 thoughts on “Android Tutorial–Programming with Calendar”

  1. Hello,

    i am trying to run this code on my eclipse platform (API level 14) but as soon as my android phone launches, it gives me an error “Unfortunately,CalendarOps has stopped”. Can you please help me?

  2. Yesterday, I have read many articles and forums about reading data from android calendar, but there were always some mistakes, that lead to errors.
    And this site was a remedy. Great job, everything works properly 😉

  3. Awesome! This is great!

    You succesfully managed to retrieve the title start date and end date. Any idea on how to retrieve the event_id?

    Also you have a small bug>>>>int l_colEnd = l_managedCursor.getColumnIndex(l_projection[1]);>>>It should be index 2

    Thanks
    again

  4. Hi, but how do I create/ add a local calendar?

    To work with your codes you need a calendar ID. How do you create a calendar and get its ID?

    Thanks

  5. Hi, great tutorial. One question – How do I start the calendar intent to edit an EXISTING event – i.e. so it pops up with the event details showing – I pass in the eventId as described in various documentation but can’t get it to work – having great trouble getting this to work! Any hints or ideas welcome. Also – as the Google stats show that about 90% of devices are on an API lower than 14 this stuff is really useful. Most new devices are still being released with 2.3.3 on!!!
    Thanks
    Phil

    1. @coi,

      Well, it does work. Just not all of it. I was able to successfully get a list of calendars, I just can’t seem to get a list of the user’s events.

      And Coi, if your program is crashing, make sure you’ve setup the calendar on your emulator with an account. Otherwise, run it on a phone.

  6. thanks for the great tutorial. But i would like to ask you is there a way to detect if an event is added to the calendar from the calendar app on the mobile device. to explain more to you for example if the user open the calendar app on his mobile device (Usually the google calendar app) then he add the detail of the event and add the calendar event. i want to detect the newly added event and use this event. hope you could know
    thanks

  7. Hi I have downloaded your sample and trying to run but I am getting following error.

    04-28 15:19:17.013: E/ActivityThread(469): Failed to find provider info for com.android.calendar

    So far I have made sure, I have correct API level (8) in project properties selected. Also I have Google Account added on my emulator. Am I missing anything?
    Seems to me that com.android.calendar provider is no more supported in Google API Level 8? I have also tried running on most recent API Level 15. But error remains same.
    Any suggestions?
    Running Environment
    Win-7, Eclipse IDE
    – Can run most of the Google Samples on my current setup.

    Thanks

  8. ContentValues event = new ContentValues();
    event.put(“calendar_id”, 2);
    event.put(“title”, strTitle);
    event.put(“dtstart”, convertDateStringtoLong(startDateTime));
    event.put(“dtend”, convertDateStringtoLong(endDateTime));
    event.put(“allDay”,0);

    Uri l_eventUri;
    if (Build.VERSION.SDK_INT >= 8 ) {
    l_eventUri = Uri.parse(“content://com.android.calendar/events”);
    } else {
    l_eventUri = Uri.parse(“content://calendar/events”);
    }

    Uri l_uri = _activity.getContentResolver().insert(l_eventUri, event);

    Log.v(“++++++test”, l_uri.toString());//05-03 13:27:36.868: V/++++++test(7615): content://com.android.calendar/events/7934

    I am able to see the Event been posted to “content://com.android.calendar/events/7934”

    when I go to the Calendar I don’t see any Event added to the Calendar… the _activity is the one which I am passing it from the WebContainerActivity

  9. Thanks for the wonderful tutorial……
    Is there any way we can remove the Guest field which is there in the Add Event 2 … I tried with the removeExtra it did not worked either…

  10. Can you modify this to show a specific calendar that is not owned by the end-user? Say myBusiness puts out there app and wants myBusiness’s google calendar to do the lastThreeFields method in their app.

    1. Official google calendar API is available since Android 4. Oficially there is no calendar on previous versions so an emulator wont support one. However many manufacturers made a calendar be themselves, but U have to use a real device to debug it.

  11. Hi, i have to run tutorial on elipse android emulator but i got this message “… has stopped unexpectedly” what have i done wrong? i really want to run it and see because i’m doing a similar project and thought this will help me a lot. someone help me pls. thanks in advance.

  12. Hi, i have try to run the tutorial on elipse, android emulator but i got this message “… has stopped unexpectedly” what have i done wrong? i really want to run it and see because i’m doing a similar project and thought this will help me a lot. someone help me pls. thanks in advance.

  13. hi, i am trying to built a project in android that is a calendar app but instead of adding events to the calender. Can we implement video attached to each date in which we desire so that we can keep our memorable days for ever..

  14. Thanks a lot for this tutorial really helped. but on running i get a force quite error. Help pls. I’m just a beginner with android. thanks

  15. Hi, i have try to run the tutorial on eclipse, android emulator but i got this message “Unfortunately,CalenderOps has stopped”.
    Tel me how to run these code

  16. Hi. I am getting this error:
    SDK_INT cannot be resolved or is not a field
    in this line:
    if (Build.VERSION.SDK_INT >= 8)

  17. Hi,
    I am running the above code on Android 4.3 device. And I am getting the below error message,

    Invalid column displayName

    Could you please let me know how to resolve this. Thanks for your help.

  18. It force closes on an ICS (4.0.4) device and in the lowest API emulator (2.2) I use (I still didn’t try to install a CalendarProvider here, maybe that would solve the issue). I guess that on devices running an OS > 4.0 (API level 14+), it will miserably fail…

  19. Hello, I am running the above code on Android 4.4.4 device. And I am getting the below error message,

    Invalid column displayName in the below line
    Cursor l_managedCursor = this.managedQuery(l_calendars, l_projection, null, null, null);

    Now please tell me what should i do ?
    Thank you for your help.

Leave a Reply

Your email address will not be published. Required fields are marked *