Android’s CalendarContract Content Provider

Android developers have been longing for an official Calendar app and content provider since Android has been released. With the release of Ice Cream Sandwich Google has finally added this feature to our tools list. Now we developers can use the Calendar app from within our Activities using Intents or we can access the data by making use of the new CalendarContract content provider.

CalendarContracts entities

Before I explain how to use the calendar I first present the calendar’s data model. It consists of calendars, events, event instances, event attendees and reminders.

First we obviously have calendars. The plural is no accident, because each user can manage multiple calendars on her device. For example her personal calendar, her work calendar, a calendar of her colleague and one for her sports team. Android uses colors to distinguish between different calendars in the Calendar app:

Events of multiple accounts

Events of multiple accounts


Account selection when adding an event

Account selection when adding an event

For each calendar you can have multiple events. But each event belongs to exactly one calendar only. If the event is visible twice (e.g. in the private and in the business account of the user), the event is stored twice, each belonging to their respective calendars.

Many events are recurring. So in addition to events there are also event instances. An instance represents the specific event that takes place at just this one point in time. For a single event Android creates one instances entry, for recurring events Android creates as many instance entries as there are occurrences of this event.

Events can of course have multiple attendees as well as multiple reminders.

Furthermore the data model contains some helper tables that are only relevant for sync adapters. I don’t deal with these in this blog post.

What’s weird is that attendees belong to the event and not to the event instances. What happens if users want to cancel one instance of a recurring event? What if they want to add an attendee for just one event? For example changing the speaker of a recurring User Group talk? The solution chosen here is that another entry is added to the events table with the field Events.ORIGINAL_ID referring to the id of the base event. This is also the case for event instances for which only the time has changed – even though this information is already part of the instances table.

What are sync adapters

Sync adapters sync data of specific accounts to a backend. Sync adapters are usually an integral part of the app, that needs them. Thus users usually do not install them on their own.

In this blog post I do not deal in detail with sync adapters. But you should know that sync adapters possess more privileges and can access more tables and fields than normal apps. The most important privilege is that only sync adapters can create calendar accounts.

Of course a sync adapter has these privileges only for its account type. An adapter cannot mess with the privileged data of another account.

Sync adapters don’t deal with calendar data alone. They also sync contact data or any data specific to your app that has to be synchronized between the device and a backend.

You can find a list of available sync adapters in your Settings app in the section “Accounts”:

Sync adapters in the settings app

Sync adapters in the settings app

Using your Google Calendar within the emulator

To test your calendar-related code within the emulator, you first need to have a calendar. The best is to sync with an existing calendar of yours – and the easiest way to do this, is to sync with your Google calendar.

I have written another post that explains how to sync with your Google Calendar.

The Calendar content provider

To use the Calendar content provider you need to declare the necessary permissions within your manifest file first:

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

Keep in mind that the Calendar is part of the official API only from Ice Cream Sandwich onwards. The constants, defined in CalendarContract and its many inner classes are not available prior to API version 14. All code samples shown here need an API-level of 14 or higher as build target and the value for the android:minSdkVersion attribute of the <uses-sdk> element in the manifest file.

The content provider itself probably is available on older versions – though you cannot rely on this. For more on this see the section Calendar-usage before Ice Cream Sandwich.

Accessing calendars

If your app doesn’t act as a sync adapter chances are that you never have to deal with the calendars itself. Other than query for the correct id that is. The thing you are most likely to do is add, delete or change events. But for this you need to know to which calendar to add the event.

So let’s start by reading all calendars that are available on a device:

String[] projection = 
      new String[]{
            Calendars._ID, 
            Calendars.NAME, 
            Calendars.ACCOUNT_NAME, 
            Calendars.ACCOUNT_TYPE};
Cursor calCursor = 
      getContentResolver().
            query(Calendars.CONTENT_URI, 
                  projection, 
                  Calendars.VISIBLE + " = 1", 
                  null, 
                  Calendars._ID + " ASC");
if (calCursor.moveToFirst()) {
   do {
      long id = calCursor.getLong(0);
      String displayName = calCursor.getString(1);
      // ...
   } while (calCursor.moveToNext());
}

Of course you can also change calendars using the content provider. But here it starts getting tricky. That’s because apart from reading data, the access to calendars is limited. Sync adapters can do pretty much anything with calendars they own, but normal apps cannot do much at all. Of course they cannot delete calendars, but they also cannot create calendars. They only can change some trivial values like the name of the calendar.

There is one exception to this rule: You can create local calendars that do not get synced. So the following code shows how to create a local calendar which you will use later on for manipulating events:

ContentValues values = new ContentValues();
values.put(
      Calendars.ACCOUNT_NAME, 
      MY_ACCOUNT_NAME);
values.put(
      Calendars.ACCOUNT_TYPE, 
      CalendarContract.ACCOUNT_TYPE_LOCAL);
values.put(
      Calendars.NAME, 
      "GrokkingAndroid Calendar");
values.put(
      Calendars.CALENDAR_DISPLAY_NAME, 
      "GrokkingAndroid Calendar");
values.put(
      Calendars.CALENDAR_COLOR, 
      0xffff0000);
values.put(
      Calendars.CALENDAR_ACCESS_LEVEL, 
      Calendars.CAL_ACCESS_OWNER);
values.put(
      Calendars.OWNER_ACCOUNT, 
      "some.account@googlemail.com");
values.put(
      Calendars.CALENDAR_TIME_ZONE, 
      "Europe/Berlin");
values.put(
      Calendars.SYNC_EVENTS, 
      1);
Uri.Builder builder = 
      CalendarContract.Calendars.CONTENT_URI.buildUpon(); 
builder.appendQueryParameter(
      Calendars.ACCOUNT_NAME, 
      "com.grokkingandroid");
builder.appendQueryParameter(
      Calendars.ACCOUNT_TYPE, 
      CalendarContract.ACCOUNT_TYPE_LOCAL);
builder.appendQueryParameter(
      CalendarContract.CALLER_IS_SYNCADAPTER, 
      "true");
Uri uri = 
      getContentResolver().insert(builder.build(), values);

Now this code needs some explaining. First of all I create a ContentValues object that represents the values we want to add. This is the normal way to add data to a content provider. Here I add a name, the color for displaying this calendar’s data, the account it belongs to and its access rights. I also add a default time zone.

But what is not normal with the code shown above are the additional query parameters the calendar provider expects. These indicate to the provider that this code acts as a sync adapter and for which account type and account name it does this. Here the account type is ACCOUNT_TYPE_LOCAL – so this calendar will not be synced. Any other type would have to be accompanied by a full-fledged sync adapter.

Adding events using the content provider

While you cannot do anything without having at least one calendar first, you most likely want to create, change or delete events.

Since all events belong to a calendar account, I use this helper method to get the calendar id for the local calendar created in the previous section:

private long getCalendarId() { 
   String[] projection = new String[]{Calendars._ID}; 
   String selection = 
         Calendars.ACCOUNT_NAME + 
         " = ? " + 
         Calendars.ACCOUNT_TYPE + 
         " = ? "; 
   // use the same values as above:
   String[] selArgs = 
         new String[]{
               MY_ACCOUNT_NAME, 
               CalendarContract.ACCOUNT_TYPE_LOCAL}; 
   Cursor cursor = 
         getContentResolver().
               query(
                  Calendars.CONTENT_URI, 
                  projection, 
                  selection, 
                  selArgs, 
                  null); 
   if (cursor.moveToFirst()) { 
      return cursor.getLong(0); 
   } 
   return -1; 
} 

In addition to this calendar id you also have to add at least the following fields in order to create events:

  • Each event must have a time zone – even if the calendar account has a default time zone anyway
  • An event must have a start date
  • The event must either have an end date or a duration, but must not have both at the same time.

Actually the last rule is very strange. Duration in this case is not the duration of a single event. Instead it is the time span used to determine the last event of recurring events. So for single events a duration makes no sense at all. Also I consider it odd that you have to include these fields even for all-day events. But well, it’s not too hard to add them. So just be warned.

The following snippet shows how to add an all-day event:

long calId = getCalendarId();
if (calId == -1) {
   // no calendar account; react meaningfully
   return;
}
Calendar cal = new GregorianCalendar(2012, 11, 14);
cal.setTimeZone(TimeZone.getTimeZone("UTC"));
cal.set(Calendar.HOUR, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
long start = cal.getTimeInMillis();
ContentValues values = new ContentValues();
values.put(Events.DTSTART, start);
values.put(Events.DTEND, start);
values.put(Events.RRULE, 
      "FREQ=DAILY;COUNT=20;BYDAY=MO,TU,WE,TH,FR;WKST=MO");
values.put(Events.TITLE, "Some title");
values.put(Events.EVENT_LOCATION, "Münster");
values.put(Events.CALENDAR_ID, calId);
values.put(Events.EVENT_TIMEZONE, "Europe/Berlin");
values.put(Events.DESCRIPTION, 
      "The agenda or some description of the event");
// reasonable defaults exist:
values.put(Events.ACCESS_LEVEL, Events.ACCESS_PRIVATE);
values.put(Events.SELF_ATTENDEE_STATUS,
      Events.STATUS_CONFIRMED);
values.put(Events.ALL_DAY, 1);
values.put(Events.ORGANIZER, "some.mail@some.address.com");
values.put(Events.GUESTS_CAN_INVITE_OTHERS, 1);
values.put(Events.GUESTS_CAN_MODIFY, 1);
values.put(Events.AVAILABILITY, Events.AVAILABILITY_BUSY);
Uri uri = 
      getContentResolver().
            insert(Events.CONTENT_URI, values);
long eventId = new Long(uri.getLastPathSegment());

If you add an event in this way, you have not yet created any alarms or set any attendes. You will have to do so in an extra step and you have to use the id of this event to do so. I will show how to add attendes and alarms later on. In preparation for this I have already extracted the id of the event.

For a lot of fields reasonable default would be inserted if you left them out. The code shown here uses them anyway so that you know what you can do and how to do it.

Since the underlying datastore doesn’t suppport boolean values, the provider uses 1 for true and 0 for false. A common practise in Android when SQLite is involved. As you can see, I’ve set the values of ALL_DAY, GUESTS_CAN_INVITE_OTHERS and GUESTS_CAN_MODIFY to true.

The value of the rrule field looks a bit strange. First the name: “rrule” is short for recurrence rule and defines how recurring events should be inserted. In this case the rule states that the event should be repeated on every weekday for the next twenty days. The values for the recurrence rule as well as for the duration have to be given in an RFC 5545 compliant format.

Alas, the RFC formats for the duration and the recurrence rule are less than obvious. Believe me: You do not want to know the detailed rules for the recurrence format. This part of the specification alone is eight pages long and Google’s class EventRecurrence, representing and parsing those rules, is about 900 lines long. Explaining these formats is way beyond the scope of this blog post!

Reading, updating and deleting events

Getting more information about an event is pretty simple. You just need the Events.CONTENT_URI and the appropriate selection. If – for example – you know the event id you can access the event like this:

long selectedEventId = // the event-id;
String[] proj = 
      new String[]{
            Events._ID, 
            Events.DTSTART, 
            Events.DTEND, 
            Events.RRULE, 
            Events.TITLE};
Cursor cursor = 
      getContentResolver().
            query(
               Events.CONTENT_URI, 
               proj, 
               Events._ID + " = ? ", 
               new String[]{Long.toString(selectedEventId)}, 
               null);
if (cursor.moveToFirst()) {
   // read event data
}

Sometimes you want to find out more about events of the device owner. E.g. a concert planning app could have a look at the users calendar and check that she is free that evening. That’s what the next code snippet does. It checks if any event instances exist between a starting point and an ending point in time.

long begin = // starting time in milliseconds
long end = // ending time in milliseconds
String[] proj = 
      new String[]{
            Instances._ID, 
            Instances.BEGIN, 
            Instances.END, 
            Instances.EVENT_ID};
Cursor cursor = 
      Instances.query(getContentResolver(), proj, begin, end);
if (cursor.getCount() > 0) {
   // deal with conflict
}

Updating and deleting events are pretty easy tasks to accomplish. To delete you simply need the id of the event you want to delete:

String[] selArgs = 
      new String[]{Long.toString(selectedEventId)};
int deleted = 
      getContentResolver().
            delete(
               Events.CONTENT_URI, 
               Events._ID + " =? ", 
               selArgs);

For updating you need a ContentValues object containing those elements that you want to change:

ContentValues values = new ContentValues();
values.put(Events.TITLE, "Some new title");
values.put(Events.EVENT_LOCATION, "A new location");
String[] selArgs = 
      new String[]{Long.toString(selectedEventId)};
int updated = 
      getContentResolver().
            update(
               Events.CONTENT_URI, 
               values, 
               Events._ID + " =? ", 
               selArgs);

Adding attendees and alarms

As I’ve mentioned above, inserting an event is not enough. You probably want to add attendees and alarms.

Both tables reference the events table by using the field EVENT_ID with the appropriate id.

As usual you need a ContentValues object to get this done:

// adding an attendee:
values.clear();
values.put(Attendees.EVENT_ID, eventId);
values.put(Attendees.ATTENDEE_TYPE, Attendees.TYPE_REQUIRED);
values.put(Attendees.ATTENDEE_NAME, "Douglas Adams");
values.put(Attendees.ATTENDEE_EMAIL, "d.adams@zaphod-b.com");
getContentResolver().insert(Attendees.CONTENT_URI, values);
// adding a reminder:
values.clear();
values.put(Reminders.EVENT_ID, eventId);
values.put(Reminders.METHOD, Reminders.METHOD_ALERT);
values.put(Reminders.MINUTES, 30);
getContentResolver().insert(Reminders.CONTENT_URI, values); 

As explained in another post, you probably would want to use the class ContentProviderOperation to do a batch operation. But to keep the sample code as easy to read as possible, I have chosen the simpler approach shown above.

Other data

Reading, updating or deleting any of the other elements is pretty much like the sample code for events. Only the CONTENT_URI and the possible columns are different. Those are well documented in the CalendarContracts API.

If you want to insert data into other tables you have to be careful though: Only SyncAdapters are allowed to add records to Colors, SyncState or ExtendedProperties. If your ignore this restriction your code will result in an IllegalArgumentException at runtime.

Furthermore you are not allowed to manipulate data of the instances table – even if you are a sync adapter. Android will take care of instances on its own whenever an event gets added, deleted or modified. The only thing you are allowed to do with instances is to query them.

What about older Android devices?

As mentioned, the Calendar app and the content provider have been introduced with Ice Cream Sandwich. Even though the market share of 4.x devices increases steadily, most devices out there are still 2.x devices. Does anything comparable exist for them as well?

Well, kind of. Of course nothing official existed prior to ICS and the emulator images for older devices didn’t and still don’t have a calendar app. But nearly every device has. Even the sources existed – though marked with the @hide annotation, so that you can’t use the classes (e.g. the final static fields for the columns) in your code.

This is a sign that Google regarded the code as yet not ready for prime time. Well, rightly so, since it is still buggy in places – though mostly in the app, as I will explain in my next post.

If you take a look at the Calendar content provider of Android 2.3.7 at grepcode you can see that the data model is pretty similar to the one of the current provider. If you diff older code and newer code you will notice how close both are. Most changes deal with the new table colors. Obviously any code that relies on this table is doomed to fail on older devices.

So can you simply act as if the provider had been around for ages? Well, no. You can’t! The code used in this tutorial would result in NoClassDefFoundErrors.

But, and this is the good news, the old provider can still be used for most tasks without too much changes. For this to work you mostly have to exchange all constants with their actual values.

Be very careful if you do so! You have to test vigorously and you risk running into problems if the values (column names, content uris and so on) should ever change. And be prepared for content providers that do not match this data model – you simply cannot rely on it. Try to isolate the critical parts as much as possible.

If you want to know more about accessing calendars prior to ICS, you should read the blog post of Jim Blackler about the old internal calendar database.

Wrapping up

In this part of the tutorial I have shown you how to use Android’s CalendarContract content provider.

Using the content provider you can add events or get information about the user’s events and you can also check for conflicting dates.

To make full use of the content provider you have to be a sync adapter. But using a device local calendar account you can also deal with calendars in many ways.

In the next part of this tutorial I am going to cover the Intents that are provided by the Calendar app. For some use cases they might be the better choice – but of course you have much more flexibility by using the content provider.

Share this article:

You can leave a response, or trackback from your own site.

46 Responses to “Android’s CalendarContract Content Provider”

  1. [...] Android's CalendarContract Content Provider | Grokking Android [...]

  2. very clear, thank you very much!!!

  3. James says:

    Hello,

    I’m still having problems with the section of code which tries to extract events from a selected Date Range.

    I never get any results returned.

    Do you have a complete example of said-procedure, showing just event retrieval?

    Many thanks, so far the clearest of the tutorials I’ve seen.

    Kind regards

  4. Michael says:

    Thanks so much for this!! Exactly what I needed…

    Cheers!

  5. Michael says:

    Would you be able to show me how to retrieve the alarms attached to an event?

  6. Don says:

    Is there a way to identify events across devices? Some sort of Uid?

    And is there a way to store information about the calendars and events in the providers if the app is not a sync adapter?

  7. Alexander Claesson says:

    Thanks man, a very good tutorial on the calendar. You helped me a lot on my first app that uses the calendar.

  8. Jacen says:

    Hi, Thanks for the tutorial. I have been looking for such a tutorial for a while dealing with content provider. Do you have the source code all wrapped up on github or something, would just like to see and learn from it.
    Thank you.

    • Not yet. I’m going to release sample apps more often from now on and will release the first sample on monday. But it will be on ActionViews. At some point in time the sample for CalendarContract will also be published. But not very soon, I’m afraid.

      Sources will be availaible either on bitbucket or on github. Haven’t decided yet, but right now I lean towards bitbucket.

      • Jason says:

        Hi,
        Thanks allot for the tutorial and your other tutorials, in regards to this do you know if it is possible to launch the Google calendar app and view only this local calendar with its associated events?

        Thank you once again.

  9. Eleve says:

    Hi Wolfram, thanks for the great tutorial, this really help me a lot!! Somehow I need to modify some of your code a bit as below for query the calendar._id in getcalendarid call before it stop complaint syntax error when SELECT _id…..in runtime.

    String selection = “((” + Calendars.ACCOUNT_NAME + ” = ?) AND (”
    + Calendars.ACCOUNT_TYPE + ” = ?))”;

    Thanks again and please keep on the good work!!!

  10. gabriel says:

    hey guys
    so, i have a question about the implementation. Where i put these codes in my android app(java, xml)?

  11. zattacks says:

    This is an excellent tutorial. Thank you very much!

    I’ve been experimenting with this and seem to have added duplicates of a calendar by mistake. Is there any way to programmatically delete these duplicated calendars on my device?

    • You can delete any data that you added yourself. But there is no magic trick you can apply here.

      The simplest would be to delete all calendars of the type that you created (probably ACCOUNT_TYPE_LOCAL) and simply recreate one calendar afterwards. Of course your events would be gone that way.

      Or you could query for all ids, iterate over the result set and delete all but the first or last one.

      If you have already added events to multiple calendars and you want these events to be available from just the one calendar, the solution would be a bit more involved.

  12. very help ful tutorial….
    THANK’S a lot…

  13. Lanny F. says:

    Great tutorial! It’s the clear, simple and works! Thanks!

  14. Markus V says:

    Hi,
    I have some problems with syncing the created events. When I use the code above (slightly modified to meet my requirements) I can create events, but they are only displayed in my calendar app on my phone and not synced to the web, too.

    Do you have any ideas what might be the problem?

    Thanks!

  15. Neha says:

    Nice tutorial, but I’m not sure how to get the event id

    • When you add an event you get the eventId as a result of this operation. its part of the return URI when inserting. See the code sample in the “Adding events using the content provider” section.

      Otherwise you would have to query for it. One way is to query the Events table using column values unique to this event. Or you could use the Instances query to get a list of instances. Those all contain an event id as well. See the relevant code sample in the post.

  16. xsknaix says:

    May I know where to put all the code snippets at? Under which class or which methods. And how to call them?

  17. Joe P. says:

    I’m currently trying to use this. the problem I’m having is regarding the CalendarContract.Events.SYNC_DATAXX fields. If I add to these fields when creating an event, I do so asSyncAdapter, and any values I add will not be synced.
    If, Afterward, I create another new event, but this time, not doing it as a sync adapter, the previous event will then sync, but not any of the SYNC_DATA fields.
    Does google calendar not sync any of these fields?
    Your help is greatly appreciated.
    Thanks

    • I’m not sure which data Google uses for synching, but those SYNC_DATA fields are sync adapter dependent. That is one adapter (say facebook) might use them, another (Google) might not. Which does and which does not, and which of the fields which one uses, is normally not published.

      Those fields are additional fields for sync adapters and specific to this adapter! Do not use them – unless you are using them for a sync adapter that you have written. Even if they work at one point in time, they might break later on when the sync provider changes the way it syncs. And you might even break an existing adapter by using values in the wrong way. So: Do not use them!

    • BTW: What do you want to achieve? Google (for example) only syncs data itself needs. So where would you like those synced events to show up? Most likely the best solution is to use an sync adapter of your own. See Udi Cohen’s excellent tutorial on sync adapters. And there is also a training section about sync adapters on the official page.

      • Joe P. says:

        I was hoping that Google would do the heavy lifting for me and sync all fields. Thats good to know.
        So I guess my best option for my application where I need these fields to hold data specific to my app, would be to write my own sync adapter, and host the calendars on my own server?
        I’m writing an app to handle tasks/projects. mainly i’m buiding it for myself to help me manage all of the different projects I have going on. I’m hoping that there are others that are in the same boat. Simplicity is the key here, and the amount of time to add a task should be minimal, or to change a priority. I’m going to tweak it as I go.
        Thank you for your reply, I appreciate you helping me along, and pointing me in the right direction.

        • If those events have to be in the calendar, than that’s your best bet. If you do not need them in the calendar, you could also use some custom database. My guess is, that you need one anyway, given your project description. You could then use cloud providers to sync data between different devices of the same user – e.g. by using json as an exchange format. Another option could be Google cloud save – but the size limit could very well pose a problem here.

  18. Christian says:

    Hi,
    Great tutorial. I use it and I create my calendar events without any problèm. Thank you very much! Now I want to display a list of these events on a activity. can you help me? Thanks

  19. Roma says:

    Thanks, very useful tutorial for me!

    I wrote easy wrapper to use functionality of Google calendar provider.
    But it is one problem..
    Is it possible to synchronize my created calendars with calendar in web? Cause I can synchronize my calendar and events only with calendar on android-phone, but they don`t go to web. And I don`t know how to fix it (and if it possible).

    Help me, if you can.
    Thanks.

  20. Aayushi Jain says:

    event is getting generate but locally in phone so how i can sync it it using sync adapter so that i will be able to see that event on desktop Google calendar

  21. Shrey says:

    An excellent tutorial… !

  22. Ribo says:

    I created a calendar with your code above but I had the strange behavior that a event won’t be visible if it is “too far” in the future and it is the first event “too far” in the future(e.g. a year).

    I don’t have these problems with the code from the first answer from:
    http://stackoverflow.com/questions/8881851/how-can-i-add-a-new-phone-calendar-to-android

    Do you know why this happens?

    • No, I have no idea. As far as I see it the only difference between the code is with the OWNER_ACCOUNT. And that is no boolean field (as suggested by the SO answer), but the mail address of the owner (as my code assumes). So I wonder why the other solution is working at all.

      Any other differences, I might have missed?

      • Ribo says:

        I’m not sure, but I think the line

        values.put(CalendarContract.Calendars.SYNC_EVENTS, 1);

        makes the difference.

        If I remove this line, the strange behaviour starts again.

        • Ah, right. Didn’t see that. You’re right, that should be present. So please add that line, but stick to the mail address with the OWNER_ACCOUNT.

          From the documentation of SYNC_EVENTS:

          Is this calendar synced and are its events stored on the device? 0 – Do not sync this calendar or store events for this calendar. 1 – Sync down events for this calendar.

          I will update the sample code. Thanks for pointing this out!

          • Swapnil Devikar says:

            By the way, in the function: getCalendarId(), I found that the selection string didn’t work so well for me. Please correct me if I am wrong, but I think that should read something like this:
            String selection = “((” + Calendars.ACCOUNT_NAME + ” = ?) AND (“+ Calendars.ACCOUNT_TYPE + ” = ?))”;

            But regardless, it was an excellent tutorial. Thanks for taking time to do this. It helped me a lot.

  23. aayush says:

    For an instance, i want to filter only the birthday events from the calendar.
    What should be my query then.

    • aayush says:

      This is my code:
      private Cursor mCursor = null;
      private static final String[] COLS = new String[]
      { CalendarContract.Events.TITLE, CalendarContract.Events.DTSTART};

      @Override
      public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.main);
      mCursor = getContentResolver().query(
      CalendarContract.Events.CONTENT_URI, COLS, null, null, null);
      mCursor.moveToFirst();

  24. Fess says:

    Hello,
    1st of all thank yoy for great post.

    I try to solve some issue: How to delete specific attendee for example by mail.

    Thank you,

Leave a Reply

You can also subscribe without commenting.