1page.title=Calendar Provider
2@jd:body
3
4<div id="qv-wrapper">
5<div id="qv">
6    <h2>In this document</h2>
7    <ol>
8  <li><a href="#overview">Basics</a></li>
9  <li><a href="#manifest">User Permissions</a></li>
10  <li><a href="#calendar">Calendars table</a>
11<ol>
12      <li><a href="#query">Querying a calendar</a></li>
13      <li><a href="#modify-calendar">Modifying a calendar</a></li>
14      <li><a href="#insert-calendar">Inserting a calendar</a></li>
15    </ol>
16  </li>
17  <li><a href="#events">Events table</a>
18<ol>
19      <li><a href="#add-event">Adding Events</a></li>
20      <li><a href="#update-event">Updating Events</a></li>
21      <li><a href="#delete-event">Deleting Events</a></li>
22    </ol>
23  </li>
24  <li><a href="#attendees">Attendees table</a>
25<ol>
26      <li><a href="#add-attendees">Adding Attendees</a></li>
27    </ol>
28  </li>
29  <li><a href="#reminders">Reminders table</a>
30<ol>
31      <li><a href="#add-reminders">Adding Reminders</a></li>
32    </ol>
33  </li>
34  <li><a href="#instances">Instances table</a>
35  <ol>
36      <li><a href="#query-instances">Querying the Instances table</a></li>
37  </ol></li>
38  <li><a href="#intents">Calendar Intents</a>
39  <ol>
40      <li><a href="#intent-insert">Using an intent to insert an event</a></li>
41      <li><a href="#intent-edit">Using an intent to edit an event</a></li>
42      <li><a href="#intent-view">Using intents to view calendar data</a></li>
43    </ol>
44  </li>
45
46  <li><a href="#sync-adapter">Sync Adapters</a></li>
47</ol>
48
49    <h2>Key classes</h2>
50    <ol>
51      <li>{@link android.provider.CalendarContract.Calendars}</li>
52      <li>{@link android.provider.CalendarContract.Events}</li>
53      <li>{@link android.provider.CalendarContract.Attendees}</li>
54      <li>{@link android.provider.CalendarContract.Reminders}</li>
55    </ol>
56</div>
57</div>
58
59<p>The Calendar Provider is a repository for a user's calendar events. The
60Calendar Provider API allows you to perform query, insert, update, and delete
61operations on calendars, events, attendees, reminders, and so on.</p>
62
63
64<p>The Calender Provider API can be used by applications and sync adapters. The
65rules vary depending on what type of program is making the calls. This document
66focuses primarily on using the Calendar Provider API as an application. For
67a discussion of how sync adapters are different, see
68<a href="#sync-adapter">Sync Adapters</a>.</p>
69
70
71<p>Normally, to read or write calendar data, an application's manifest must
72include the proper permissions, described in <a href="#manifest">User
73Permissions</a>. To make performing common operations easier, the Calendar
74Provider offers a set of intents, as described in <a href="#intents">Calendar
75Intents</a>. These intents take users to the Calendar application to insert, view,
76and edit events. The user interacts with the Calendar application and then
77returns to the original application. Thus your application doesn't need to request permissions,
78nor does it need to provide a user interface to view or create events.</p>
79
80<h2 id="overview">Basics</h2>
81
82<p><a href="{@docRoot}guide/topics/providers/content-providers.html">Content providers</a> store data and make it accessible to
83applications. The content providers offered by the Android platform (including the Calendar Provider) typically expose data as a set of tables based on a
84relational database model, where each row is a record and each column is data of
85a particular type and meaning. Through the Calendar Provider API, applications
86and sync adapters can get read/write access to the database tables that hold a
87user's calendar data.</p>
88
89<p>Every content provider exposes a public URI (wrapped as a
90{@link android.net.Uri}
91object) that uniquely identifies its data set.  A content provider that controls
92 multiple data sets (multiple tables) exposes a separate URI for each one.  All
93URIs for providers begin with the string &quot;content://&quot;.  This
94identifies the data as being controlled by a content provider. The Calendar
95Provider defines constants for the URIs for each of its classes (tables). These
96URIs have the format <code><em>&lt;class&gt;</em>.CONTENT_URI</code>. For
97example, {@link android.provider.CalendarContract.Events#CONTENT_URI Events.CONTENT_URI}.</p>
98
99<p>Figure 1 shows a graphical representation of the Calendar Provider data model. It shows the
100main tables and the fields that link them to each other.</p>
101
102<img src="{@docRoot}images/providers/datamodel.png" alt="Calendar Provider Data Model"/>
103<p class="img-caption"><strong>Figure 1.</strong> Calendar Provider data model.</p>
104
105<p>A user can have multiple calendars, and different calendars can be associated with different types of accounts (Google Calendar, Exchange, and so on).</p>
106
107<p>The {@link android.provider.CalendarContract} defines the data model of calendar and event related information. This data is stored in a number of tables, listed below.</p>
108
109<table>
110  <tr>
111    <th>Table (Class)</th>
112    <th>Description</th>
113  </tr>
114  <tr>
115    <td><p>{@link android.provider.CalendarContract.Calendars}</p></td>
116
117    <td>This table holds
118the calendar-specific information. Each  row in this table contains the details for
119a single calendar, such as the  name, color, sync information, and so on.</td>
120  </tr>
121  <tr>
122    <td>{@link android.provider.CalendarContract.Events}</td>
123
124    <td>This table holds the
125event-specific information. Each row  in this table has the information for a single
126event&mdash;for example, event title, location, start time, end
127time, and so on. The event can occur one-time or can recur multiple times. Attendees,
128reminders, and extended  properties are stored in separate tables.
129They each have an {@link android.provider.CalendarContract.AttendeesColumns#EVENT_ID}
130that references the {@link android.provider.BaseColumns#_ID} in the Events table.</td>
131
132  </tr>
133  <tr>
134    <td>{@link android.provider.CalendarContract.Instances}</td>
135
136    <td>This table holds the
137start and end time for each occurrence of an event. Each row in this table
138represents a single event occurrence. For one-time events there is a 1:1 mapping
139of instances to events. For recurring events, multiple rows are automatically
140 generated that correspond to multiple occurrences of that event.</td>
141  </tr>
142  <tr>
143    <td>{@link android.provider.CalendarContract.Attendees}</td>
144
145    <td>This table holds the
146event attendee (guest) information. Each row represents a single guest of an
147event. It specifies the type of guest and the guest's attendance response
148for the event.</td>
149  </tr>
150  <tr>
151    <td>{@link android.provider.CalendarContract.Reminders}</td>
152
153    <td>This table holds the
154alert/notification data. Each row represents a single alert for an event. An
155event can have multiple reminders. The maximum number of reminders per event is
156specified in
157{@link android.provider.CalendarContract.CalendarColumns#MAX_REMINDERS},
158which is set by the sync adapter that
159owns  the given calendar. Reminders are specified in minutes before the event
160and have a method that determines how the user will be alerted.</td>
161  </tr>
162
163</table>
164
165<p>The Calendar Provider API is designed to be flexible and powerful. At the
166same time, it's important to provide a good end user experience and
167protect the integrity of the calendar and its data. To this end, here are
168some things to keep in mind when using the API:</p>
169
170<ul>
171
172<li><strong>Inserting, updating, and viewing calendar events.</strong> To directly insert, modify, and read events from the Calendar Provider, you need the appropriate <a href="#manifest">permissions</a>. However, if you're not building a full-fledged calendar application or sync adapter, requesting these permissions isn't necessary. You can instead use intents supported by Android's Calendar application to hand off read and write operations to that application. When you use the intents, your application sends users to the Calendar application to perform the desired operation
173in a pre-filled form. After they're done, they're returned to your application.
174By designing your application to perform common operations through the Calendar,
175you provide users with a consistent, robust user interface. This is the
176recommended approach. For more information, see <a href="#intents">Calendar
177Intents</a>.</p>
178
179
180<li><strong>Sync adapters.</strong> A sync adapter synchronizes the calendar data
181on a user's device with another server or data source. In the
182{@link android.provider.CalendarContract.Calendars} and
183{@link android.provider.CalendarContract.Events} tables,
184there are columns that are reserved for the sync adapters to use.
185The provider and applications should not modify them. In fact, they are not
186visible unless they are accessed as a sync adapter. For more information about
187sync adapters, see <a href="#sync-adapter">Sync Adapters</a>.</li>
188
189</ul>
190
191
192<h2 id="manifest">User Permissions</h2>
193
194<p>To read calendar data, an application must include the {@link
195android.Manifest.permission#READ_CALENDAR} permission in its manifest file. It
196must include the {@link android.Manifest.permission#WRITE_CALENDAR} permission
197to delete, insert or update calendar data:</p>
198
199<pre>
200&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
201&lt;manifest xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;...&gt;
202    &lt;uses-sdk android:minSdkVersion=&quot;14&quot; /&gt;
203    &lt;uses-permission android:name=&quot;android.permission.READ_CALENDAR&quot; /&gt;
204    &lt;uses-permission android:name=&quot;android.permission.WRITE_CALENDAR&quot; /&gt;
205    ...
206&lt;/manifest&gt;
207</pre>
208
209
210<h2 id="calendar">Calendars Table</h2>
211
212<p>The {@link android.provider.CalendarContract.Calendars} table contains details
213for individual calendars. The following
214Calendars columns are writable by both an application and a <a href="#sync-adapter">sync adapter</a>.
215For a full list of supported fields, see the
216{@link android.provider.CalendarContract.Calendars} reference.</p>
217<table>
218  <tr>
219    <th>Constant</th>
220    <th>Description</th>
221  </tr>
222  <tr>
223    <td>{@link android.provider.CalendarContract.Calendars#NAME}</td>
224    <td>The name of the calendar.</td>
225  </tr>
226  <tr>
227    <td>{@link android.provider.CalendarContract.Calendars#CALENDAR_DISPLAY_NAME}</td>
228    <td>The name of this calendar that is displayed to the user.</td>
229  </tr>
230  <tr>
231    <td>{@link android.provider.CalendarContract.Calendars#VISIBLE}</td>
232
233    <td>A boolean indicating whether the calendar is selected to be displayed. A
234value of 0 indicates that events associated with this calendar should not be
235shown.  A value of 1 indicates that events associated with this calendar should
236be shown. This value affects the generation of rows in the {@link
237android.provider.CalendarContract.Instances} table.</td>
238
239
240  </tr>
241  <tr>
242    <td>{@link android.provider.CalendarContract.CalendarColumns#SYNC_EVENTS}</td>
243
244    <td>A boolean indicating whether the calendar should be synced and have its
245events stored on the device. A value of 0 says do not sync this calendar or
246store its events on the device.  A value of 1 says sync events for this calendar
247and store its events on the device.</td>
248  </tr>
249</table>
250
251<h3 id="query">Querying a calendar</h3>
252
253<p>Here is an example that shows how to get the calendars that are owned by a particular
254user. For simplicity's sake, in this example the query operation is shown in the
255user interface thread ("main thread"). In practice, this should be done in an asynchronous
256thread instead of on the main thread. For more discussion, see
257<a href="{@docRoot}guide/components/loaders.html">Loaders</a>. If you are not just
258reading data but modifying it, see {@link android.content.AsyncQueryHandler}.
259</p>
260
261
262<pre>
263// Projection array. Creating indices for this array instead of doing
264// dynamic lookups improves performance.
265public static final String[] EVENT_PROJECTION = new String[] {
266    Calendars._ID,                           // 0
267    Calendars.ACCOUNT_NAME,                  // 1
268    Calendars.CALENDAR_DISPLAY_NAME,         // 2
269    Calendars.OWNER_ACCOUNT                  // 3
270};
271
272// The indices for the projection array above.
273private static final int PROJECTION_ID_INDEX = 0;
274private static final int PROJECTION_ACCOUNT_NAME_INDEX = 1;
275private static final int PROJECTION_DISPLAY_NAME_INDEX = 2;
276private static final int PROJECTION_OWNER_ACCOUNT_INDEX = 3;</pre>
277
278
279<div class="sidebox-wrapper"> <div class="sidebox"> <h3>Why must you include
280ACCOUNT_TYPE?</h3> <p>If you query on a {@link
281android.provider.CalendarContract.Calendars#ACCOUNT_NAME
282Calendars.ACCOUNT_NAME}, you must also include
283{@link android.provider.CalendarContract.Calendars#ACCOUNT_TYPE Calendars.ACCOUNT_TYPE}
284in the selection. That is because a given account is
285only considered unique given both its <code>ACCOUNT_NAME</code> and its
286<code>ACCOUNT_TYPE</code>. The <code>ACCOUNT_TYPE</code> is the string corresponding to the
287account authenticator that was used when the account was registered with the
288{@link android.accounts.AccountManager}. There is also a special type of account called {@link
289android.provider.CalendarContract#ACCOUNT_TYPE_LOCAL} for calendars not
290associated with a device account. {@link
291android.provider.CalendarContract#ACCOUNT_TYPE_LOCAL} accounts do not get
292synced.</p> </div> </div>
293
294
295<p> In the next part of the example, you construct your query. The selection
296specifies the criteria for the query. In this example the query is looking for
297calendars that have the <code>ACCOUNT_NAME</code>
298"sampleuser@google.com", the <code>ACCOUNT_TYPE</code>
299"com.google", and the <code>OWNER_ACCOUNT</code>
300"sampleuser@google.com". If you want to see all calendars that a user
301has viewed, not just calendars the user owns, omit the <code>OWNER_ACCOUNT</code>.
302The query returns a {@link android.database.Cursor}
303object that you can use to traverse the result set returned by the database
304query. For more discussion of using queries in content providers,
305see <a href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a>.</p>
306
307
308<pre>// Run query
309Cursor cur = null;
310ContentResolver cr = getContentResolver();
311Uri uri = Calendars.CONTENT_URI;
312String selection = "((" + Calendars.ACCOUNT_NAME + " = ?) AND ("
313                        + Calendars.ACCOUNT_TYPE + " = ?) AND ("
314                        + Calendars.OWNER_ACCOUNT + " = ?))";
315String[] selectionArgs = new String[] {"sampleuser@gmail.com", "com.google",
316        "sampleuser@gmail.com"};
317// Submit the query and get a Cursor object back.
318cur = cr.query(uri, EVENT_PROJECTION, selection, selectionArgs, null);</pre>
319
320<p>This next section uses the cursor to step through the result set. It uses the
321constants that were set up at the beginning of the example to return the values
322for each field.</p>
323
324<pre>// Use the cursor to step through the returned records
325while (cur.moveToNext()) {
326    long calID = 0;
327    String displayName = null;
328    String accountName = null;
329    String ownerName = null;
330
331    // Get the field values
332    calID = cur.getLong(PROJECTION_ID_INDEX);
333    displayName = cur.getString(PROJECTION_DISPLAY_NAME_INDEX);
334    accountName = cur.getString(PROJECTION_ACCOUNT_NAME_INDEX);
335    ownerName = cur.getString(PROJECTION_OWNER_ACCOUNT_INDEX);
336
337    // Do something with the values...
338
339   ...
340}
341</pre>
342
343<h3 id="modify-calendar">Modifying a calendar</h3>
344
345<p>To perform an update of an calendar, you can provide the {@link
346android.provider.BaseColumns#_ID} of the calendar either as an appended ID to
347the Uri
348
349({@link android.content.ContentUris#withAppendedId(android.net.Uri,long) withAppendedId()})
350or as the first selection item. The  selection
351should start with <code>&quot;_id=?&quot;</code>, and the first
352<code>selectionArg</code> should be  the {@link
353android.provider.BaseColumns#_ID} of the calendar.
354You can also do updates by encoding the ID in the URI. This example changes a
355calendar's display name using the
356({@link android.content.ContentUris#withAppendedId(android.net.Uri,long) withAppendedId()})
357approach:</p>
358
359<pre>private static final String DEBUG_TAG = "MyActivity";
360...
361long calID = 2;
362ContentValues values = new ContentValues();
363// The new display name for the calendar
364values.put(Calendars.CALENDAR_DISPLAY_NAME, &quot;Trevor's Calendar&quot;);
365Uri updateUri = ContentUris.withAppendedId(Calendars.CONTENT_URI, calID);
366int rows = getContentResolver().update(updateUri, values, null, null);
367Log.i(DEBUG_TAG, &quot;Rows updated: &quot; + rows);</pre>
368
369<h3 id="insert-calendar">Inserting a calendar</h2>
370
371<p>Calendars are  designed to be primarily managed by a sync adapter, so you
372should only insert new calendars as a sync adapter. For the most part,
373applications can only make superficial changes to calendars, such as changing the display name. If
374an application needs to create a local calendar, it can do this by performing
375the calendar insertion as a sync adapter, using an {@link
376android.provider.CalendarContract.SyncColumns#ACCOUNT_TYPE} of {@link
377android.provider.CalendarContract#ACCOUNT_TYPE_LOCAL}.
378{@link android.provider.CalendarContract#ACCOUNT_TYPE_LOCAL}
379is a special account type for calendars that are not
380associated with a device account. Calendars of this type are not synced to a server. For a
381discussion of sync adapters, see <a href="#sync-adapter">Sync Adapters</a>.</p>
382
383<h2 id="events">Events Table</h2>
384
385<p>The {@link android.provider.CalendarContract.Events} table contains details
386for individual events. To add, update, or delete  events, an application must
387include the {@link android.Manifest.permission#WRITE_CALENDAR} permission in its
388<a href="#manifest">manifest file</a>.</p>
389
390<p>The following Events columns are writable by both an application and a sync
391adapter. For a full list of supported fields, see the {@link
392android.provider.CalendarContract.Events} reference.</p>
393
394<table>
395  <tr>
396    <th>Constant</th>
397    <th>Description</th>
398  </tr>
399  <tr>
400    <td>{@link android.provider.CalendarContract.EventsColumns#CALENDAR_ID}</td>
401    <td>The {@link android.provider.BaseColumns#_ID} of the calendar the event belongs to.</td>
402  </tr>
403  <tr>
404    <td>{@link android.provider.CalendarContract.EventsColumns#ORGANIZER}</td>
405    <td>Email of the organizer (owner) of the event.</td>
406  </tr>
407  <tr>
408    <td>{@link android.provider.CalendarContract.EventsColumns#TITLE}</td>
409    <td>The title of the event.</td>
410  </tr>
411  <tr>
412    <td>{@link android.provider.CalendarContract.EventsColumns#EVENT_LOCATION}</td>
413    <td>Where the event takes place. </td>
414  </tr>
415  <tr>
416    <td>{@link android.provider.CalendarContract.EventsColumns#DESCRIPTION}</td>
417    <td>The description of the event.</td>
418  </tr>
419  <tr>
420    <td>{@link android.provider.CalendarContract.EventsColumns#DTSTART}</td>
421    <td>The time the event starts in UTC milliseconds since the epoch. </td>
422  </tr>
423  <tr>
424    <td>{@link android.provider.CalendarContract.EventsColumns#DTEND}</td>
425    <td>The time the event ends in UTC milliseconds since the epoch. </td>
426  </tr>
427  <tr>
428    <td>{@link android.provider.CalendarContract.EventsColumns#EVENT_TIMEZONE}</td>
429    <td>The time zone for the event.</td>
430  </tr>
431  <tr>
432    <td>{@link android.provider.CalendarContract.EventsColumns#EVENT_END_TIMEZONE}</td>
433    <td>The time zone for the end time of the event.</td>
434  </tr>
435  <tr>
436    <td>{@link android.provider.CalendarContract.EventsColumns#DURATION}</td>
437
438    <td>The duration of the event in <a
439href="http://tools.ietf.org/html/rfc5545#section-3.8.2.5">RFC5545</a> format.
440For example, a value of <code>&quot;PT1H&quot;</code> states that the event
441should last one hour, and a value of <code>&quot;P2W&quot;</code> indicates a
442duration of 2 weeks. </td>
443
444
445  </tr>
446  <tr>
447    <td>{@link android.provider.CalendarContract.EventsColumns#ALL_DAY}</td>
448
449    <td>A value of 1 indicates this event occupies the entire day, as defined by
450the local time zone. A value of 0 indicates it is a regular event that may start
451and end at any time during a day.</td>
452
453
454  </tr>
455
456
457  <tr>
458    <td>{@link android.provider.CalendarContract.EventsColumns#RRULE}</td>
459
460    <td>The recurrence rule for the event format. For
461example, <code>&quot;FREQ=WEEKLY;COUNT=10;WKST=SU&quot;</code>. You can find
462more examples <a
463href="http://tools.ietf.org/html/rfc5545#section-3.8.5.3">here</a>.</td>
464
465  </tr>
466
467  <tr>
468    <td>{@link android.provider.CalendarContract.EventsColumns#RDATE}</td>
469    <td>The recurrence dates for the event.
470    You typically use {@link android.provider.CalendarContract.EventsColumns#RDATE}
471    in conjunction with {@link android.provider.CalendarContract.EventsColumns#RRULE}
472    to define an aggregate set of
473repeating occurrences. For more discussion, see the <a
474href="http://tools.ietf.org/html/rfc5545#section-3.8.5.2">RFC5545 spec</a>.</td>
475</tr>
476
477  <tr>
478    <td>{@link android.provider.CalendarContract.EventsColumns#AVAILABILITY}</td>
479
480    <td>If this event counts as busy time or is free time that can be
481scheduled over. </td>
482
483  </tr>
484  <tr>
485    <td>{@link android.provider.CalendarContract.EventsColumns#GUESTS_CAN_MODIFY}</td>
486    <td>Whether guests can modify the event. </td>
487  </tr>
488  <tr>
489    <td>{@link android.provider.CalendarContract.EventsColumns#GUESTS_CAN_INVITE_OTHERS}</td>
490    <td>Whether guests can invite other guests. </td>
491  </tr>
492  <tr>
493    <td>{@link android.provider.CalendarContract.EventsColumns#GUESTS_CAN_SEE_GUESTS}</td>
494    <td>Whether guests can see the list of attendees.</td>
495  </tr>
496</table>
497
498<h3 id="add-event">Adding Events</h3>
499
500<p>When your application inserts a new event, we recommend that you use an
501{@link android.content.Intent#ACTION_INSERT INSERT} Intent, as described in <a
502href="#intent-insert">Using an intent to insert an event</a>. However, if you
503need to, you can insert events directly. This section describes how to do
504this.</p>
505
506
507<p>Here are the rules for inserting a new event: </p>
508<ul>
509
510  <li>You must include  {@link
511android.provider.CalendarContract.EventsColumns#CALENDAR_ID} and {@link
512android.provider.CalendarContract.EventsColumns#DTSTART}.</li>
513
514<li>You must include an {@link
515android.provider.CalendarContract.EventsColumns#EVENT_TIMEZONE}. To get a list
516of the system's installed time zone IDs, use {@link
517java.util.TimeZone#getAvailableIDs()}. Note that this rule does not apply if
518you're inserting an event through the {@link
519android.content.Intent#ACTION_INSERT INSERT} Intent, described in <a
520href="#intent-insert">Using an intent to insert an event</a>&mdash;in that
521scenario, a default time zone is supplied.</li>
522
523  <li>For non-recurring events, you must include {@link
524android.provider.CalendarContract.EventsColumns#DTEND}. </li>
525
526
527  <li>For recurring events, you must include a {@link
528android.provider.CalendarContract.EventsColumns#DURATION} in addition to  {@link
529android.provider.CalendarContract.EventsColumns#RRULE} or {@link
530android.provider.CalendarContract.EventsColumns#RDATE}. Note that this rule does not apply if
531you're inserting an event through the {@link
532android.content.Intent#ACTION_INSERT INSERT} Intent, described in <a
533href="#intent-insert">Using an intent to insert an event</a>&mdash;in that
534scenario, you can use an {@link
535android.provider.CalendarContract.EventsColumns#RRULE} in conjunction with {@link android.provider.CalendarContract.EventsColumns#DTSTART} and {@link android.provider.CalendarContract.EventsColumns#DTEND}, and the Calendar application
536converts it to a duration automatically.</li>
537
538</ul>
539
540<p>Here is an example of inserting an event. This is being performed in the UI
541thread for simplicity. In practice, inserts and updates should be done in an
542asynchronous thread to move the action into a background thread. For more
543information, see {@link android.content.AsyncQueryHandler}.</p>
544
545
546<pre>
547long calID = 3;
548long startMillis = 0;
549long endMillis = 0;
550Calendar beginTime = Calendar.getInstance();
551beginTime.set(2012, 9, 14, 7, 30);
552startMillis = beginTime.getTimeInMillis();
553Calendar endTime = Calendar.getInstance();
554endTime.set(2012, 9, 14, 8, 45);
555endMillis = endTime.getTimeInMillis();
556...
557
558ContentResolver cr = getContentResolver();
559ContentValues values = new ContentValues();
560values.put(Events.DTSTART, startMillis);
561values.put(Events.DTEND, endMillis);
562values.put(Events.TITLE, &quot;Jazzercise&quot;);
563values.put(Events.DESCRIPTION, &quot;Group workout&quot;);
564values.put(Events.CALENDAR_ID, calID);
565values.put(Events.EVENT_TIMEZONE, "America/Los_Angeles");
566Uri uri = cr.insert(Events.CONTENT_URI, values);
567
568// get the event ID that is the last element in the Uri
569long eventID = Long.parseLong(uri.getLastPathSegment());
570//
571// ... do something with event ID
572//
573//</pre>
574
575<p class="note"><strong>Note:</strong> See how this example captures the event
576ID after the event is created. This is the easiest way to get an event ID. You often
577need the event ID to perform other calendar operations&mdash;for example, to add
578attendees or reminders to an event.</p>
579
580
581<h3 id="update-event">Updating Events</h3>
582
583<p>When your application wants to allow the user to edit an event, we recommend
584that you use an {@link android.content.Intent#ACTION_EDIT EDIT} Intent, as
585described in <a href="#intent-edit">Using an intent to edit an  event</a>.
586However, if you need to, you can edit events directly. To perform an update of
587an Event, you can provide the <code>_ID</code> of the
588event either as an appended ID to the Uri ({@link
589android.content.ContentUris#withAppendedId(android.net.Uri,long) withAppendedId()})
590or as the first selection item.
591The selection should start with <code>&quot;_id=?&quot;</code>, and the first
592<code>selectionArg</code> should be  the <code>_ID</code> of the event. You can
593also do updates using a selection with no ID. Here is an example of updating an
594event. It changes the title of the event using the
595{@link android.content.ContentUris#withAppendedId(android.net.Uri,long) withAppendedId()}
596approach:</p>
597
598
599<pre>private static final String DEBUG_TAG = "MyActivity";
600...
601long eventID = 188;
602...
603ContentResolver cr = getContentResolver();
604ContentValues values = new ContentValues();
605Uri updateUri = null;
606// The new title for the event
607values.put(Events.TITLE, &quot;Kickboxing&quot;);
608updateUri = ContentUris.withAppendedId(Events.CONTENT_URI, eventID);
609int rows = getContentResolver().update(updateUri, values, null, null);
610Log.i(DEBUG_TAG, &quot;Rows updated: &quot; + rows);  </pre>
611
612<h3 id="delete-event">Deleting Events</h3>
613
614<p>You can delete an event either by its {@link
615android.provider.BaseColumns#_ID} as an appended  ID on the URI, or by using
616standard selection. If you use an appended ID, you can't also do a selection.
617There are two versions of delete: as an application and as a sync adapter. An
618application delete sets the <em>deleted</em> column to 1. This flag that tells
619the sync adapter that the row was deleted and that this deletion should be
620propagated to the server. A sync adapter delete removes the event from the
621database along with all its associated data. Here is an example of application
622deleting an event through its {@link android.provider.BaseColumns#_ID}:</p>
623
624
625<pre>private static final String DEBUG_TAG = "MyActivity";
626...
627long eventID = 201;
628...
629ContentResolver cr = getContentResolver();
630ContentValues values = new ContentValues();
631Uri deleteUri = null;
632deleteUri = ContentUris.withAppendedId(Events.CONTENT_URI, eventID);
633int rows = getContentResolver().delete(deleteUri, null, null);
634Log.i(DEBUG_TAG, &quot;Rows deleted: &quot; + rows);
635</pre>
636
637<h2 id="attendees">Attendees Table</h2>
638
639<p>Each row of the {@link android.provider.CalendarContract.Attendees} table
640represents a single attendee or guest of an event. Calling
641{@link android.provider.CalendarContract.Reminders#query(android.content.ContentResolver, long, java.lang.String[]) query()}
642returns a list of attendees for  the
643event with the given {@link android.provider.CalendarContract.AttendeesColumns#EVENT_ID}.
644This  {@link android.provider.CalendarContract.AttendeesColumns#EVENT_ID}
645must match the {@link
646android.provider.BaseColumns#_ID} of a particular event.</p>
647
648<p>The following table lists the
649writable fields. When inserting a new attendee, you must include all of them
650except <code>ATTENDEE_NAME</code>.
651</p>
652
653
654<table>
655  <tr>
656    <th>Constant</th>
657    <th>Description</th>
658  </tr>
659  <tr>
660    <td>{@link android.provider.CalendarContract.AttendeesColumns#EVENT_ID}</td>
661    <td>The ID of the event.</td>
662  </tr>
663  <tr>
664    <td>{@link android.provider.CalendarContract.AttendeesColumns#ATTENDEE_NAME}</td>
665    <td>The name of the attendee.</td>
666  </tr>
667  <tr>
668    <td>{@link android.provider.CalendarContract.AttendeesColumns#ATTENDEE_EMAIL}</td>
669    <td>The email address of the attendee.</td>
670  </tr>
671  <tr>
672    <td>{@link android.provider.CalendarContract.AttendeesColumns#ATTENDEE_RELATIONSHIP}</td>
673    <td><p>The relationship of the attendee to the event. One of:</p>
674      <ul>
675        <li>{@link android.provider.CalendarContract.AttendeesColumns#RELATIONSHIP_ATTENDEE}</li>
676        <li>{@link android.provider.CalendarContract.AttendeesColumns#RELATIONSHIP_NONE}</li>
677        <li>{@link android.provider.CalendarContract.AttendeesColumns#RELATIONSHIP_ORGANIZER}</li>
678        <li>{@link android.provider.CalendarContract.AttendeesColumns#RELATIONSHIP_PERFORMER}</li>
679        <li>{@link android.provider.CalendarContract.AttendeesColumns#RELATIONSHIP_SPEAKER}</li>
680    </ul>
681    </td>
682  </tr>
683  <tr>
684    <td>{@link android.provider.CalendarContract.AttendeesColumns#ATTENDEE_TYPE}</td>
685    <td><p>The type of attendee. One of: </p>
686      <ul>
687        <li>{@link android.provider.CalendarContract.AttendeesColumns#TYPE_REQUIRED}</li>
688        <li>{@link android.provider.CalendarContract.AttendeesColumns#TYPE_OPTIONAL}</li>
689    </ul></td>
690  </tr>
691  <tr>
692    <td>{@link android.provider.CalendarContract.AttendeesColumns#ATTENDEE_STATUS}</td>
693    <td><p>The attendance status of the attendee. One of:</p>
694      <ul>
695        <li>{@link android.provider.CalendarContract.AttendeesColumns#ATTENDEE_STATUS_ACCEPTED}</li>
696        <li>{@link android.provider.CalendarContract.AttendeesColumns#ATTENDEE_STATUS_DECLINED}</li>
697        <li>{@link android.provider.CalendarContract.AttendeesColumns#ATTENDEE_STATUS_INVITED}</li>
698        <li>{@link android.provider.CalendarContract.AttendeesColumns#ATTENDEE_STATUS_NONE}</li>
699        <li>{@link android.provider.CalendarContract.AttendeesColumns#ATTENDEE_STATUS_TENTATIVE}</li>
700    </ul></td>
701  </tr>
702</table>
703
704<h3 id="add-attendees">Adding Attendees</h3>
705
706<p>Here is an example that adds a single attendee to an event. Note that the
707{@link android.provider.CalendarContract.AttendeesColumns#EVENT_ID}
708is required:</p>
709
710<pre>
711long eventID = 202;
712...
713ContentResolver cr = getContentResolver();
714ContentValues values = new ContentValues();
715values.put(Attendees.ATTENDEE_NAME, &quot;Trevor&quot;);
716values.put(Attendees.ATTENDEE_EMAIL, &quot;trevor@example.com&quot;);
717values.put(Attendees.ATTENDEE_RELATIONSHIP, Attendees.RELATIONSHIP_ATTENDEE);
718values.put(Attendees.ATTENDEE_TYPE, Attendees.TYPE_OPTIONAL);
719values.put(Attendees.ATTENDEE_STATUS, Attendees.ATTENDEE_STATUS_INVITED);
720values.put(Attendees.EVENT_ID, eventID);
721Uri uri = cr.insert(Attendees.CONTENT_URI, values);
722</pre>
723
724<h2 id="reminders">Reminders Table</h2>
725
726<p>Each row of the {@link android.provider.CalendarContract.Reminders} table
727represents a single reminder for an event. Calling
728{@link android.provider.CalendarContract.Reminders#query(android.content.ContentResolver, long, java.lang.String[]) query()}  returns a list of reminders for the
729event with the given
730{@link android.provider.CalendarContract.AttendeesColumns#EVENT_ID}.</p>
731
732
733<p>The following table lists the writable fields for reminders. All of them must
734be included when inserting a new reminder. Note that sync adapters specify the
735types of reminders they support in the {@link
736android.provider.CalendarContract.Calendars} table. See
737{@link android.provider.CalendarContract.CalendarColumns#ALLOWED_REMINDERS}
738for details.</p>
739
740
741<table>
742  <tr>
743    <th>Constant</th>
744    <th>Description</th>
745  </tr>
746  <tr>
747    <td>{@link android.provider.CalendarContract.RemindersColumns#EVENT_ID}</td>
748    <td>The ID of the event.</td>
749  </tr>
750  <tr>
751    <td>{@link android.provider.CalendarContract.RemindersColumns#MINUTES}</td>
752    <td>The minutes prior to the event that the reminder should fire.</td>
753  </tr>
754  <tr>
755    <td>{@link android.provider.CalendarContract.RemindersColumns#METHOD}</td>
756    <td><p>The alarm method, as set on the server. One of:</p>
757      <ul>
758        <li>{@link android.provider.CalendarContract.RemindersColumns#METHOD_ALERT}</li>
759        <li>{@link android.provider.CalendarContract.RemindersColumns#METHOD_DEFAULT}</li>
760        <li>{@link android.provider.CalendarContract.RemindersColumns#METHOD_EMAIL}</li>
761        <li>{@link android.provider.CalendarContract.RemindersColumns#METHOD_SMS}</li>
762    </ul></td>
763  </tr>
764</table>
765
766<h3 id="add-reminders">Adding Reminders</h3>
767
768<p>This example adds a reminder to an event. The reminder fires 15
769minutes before the event.</p>
770<pre>
771long eventID = 221;
772...
773ContentResolver cr = getContentResolver();
774ContentValues values = new ContentValues();
775values.put(Reminders.MINUTES, 15);
776values.put(Reminders.EVENT_ID, eventID);
777values.put(Reminders.METHOD, Reminders.METHOD_ALERT);
778Uri uri = cr.insert(Reminders.CONTENT_URI, values);</pre>
779
780<h2 id="instances">Instances Table</h2>
781
782<p>The
783{@link android.provider.CalendarContract.Instances} table holds the
784start and end time for occurrences of an event. Each row in this table
785represents a single event occurrence. The instances table is not writable and only
786provides a  way to query event occurrences. </p>
787
788<p>The following table lists some of the fields you can query on for an instance. Note
789that time zone is defined by
790{@link android.provider.CalendarContract.CalendarCache#KEY_TIMEZONE_TYPE}
791and
792{@link android.provider.CalendarContract.CalendarCache#KEY_TIMEZONE_INSTANCES}.</p>
793
794
795<table>
796  <tr>
797    <th>Constant</th>
798    <th>Description</th>
799  </tr>
800  <tr>
801    <td>{@link android.provider.CalendarContract.Instances#BEGIN}</td>
802    <td>The beginning time of the instance, in UTC milliseconds.</td>
803  </tr>
804  <tr>
805    <td>{@link android.provider.CalendarContract.Instances#END}</td>
806    <td>The ending time of the instance, in UTC milliseconds.</td>
807  </tr>
808  <tr>
809    <td>{@link android.provider.CalendarContract.Instances#END_DAY}</td>
810
811    <td>The Julian end day of the instance, relative to the Calendar's time
812zone.
813
814</td>
815  </tr>
816  <tr>
817    <td>{@link android.provider.CalendarContract.Instances#END_MINUTE}</td>
818
819    <td>The end minute of the instance measured from midnight in the
820Calendar's time zone.</td>
821
822  </tr>
823  <tr>
824    <td>{@link android.provider.CalendarContract.Instances#EVENT_ID}</td>
825    <td>The <code>_ID</code> of the event for this instance.</td>
826  </tr>
827    <tr>
828    <td>{@link android.provider.CalendarContract.Instances#START_DAY}</td>
829    <td>The Julian start day of the instance, relative to the Calendar's time zone.
830 </td>
831  </tr>
832  <tr>
833    <td>{@link android.provider.CalendarContract.Instances#START_MINUTE}</td>
834
835    <td>The start minute of the instance measured from midnight, relative to the
836Calendar's time zone.
837</td>
838
839  </tr>
840
841</table>
842
843<h3 id="query-instances">Querying the Instances table</h3>
844
845<p>To query the Instances table, you need to specify a range time for the query
846in the URI. In this example, {@link android.provider.CalendarContract.Instances}
847gets access to the {@link
848android.provider.CalendarContract.EventsColumns#TITLE} field through its
849implementation of the {@link android.provider.CalendarContract.EventsColumns} interface.
850In other words, {@link
851android.provider.CalendarContract.EventsColumns#TITLE} is returned through a
852database view, not through querying the raw {@link
853android.provider.CalendarContract.Instances} table.</p>
854
855<pre>
856private static final String DEBUG_TAG = "MyActivity";
857public static final String[] INSTANCE_PROJECTION = new String[] {
858    Instances.EVENT_ID,      // 0
859    Instances.BEGIN,         // 1
860    Instances.TITLE          // 2
861  };
862
863// The indices for the projection array above.
864private static final int PROJECTION_ID_INDEX = 0;
865private static final int PROJECTION_BEGIN_INDEX = 1;
866private static final int PROJECTION_TITLE_INDEX = 2;
867...
868
869// Specify the date range you want to search for recurring
870// event instances
871Calendar beginTime = Calendar.getInstance();
872beginTime.set(2011, 9, 23, 8, 0);
873long startMillis = beginTime.getTimeInMillis();
874Calendar endTime = Calendar.getInstance();
875endTime.set(2011, 10, 24, 8, 0);
876long endMillis = endTime.getTimeInMillis();
877
878Cursor cur = null;
879ContentResolver cr = getContentResolver();
880
881// The ID of the recurring event whose instances you are searching
882// for in the Instances table
883String selection = Instances.EVENT_ID + " = ?";
884String[] selectionArgs = new String[] {"207"};
885
886// Construct the query with the desired date range.
887Uri.Builder builder = Instances.CONTENT_URI.buildUpon();
888ContentUris.appendId(builder, startMillis);
889ContentUris.appendId(builder, endMillis);
890
891// Submit the query
892cur =  cr.query(builder.build(),
893    INSTANCE_PROJECTION,
894    selection,
895    selectionArgs,
896    null);
897
898while (cur.moveToNext()) {
899    String title = null;
900    long eventID = 0;
901    long beginVal = 0;
902
903    // Get the field values
904    eventID = cur.getLong(PROJECTION_ID_INDEX);
905    beginVal = cur.getLong(PROJECTION_BEGIN_INDEX);
906    title = cur.getString(PROJECTION_TITLE_INDEX);
907
908    // Do something with the values.
909    Log.i(DEBUG_TAG, "Event:  " + title);
910    Calendar calendar = Calendar.getInstance();
911    calendar.setTimeInMillis(beginVal);
912    DateFormat formatter = new SimpleDateFormat("MM/dd/yyyy");
913    Log.i(DEBUG_TAG, "Date: " + formatter.format(calendar.getTime()));
914    }
915 }</pre>
916
917<h2 id="intents">Calendar Intents</h2>
918<p>Your application doesn't need <a href="#manifest">permissions</a> to read and write calendar data. It can instead use intents supported by Android's Calendar application to hand off read and write operations to that application. The following table lists the intents supported by the Calendar Provider:</p>
919<table>
920  <tr>
921    <th>Action</th>
922    <th>URI</th>
923
924    <th>Description</th>
925    <th>Extras</th>
926  </tr>
927  <tr>
928    <td><br>
929    {@link android.content.Intent#ACTION_VIEW VIEW} <br></td>
930    <td><p><code>content://com.android.calendar/time/&lt;ms_since_epoch&gt;</code></p>
931    You can also refer to the URI with
932{@link android.provider.CalendarContract#CONTENT_URI CalendarContract.CONTENT_URI}.
933For an example of using this intent, see <a href="{@docRoot}guide/topics/providers/calendar-provider.html#intent-view">Using intents to view calendar data</a>.
934
935    </td>
936    <td>Open calendar to the time specified by <code>&lt;ms_since_epoch&gt;</code>.</td>
937    <td>None.</td>
938  </tr>
939  <tr>
940    <td><p>{@link android.content.Intent#ACTION_VIEW VIEW} </p>
941
942     </td>
943    <td><p><code>content://com.android.calendar/events/&lt;event_id&gt;</code></p>
944
945    You can also refer to the URI with
946{@link android.provider.CalendarContract.Events#CONTENT_URI Events.CONTENT_URI}.
947For an example of using this intent, see <a href="{@docRoot}guide/topics/providers/calendar-provider.html#intent-view">Using intents to view calendar data</a>.
948
949    </td>
950    <td>View the event specified by <code>&lt;event_id&gt;</code>.</td>
951
952    <td>{@link android.provider.CalendarContract#EXTRA_EVENT_BEGIN_TIME CalendarContract.EXTRA_EVENT_BEGIN_TIME}<br>
953      <br>
954      <br>
955    {@link android.provider.CalendarContract#EXTRA_EVENT_END_TIME CalendarContract.EXTRA_EVENT_END_TIME}</td>
956  </tr>
957
958  <tr>
959    <td>{@link android.content.Intent#ACTION_EDIT EDIT} </td>
960    <td><p><code>content://com.android.calendar/events/&lt;event_id&gt;</code></p>
961
962  You can also refer to the URI with
963{@link android.provider.CalendarContract.Events#CONTENT_URI Events.CONTENT_URI}.
964For an example of using this intent, see <a href="{@docRoot}guide/topics/providers/calendar-provider.html#intent-edit">Using an intent to edit an event</a>.
965
966
967    </td>
968    <td>Edit the event specified by <code>&lt;event_id&gt;</code>.</td>
969
970    <td>{@link android.provider.CalendarContract#EXTRA_EVENT_BEGIN_TIME CalendarContract.EXTRA_EVENT_BEGIN_TIME}<br>
971      <br>
972      <br>
973    {@link android.provider.CalendarContract#EXTRA_EVENT_END_TIME CalendarContract.EXTRA_EVENT_END_TIME}</td>
974  </tr>
975
976  <tr>
977    <td>{@link android.content.Intent#ACTION_EDIT EDIT} <br>
978    <br>
979    {@link android.content.Intent#ACTION_INSERT INSERT} </td>
980    <td><p><code>content://com.android.calendar/events</code></p>
981
982   You can also refer to the URI with
983{@link android.provider.CalendarContract.Events#CONTENT_URI Events.CONTENT_URI}.
984For an example of using this intent, see <a href="{@docRoot}guide/topics/providers/calendar-provider.html#intent-insert">Using an intent to insert an event</a>.
985
986    </td>
987
988    <td>Create an event.</td>
989    <td>Any of the extras listed in the table below.</td>
990  </tr>
991</table>
992
993<p>The following table lists the intent extras supported by the Calendar Provider:
994</p>
995<table>
996  <tr>
997    <th>Intent Extra</th>
998    <th>Description</th>
999  </tr>
1000  <tr>
1001    <td>{@link android.provider.CalendarContract.EventsColumns#TITLE Events.TITLE}</td>
1002    <td>Name for the event.</td>
1003  </tr>
1004  <tr>
1005
1006    <td>{@link android.provider.CalendarContract#EXTRA_EVENT_BEGIN_TIME
1007CalendarContract.EXTRA_EVENT_BEGIN_TIME}</td>
1008    <td>Event begin time in milliseconds from the epoch.</td>
1009  </tr>
1010  <tr>
1011    <td>{@link android.provider.CalendarContract#EXTRA_EVENT_END_TIME
1012CalendarContract.EXTRA_EVENT_END_TIME}</td>
1013
1014    <td>Event end time in milliseconds from the epoch.</td>
1015  </tr>
1016  <tr>
1017    <td>{@link android.provider.CalendarContract#EXTRA_EVENT_ALL_DAY
1018CalendarContract.EXTRA_EVENT_ALL_DAY}</td>
1019
1020    <td>A boolean that indicates that an event is all day. Value can be
1021<code>true</code> or <code>false</code>.</td> </tr>
1022  <tr>
1023    <td>{@link android.provider.CalendarContract.EventsColumns#EVENT_LOCATION
1024Events.EVENT_LOCATION}</td>
1025
1026    <td>Location of the event.</td>
1027  </tr>
1028  <tr>
1029    <td>{@link android.provider.CalendarContract.EventsColumns#DESCRIPTION
1030Events.DESCRIPTION}</td>
1031
1032    <td>Event description.</td>
1033  </tr>
1034  <tr>
1035    <td>
1036    {@link android.content.Intent#EXTRA_EMAIL Intent.EXTRA_EMAIL}</td>
1037    <td>Email addresses of those to invite as a comma-separated list.</td>
1038  </tr>
1039  <tr>
1040    <td>
1041    {@link android.provider.CalendarContract.EventsColumns#RRULE Events.RRULE}</td>
1042    <td>The recurrence rule for the event.</td>
1043  </tr>
1044  <tr>
1045    <td>
1046    {@link android.provider.CalendarContract.EventsColumns#ACCESS_LEVEL
1047Events.ACCESS_LEVEL}</td>
1048
1049    <td>Whether the event is private or public.</td>
1050  </tr>
1051  <tr>
1052    <td>{@link android.provider.CalendarContract.EventsColumns#AVAILABILITY
1053Events.AVAILABILITY}</td>
1054
1055    <td>If this event counts as busy time or is free time that can be scheduled over.</td>
1056
1057</table>
1058<p>The following sections describe how to use these intents.</p>
1059
1060
1061<h3 id="intent-insert">Using an intent to insert an event</h3>
1062
1063<p>Using the {@link android.content.Intent#ACTION_INSERT INSERT} Intent
1064lets your application hand off the event insertion task to the Calendar itself.
1065With this approach, your application doesn't even need to have the {@link
1066android.Manifest.permission#WRITE_CALENDAR} permission included in its <a
1067href="#manifest">manifest file</a>.</p>
1068
1069
1070<p>When users run an application that uses this approach, the application sends
1071them to the Calendar to finish adding the event. The {@link
1072android.content.Intent#ACTION_INSERT INSERT} Intent uses extra fields to
1073pre-populate a form with the details of the event in the Calendar. Users can
1074then cancel the event, edit the form as needed, or save the event to their
1075calendars.</p>
1076
1077
1078
1079<p>Here is a code snippet that schedules an event on January 19, 2012, that runs
1080from 7:30 a.m. to 8:30 a.m. Note the following about this code snippet:</p>
1081
1082<ul>
1083  <li>It specifies {@link android.provider.CalendarContract.Events#CONTENT_URI Events.CONTENT_URI}
1084  as the Uri.</li>
1085
1086  <li>It uses the {@link
1087android.provider.CalendarContract#EXTRA_EVENT_BEGIN_TIME
1088CalendarContract.EXTRA_EVENT_BEGIN_TIME} and {@link
1089android.provider.CalendarContract#EXTRA_EVENT_END_TIME
1090CalendarContract.EXTRA_EVENT_END_TIME} extra fields to pre-populate the form
1091with the time of the event. The values  for these times must be in UTC milliseconds
1092from the epoch.</li>
1093
1094  <li>It uses the {@link android.content.Intent#EXTRA_EMAIL Intent.EXTRA_EMAIL}
1095extra field to provide a comma-separated list of invitees, specified by email address.</li>
1096
1097</ul>
1098<pre>
1099Calendar beginTime = Calendar.getInstance();
1100beginTime.set(2012, 0, 19, 7, 30);
1101Calendar endTime = Calendar.getInstance();
1102endTime.set(2012, 0, 19, 8, 30);
1103Intent intent = new Intent(Intent.ACTION_INSERT)
1104        .setData(Events.CONTENT_URI)
1105        .putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, beginTime.getTimeInMillis())
1106        .putExtra(CalendarContract.EXTRA_EVENT_END_TIME, endTime.getTimeInMillis())
1107        .putExtra(Events.TITLE, &quot;Yoga&quot;)
1108        .putExtra(Events.DESCRIPTION, &quot;Group class&quot;)
1109        .putExtra(Events.EVENT_LOCATION, &quot;The gym&quot;)
1110        .putExtra(Events.AVAILABILITY, Events.AVAILABILITY_BUSY)
1111        .putExtra(Intent.EXTRA_EMAIL, &quot;rowan@example.com,trevor@example.com&quot;);
1112startActivity(intent);
1113</pre>
1114
1115<h3 id="intent-edit">Using an intent to edit an event</h3>
1116
1117<p>You can update an event directly, as described in <a
1118href="#update-event">Updating events</a>. But using the {@link
1119android.content.Intent#ACTION_EDIT EDIT} Intent allows an application that
1120doesn't have permission to hand off event editing to the Calendar application.
1121When users finish editing their event in Calendar, they're returned to the
1122original application.</p> <p>Here is an example of an intent that sets a new
1123title for a specified event and lets users edit the event in the Calendar.</p>
1124
1125
1126<pre>long eventID = 208;
1127Uri uri = ContentUris.withAppendedId(Events.CONTENT_URI, eventID);
1128Intent intent = new Intent(Intent.ACTION_EDIT)
1129    .setData(uri)
1130    .putExtra(Events.TITLE, &quot;My New Title&quot;);
1131startActivity(intent);</pre>
1132
1133<h3 id="intent-view">Using  intents to view calendar data</h3>
1134<p>Calender Provider offers two different ways to use the {@link android.content.Intent#ACTION_VIEW VIEW} Intent:</p>
1135<ul>
1136  <li>To open the Calendar to a particular date.</li>
1137  <li>To view an event.</li>
1138
1139</ul>
1140<p>Here is an example that shows how to open the Calendar to a particular date:</p>
1141<pre>// A date-time specified in milliseconds since the epoch.
1142long startMillis;
1143...
1144Uri.Builder builder = CalendarContract.CONTENT_URI.buildUpon();
1145builder.appendPath(&quot;time&quot;);
1146ContentUris.appendId(builder, startMillis);
1147Intent intent = new Intent(Intent.ACTION_VIEW)
1148    .setData(builder.build());
1149startActivity(intent);</pre>
1150
1151<p>Here is an example that shows how to open an event for viewing:</p>
1152<pre>long eventID = 208;
1153...
1154Uri uri = ContentUris.withAppendedId(Events.CONTENT_URI, eventID);
1155Intent intent = new Intent(Intent.ACTION_VIEW)
1156   .setData(uri);
1157startActivity(intent);
1158</pre>
1159
1160
1161<h2 id="sync-adapter">Sync Adapters</h2>
1162
1163
1164<p>There are only minor differences in how an application and a sync adapter
1165access the Calendar Provider:</p>
1166
1167<ul>
1168  <li>A sync adapter needs to specify that it's a sync adapter by setting {@link android.provider.CalendarContract#CALLER_IS_SYNCADAPTER} to <code>true</code>.</li>
1169
1170
1171  <li>A sync adapter needs to provide an {@link
1172android.provider.CalendarContract.SyncColumns#ACCOUNT_NAME} and an {@link
1173android.provider.CalendarContract.SyncColumns#ACCOUNT_TYPE} as query parameters in the URI. </li>
1174
1175  <li>A sync adapter has write access to more columns than an application or widget.
1176  For example, an application can only modify a few characteristics of a calendar,
1177  such as its name, display name, visibility setting, and whether the calendar is
1178  synced. By comparison, a sync adapter can access not only those columns, but many others,
1179  such as calendar color, time zone, access level, location, and so on.
1180However, a sync adapter is restricted to the <code>ACCOUNT_NAME</code> and
1181<code>ACCOUNT_TYPE</code> it specified.</li> </ul>
1182
1183<p>Here is a helper method you can use to return a URI for use with a sync adapter:</p>
1184<pre> static Uri asSyncAdapter(Uri uri, String account, String accountType) {
1185    return uri.buildUpon()
1186        .appendQueryParameter(android.provider.CalendarContract.CALLER_IS_SYNCADAPTER,&quot;true&quot;)
1187        .appendQueryParameter(Calendars.ACCOUNT_NAME, account)
1188        .appendQueryParameter(Calendars.ACCOUNT_TYPE, accountType).build();
1189 }
1190</pre>
1191<p>For a sample implementation of a sync adapter (not specifically related to Calendar), see
1192<a href="{@docRoot}resources/samples/SampleSyncAdapter/index.html">SampleSyncAdapter</a>.
1193