Accessing the internal calendar database inside Google Android applications

The Android phone operating system provides close integration with three excellent services from Google; email, address book and calendar. In addition it has a thriving third party app scene with a great variety of free and commercial applications on the Market. In theory this should mean that apps can provide new services to the user based on the Google service data they have already synced on the phone.


However in the case of calendar data this has proven a bit tricky. Google provide an API to access calendar data via the internet, and this can be used directly from Android apps. Unfortunately this also requires a working data connection, time and battery life to get at the data. In addition it will need the app to prompt for the user’s credentials (user name and password).


All this seems unnecessary when the data you want is right there on the phone already. Since there is an API that any application can use to access the user’s contact (address book) data directly on the phone without going to the internet. It’s called android.provider.Contacts and is documented here. So why doesn’t android.provider.Calender exist?


The answer


The answer is that is does exist – although it is not documented, and it is not included with the standard Google Android SDK. It is a little-known fact that it is possible to download the Android source, force the provider classes to be included by removing the @hide annotation that protects it, and make your own version of the SDK. This can be compiled against apps from which calendar queries can then be made.


This is how I originally built my app Quick Calendar – a ‘lite’ read only version alternative to the built-in calendar application released early 2009. This uses the same data used by the built-in calendar application, already synced onto users’ Android phones. Judging by my inbox it’s been the most popular hobby application I’ve ever put out. I’ve since had a number of inquires from other developers as to how I managed get at the internal calendar data on Android.


Firstly I would say that getting at the data by a custom-build SDK is possible but awkward. For one thing it is a pain keeping up to date with the latest changes and staying in sync with the Android Eclipse plug in.


The good news is you don’t actually need to use the calendar provider SDK classes to get at the data. Android exposes data across applications by using a feed system similar to web-based feeds, and query syntax similar to SQL. As a result, provided your app has the correct user permission (android.permission.READ_CALENDAR) you can query the database from the names, and continue to use standard SDKs such as 1.5 or 1.6. In the absence of specific SDK support for calendars, it’s only slightly less convenient to directly use the provider’s internal URIs (e.g. “content://calendar/calendars”) directly.


Warning


At this point I should point out that there’s a reason why Google haven’t officially exposed the internal calendar APIs. This is probably because they anticipate future changes to the calendar format. Once they’ve published an SDK the formats are to some extent set in stone and they’d like to avoid that. In my experience the formats have been stable since I first discovered the feed. However, don’t be surprised if future firmware changes break any apps that use the feed. In this event you’ll have to update your app and re-upload it to the Market. It’s not that big a worry, certainly not enough to avoid using this great feature – the ability to present users’ calendar data in new ways to them.


Example


I’ve uploaded an example project to http://svn.jimblackler.net/jimblackler/trunk/workspace/AndroidReadCalendarExample. All the calendar reading code is in http://svn.jimblackler.net/jimblackler/trunk/workspace/AndroidReadCalendarExample/src/net/jimblackler/readcalendar/Example.java.


To read the calendar data in your own app firstly add android.permission.READ_CALENDAR under <manifest> in your application’s AndroidManifest.xml.


Please note that you will probably have to use a real phone to test your app in development, because the emulator included with the SDK does not include the Google services (there will simply be no calendar database present to query).


Then get an android.content.ContentResolver and make a query to content://calendar/calendars to enumerate all the available calendars
on the phone. The ‘_id’ column will give you the calendar’s ID (referenced in events). You can get rough documentation of all the columns supported by looking at core/java/android/provider/Calendar.java. (As mentioned previously, this file is part of the public open source Android project but is not part of the official Android SDK from Google)

  1. ContentResolver contentResolver = context.getContentResolver();
  2.  
  3. final Cursor cursor = contentResolver.query(Uri.parse("content://calendar/calendars"),
  4.         (new String[] { "_id", "displayName", "selected" }), null, null, null);
  5.  
  6. while (cursor.moveToNext()) {
  7.  
  8.     final String _id = cursor.getString(0);
  9.     final String displayName = cursor.getString(1);
  10.     final Boolean selected = !cursor.getString(2).equals("0");
  11.    
  12.     System.out.println("Id: " + _id + " Display Name: " + displayName + " Selected: " + selected);
  13. }

Once you have a calendar ID you can use your ContentResolver object to obtain the events from that calendar. Note how a ‘where’ clause of ‘Calendars._id=??’ is employed to fetch only events of that particular calendar. This clause could query whichever columns your app required, using an SQL-like syntax. Note also how the Uri.Builder was used to build up a URL including date bounds for the query.

  1. Uri.Builder builder = Uri.parse("content://calendar/instances/when").buildUpon();
  2. long now = new Date().getTime();
  3. ContentUris.appendId(builder, now - DateUtils.WEEK_IN_MILLIS);
  4. ContentUris.appendId(builder, now + DateUtils.WEEK_IN_MILLIS);
  5.  
  6. Cursor eventCursor = contentResolver.query(builder.build(),
  7.         new String[] { "title", "begin", "end", "allDay"}, "Calendars._id=" + id,
  8.         null, "startDay ASC, startMinute ASC");
  9.  
  10. while (eventCursor.moveToNext()) {
  11.     final String title = eventCursor.getString(0);
  12.     final Date begin = new Date(eventCursor.getLong(1));
  13.     final Date end = new Date(eventCursor.getLong(2));
  14.     final Boolean allDay = !eventCursor.getString(3).equals("0");
  15.    
  16.     System.out.println("Title: " + title + " Begin: " + begin + " End: " + end +
  17.             " All Day: " + allDay);
  18. }

Note that all dates in the calendar format are stored as UTC (the number of milliseconds that have elapsed between midnight 1st January 1970 and the event in Greenwich UK).


This is the basics of calendar access on Android. I haven’t covered all the columns (these can be seen in the SDK source linked above) and I haven’t covered modification. Notheless I hope this information allows other developers to build great calendar-aware apps for Android. Please do leave queries in the comments here, and if you use this information to make an app please do tell us about it in the comments here.


Update


To access the Corporate Calendar on Motorola devices, use “content://calendarEx” in place of “content://calendar”.


Update 2


For Android devices using 2.2 (Froyo) or greater, where previously you had content://calendar you should write content://com.android.calendar

  1. Pierrot’s avatar

    Is it possible to create/modify events in the built-in calendar?

  2. Mike’s avatar

    How timely! Just what I have been looking for. Thanks for taking the time to document

  3. jimblackler’s avatar

    I expect you can add/modify by the feed but I haven’t had to do this myself so not worked it out. I would look at what the documented providers do (e.g. the contacts provider) for reference.

    Alternatively if it is a low volume of events it may be best to use activities to get the user to confirm the add/modify manually. I do this in my BBC Listings application.

  4. Joe’s avatar

    Excellent! Thanks for the rundown, you’ve saved me a lot of pain…

  5. Matt’s avatar

    Is there a way to run this example in the SDK’s emulator? For me it fails here:

    final Cursor cursor = contentResolver.query(Uri.parse(“content://calendar/calendars”), …);

    returning “null” everytime.

  6. jimblackler’s avatar

    Matt, I don’t know if there are any publicly available Android emulators that support Google Calendar. Without a calendar on the phone, there is no service to query.

  7. Jason’s avatar

    I know it’s asking a lot, but could you create a “quick add” event app.
    I used a Palm Treo 650 before my Droid, and the day-view of the Palm’s calendar was used more than the phone portion.

    I constantly check, add, reschedule events on the calendar. And it has notification events (with defaults for alert tone/vibrate and time before event)

  8. jimblackler’s avatar

    Hi Jason, did you know if you long click on the day title in the event list in QC that it prompts you to add an event on that day?

  9. Ram’s avatar

    Hi Jim,

    Thanks for the beautiful write-up and the code. I have a quick question. Is it possible to query the Calendar database with event’s creation time/date? If yes then could you please tell how.

    Also, I am capturning the change notifications from calendar using the ContectObserver but my problem is how do I distinguish if it’s add event or delete event?

    Thanks in advance for your help.
    -Ram

  10. jimblackler’s avatar

    Re. your first question, I haven’t had to do that, but have you looked at the available columns in the source for the CalendarProvider, as linked in the article?

    Re. the second question I haven’t used the class you mention so cannot advise there.

  11. Ray’s avatar

    Hi Jim,

    I want to write a calendar app which can read and write meetings.
    Is there any possibility to get a calendar app like your ‘Quick Calendar’ run in the Android SDK to set some “example meetings”? When I install your app on my SDK i get every time the error: “The application Calendar Storage (process com.android.calendar) has stopped unexpectedly. Please try again.” Don’t know how to solve, so you’re my last chance! :-)

    Thank you in advance for your help!
    Ray

  12. jimblackler’s avatar

    Hi Ray

    Can you run the built-in Google Calendar application on the device? Usually called “Calendar” in the applications selector.

    Also could you let me know which device you have?http://jimblackler.net/blog/wp-admin/edit-comments.php?p=151#comments-form

    Jim

  13. Ram’s avatar

    thanks Jim.

    Another question please. How to update or delete the calendar entries? Could you please mention how the query looks like?

    Thanks,
    -Ram

  14. Ray’s avatar

    Hi Jim,

    I don’t have any Android device to test my programs. I can only test them with the Android emulator, but emulator has a calendar app installed. I tried to install the calendar with the Calendar.apk from http://code.google.com/p/android/issues/detail?id=1389 and the CalendarProvider.apk but when i click on the icon the same error comes.
    Currently I’m using Android 2.0 emulator. I alredy tried it with 1.5 and 1.6, but everytime with the same error!

    Greetings
    Ray

  15. tibo’s avatar

    If you want to write events to a calendar you can follow this tutorial [->http://android.arnodenhond.com/tutorials/calendar%5D

  16. Varun’s avatar

    Hi Jim,

    I am new to android and I was trying to use Android’s Native Calendar.
    Thanks for an excellent write-up.

    I had couple of questions regarding the usage of the native calendar.

    I am trying to build an application which can interact with the calendar to add/edit/delete events from the native calendar.

    In your blog you are talking about reading the events from the calendar. Is it possible to perform the CRUD operations on the native calendar using ContentProviders alone ?

    Thanks in advance,
    Varun

  17. jimblackler’s avatar

    > Is it possible to perform the CRUD operations on the native calendar using ContentProviders alone ?

    I believe it is although I prefer to write events through Intents myself (this gives the user a chance to confirm the calendar event before adding).

  18. Sean Neilan’s avatar

    Dear Jim,

    I am trying to get this to work with android sdk 2.0.1. I had put the Example class from your project into my standard android project & it didn’t work. I noticed that there wasn’t a Calendar class in the Android.jar file in eclipse.

    Is it possible that I need to recompile the android 2.0.1 sdk and include the calendar class?

    Should I be using a different android sdk?

    Thank you for time,

    Sean

  19. jimblackler’s avatar

    You shouldn’t have to rebuild the SDK no. The point of this technique is that it doesn’t actually require the Calendar classes.

  20. Sean Neilan’s avatar

    Is it possible that it doesn’t work with android sdk 2.0.1? Which android sdk did you use?

  21. Sean Neilan’s avatar

    Actually, I think I meant which version of the android OS you used because the phone I am running has android 2.0.1 on it. There’s no way to debug this inside of the emulator so I’ll have to reflash my phone if necessary.)

    Is there a way to find the sqlite file itself perhaps?

    Please excuse me for asking so many questions. I thank you very much for your time in this.

  22. lauren’s avatar

    thank you! this was very helpful.

  23. Mo’s avatar

    Hi Jim,

    Fantastic blog. Can you give me an advice on what I need to extract events from calendar instead of the calendar as a whole. Am planning to build an application which pulls events from the phone calendar then send it as sms messages to contacts.

    Many thnx

  24. jimblackler’s avatar

    Hi Mo

    The demo shows querying of all events in a given time range.

    You can add sqlite SELECT terms to the query to query on any columns you choose.

    Jim

  25. Matt’s avatar

    I can’t get this working. I’ve downloaded the source code and compiled and run on my g1 to no avail. I’ve downloaded your quickcalendar app and that works fine… any ideas,

  26. Matt’s avatar

    Well it works but it just shows a blank screen with the app title. I have also set up multiple appointments for the week to test…

    Any ideas, this would really help.

    I have a G1 running stock android 1.6

    thanks

  27. jimblackler’s avatar

    Matt, look at the console log output. It’s not a fully working application, it just shows how the calendar information can be read, which is written to the console rather than the phone screen.

  28. Matt’s avatar

    Perfect, don’t believe i didn’t read the code properly. thanks. For some reason my console isn’t outputting anything so i sightly modified and used a textview to output. Now all i have to work out is why i can’t write to the calendar even though permissions are added (any ideas on that one will be much appreciated :) )

    Thanks again

  29. Alberto’s avatar

    Hi Jim, great blog post. I’d been looking for something like this for a while. Would you happen to know if it’s possible to do this with Gmail’s content provider as well to read e-mail? I made a first attempt but couldn’t get it to work but maybe you’ve had better luck?

  30. jimblackler’s avatar

    I haven’t looked into it Alberto. It’s an interesting question. You can often get a clue about that kind of thing by running ‘adb logcat -d’ on a USB connected PC with SDK, using the app you are interested in and watching the log output. It may well give content provider URLs in the output.

  31. Alberto’s avatar

    Thanks, I’ll give that a try. There’s a new app called Slide Screen that just came out that’s displaying both calendar info as well as Gmail so I imagine they must be using a similar method to what you described here. I’ll let you know if I’m able to make progress. If anyone’s got this working (Gmail) please let us know!

  32. Laurent’s avatar

    Thanks Jim :)

    What about corporate calendar? is that just using a different Uri for the query?
    I’d like to make a small app that registers my visits to customers…
    I did that on windows mobile but I cannot find out how to do it on android :(

  33. Richard Sewell’s avatar

    Jim – can you share anything the Intents you use to add calendar events ? I couldn’t see those in your example.

    I’ve tried adding events from code, following
    http://android.arnodenhond.com/tutorials/calendar
    and
    http://www.developer.com/ws/article.php/3850276/Working-with-the-Android-Calendar.htm

    While I did manage to add events, I also broke my Google Calendar in a way which means that it won’t sync to the cloud any more. Also, I can no longer edit my calendar via the Web interface. Apparently it is waiting for a human at Google to review it!

    That made me a little nervous about adding events directly to the database, so I am hoping to find a safer way…

  34. jimblackler’s avatar

    Sure Richard… try this.


    Intent intent = new Intent(Intent.ACTION_EDIT);
    intent.setType("vnd.android.cursor.item/event");
    intent.putExtra("beginTime", startTime);
    intent.putExtra("endTime", startTime + duration);
    intent.putExtra("title", title);
    intent.putExtra("eventLocation", location);
    intent.putExtra("description", description);
    startActivity(intent);

    Adding events by intent has limitations and advantages.

    Limitations: Only one event at a time, requires user to approve each one.
    Advantages: Doesn’t require a permission flag in the application, user has the chance to modify the event and select calendar the to use.

  35. Richard Sewell’s avatar

    Jim – thanks – that’s perfect. And (I hope) it will be harder to break the calendar database with that approach.

    Did you ever stray into creating repeating events, by the way ?

  36. arnold’s avatar

    Jim – thanks for the clear blog..

    You say it’s possible to build a android.jar with the calendar.
    This would be very helpfull for me to build a app.

    But i keep solving errors when i remove the @hide in the calendarprovider.
    And i can’t seem to find much on that item on the web.

    Can you sent me in the good direction with this..or do you maybe have a android.jar with the calendar class?

    Thanks.

  37. John’s avatar

    Thanks for posting this, it really was helpful when I started integrating my project with the android calendar. I found a few other helpful sources as well, and have compiled a “wrapper” class to wrap the calendar in a more usable way.

  38. Craig’s avatar

    First, I REALLY appreciate your tutorial. It made all the difference in the world on my latest app.

    Something I’ve found worth mention.. Your tutorial, as it stands, worked great on my Motorola Cliq, but I was getting bug reports from all over, so after a lot of tracking, I figured out that it’s a good practice to also look for the value “name” in addition to “displayName”. “displayName” seems to be optional, so I have my code look for both and go with whatever it finds.

    ContentResolver contentResolver = this.getContentResolver();
    final Cursor cursor = contentResolver.query(Uri.parse(“content://calendar/calendars”),
    (new String[] { “_id”, “displayName”, “name”, “selected” }), null, null, null);

    String myDisplayName=”NONE”;
    String myCalName=”NONE”;

    while (cursor.moveToNext()) {
    final String _id = cursor.getString(0);
    final String displayName = cursor.getString(1);
    final String calName = cursor.getString(2);
    final Boolean selected = !cursor.getString(3).equals(“0”);
    if (displayName.contains(“gmail.com”)) { useCalId=_id; myDisplayName=displayName; myCalName=calName; }
    if (calName.contains(“gmail.com”)) { useCalId=_id; myDisplayName=displayName; myCalName=calName; }
    if (selected) { useCalId=_id; myDisplayName=displayName; myCalName=calName; }
    if (Debug) { Log.i(“DEBUG”, “totalCals: “+String.valueOf(totalCals)+” CalId: “+String.valueOf(_id)+” Calendar: “+displayName+” CalName: “+calName+” selected: “+String.valueOf(selected)); }
    }

    And once again, thank you VERY much for getting me off in the right direction!

    – Craig
    SweetMerch.com

  39. Aleksey’s avatar

    Jim, echoing everyone here once more; THANKS for the hard work you put into this tutorial.

    I’m having some trouble getting your code to run on my Motorola CLIQ (v1.5). I checked out your AndroidReadCalendarExample from your SVN, “tethered” my CLIQ and launched your code. I am getting the following errors from the console though:

    [2010-03-05 00:34:51 – AndroidReadCalendarExample]Starting activity net.jimblackler.readcalendar.MainActivity on device
    [2010-03-05 00:34:52 – AndroidReadCalendarExample]ActivityManager: Can’t dispatch DDM chunk 46454154: no handler defined
    [2010-03-05 00:34:52 – AndroidReadCalendarExample]ActivityManager: Can’t dispatch DDM chunk 4d505251: no handler defined
    [2010-03-05 00:34:53 – AndroidReadCalendarExample]ActivityManager: Starting: Intent { comp={net.jimblackler.readcalendar/net.jimblackler.readcalendar.MainActivity} }

    These are the last four lines from the console, so somehow it is not reading the calendar correctly.

    Thanks in advance,
    Aleksey

  40. Kyle’s avatar

    John – great helper class, thank you. Although, I was wondering if you could either parse it down a little or provide the rest of the code for it…not having all of the imports makes it a little challenging. Also, what build of the SDK did you use for this?

    Thanks
    -Kyle

  41. Kyle’s avatar

    One other question for John…what is the CalendarListItem class around line 185? Is that something in the SDK or within your project?

    – kyle

  42. Rajeev’s avatar

    Hi Jim,

    Many thanks for this forum and it has been extremely useful to me. Thank you.

    This would be very useful to me now – Can you provide detailed description on creating a new calendar (and not events) on a device and getting it sync-ed with the google cloud ? What has been your experience with Google api on this front as well ?

    many thanks once again,
    rajeev

  43. Michael  Saunders’s avatar

    Jim,

    Great article. I really appreciate you providing this Calendar example and blog. Has your employer OKed the release of the source code for QuickCalendar yet? It would be really helpful to see the source code of a full application.

    Thanks,
    Michael

  44. Ken Hughes’s avatar

    Great article. Been wanting an app to turn off my phone ringer when in certain meetings, now I can write one.

  45. Jeffrey Karp’s avatar

    My HTC Eris did an update today to 2.1 – I didn’t have a backup of my calendar but I see that my calendar storage has 13.5 MB so I assume my data is still there – is there a way for me to access this?

  46. Jeffrey Karp’s avatar

    meant to add that I can’t access my calendar…

  47. John’s avatar

    Hey Kyle, I’ve worked with that piece of code quite a bit since I originally posted on here.

    CalendarEventItem was just a small class to hold the name of a calendar and it’s id.

    That is the entire class, and I cannot at this time post any more of the project.

    However, I can post a few examples of how it is used if you want although it’s pretty self explanatory.

    1 Thing I cannot figure out though is how to get a reminder to be used. I just can’t get it to use a reminder =[

  48. Tim’s avatar

    Hi Jim, thanks for the article. I used it when I was researching my own calendar widget app. Unfortunately, it looks like the Froyo release has changed the URI we need. Do you or does anyone else know what changes are needed to get our apps to work on Froyo?

  49. moamen’s avatar

    hello Jim, please provide us with help for froyo calendar
    i’m working in my app for my nexus one to add events to calendar but from now i don’t know how to move forward

    thanks for your help and wish we receive more

  50. moamen’s avatar

    i can provide you with the calendar 2.2 from my phone in case it will help

1 · 2 · 3 ·

Reply

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