Home | History | Annotate | Download | only in providers
      1 page.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
     60 Calendar Provider API allows you to perform query, insert, update, and delete
     61 operations 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
     65 rules vary depending on what type of program is making the calls. This document
     66 focuses primarily on using the Calendar Provider API as an application. For 
     67 a 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
     72 include the proper permissions, described in <a href="#manifest">User
     73 Permissions</a>. To make performing common operations easier, the Calendar
     74 Provider offers a set of intents, as described in <a href="#intents">Calendar
     75 Intents</a>. These intents take users to the Calendar application to insert, view,
     76 and edit events. The user interacts with the Calendar application and then
     77 returns to the original application. Thus your application doesn't need to request permissions,
     78 nor 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 
     83 applications. The content providers offered by the Android platform (including the Calendar Provider) typically expose data as a set of tables based on a
     84 relational database model, where each row is a record and each column is data of
     85 a particular type and meaning. Through the Calendar Provider API, applications
     86 and sync adapters can get read/write access to the database tables that hold a
     87 user's calendar data.</p>
     88 
     89 <p>Every content provider exposes a public URI (wrapped as a 
     90 {@link android.net.Uri} 
     91 object) 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 
     93 URIs for providers begin with the string &quot;content://&quot;.  This
     94 identifies the data as being controlled by a content provider. The Calendar
     95 Provider defines constants for the URIs for each of its classes (tables). These
     96 URIs have the format <code><em>&lt;class&gt;</em>.CONTENT_URI</code>. For
     97 example, {@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
    100 main 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 
    118 the calendar-specific information. Each  row in this table contains the details for
    119 a 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
    125 event-specific information. Each row  in this table has the information for a single
    126 event&mdash;for example, event title, location, start time, end
    127 time, and so on. The event can occur one-time or can recur multiple times. Attendees,
    128 reminders, and extended  properties are stored in separate tables. 
    129 They each have an {@link android.provider.CalendarContract.AttendeesColumns#EVENT_ID} 
    130 that 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
    137 start and end time for each occurrence of an event. Each row in this table
    138 represents a single event occurrence. For one-time events there is a 1:1 mapping
    139 of 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
    146 event attendee (guest) information. Each row represents a single guest of an
    147 event. It specifies the type of guest and the guest's attendance response
    148 for the event.</td>
    149   </tr>
    150   <tr>
    151     <td>{@link android.provider.CalendarContract.Reminders}</td>
    152     
    153     <td>This table holds the
    154 alert/notification data. Each row represents a single alert for an event. An
    155 event can have multiple reminders. The maximum number of reminders per event is
    156 specified in 
    157 {@link android.provider.CalendarContract.CalendarColumns#MAX_REMINDERS}, 
    158 which is set by the sync adapter that
    159 owns  the given calendar. Reminders are specified in minutes before the event
    160 and 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
    166 same time, it's important to provide a good end user experience and
    167 protect the integrity of the calendar and its data. To this end, here are
    168 some 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
    173 in a pre-filled form. After they're done, they're returned to your application.
    174 By designing your application to perform common operations through the Calendar,
    175 you provide users with a consistent, robust user interface. This is the
    176 recommended approach. For more information, see <a href="#intents">Calendar
    177 Intents</a>.</p>
    178 
    179 
    180 <li><strong>Sync adapters.</strong> A sync adapter synchronizes the calendar data
    181 on 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, 
    184 there are columns that are reserved for the sync adapters to use.
    185 The provider and applications should not modify them. In fact, they are not
    186 visible unless they are accessed as a sync adapter. For more information about
    187 sync 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
    195 android.Manifest.permission#READ_CALENDAR} permission in its manifest file. It
    196 must include the {@link android.Manifest.permission#WRITE_CALENDAR} permission
    197 to 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"...>;
    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 
    213 for individual calendars. The following
    214 Calendars columns are writable by both an application and a <a href="#sync-adapter">sync adapter</a>. 
    215 For 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
    234 value of 0 indicates that events associated with this calendar should not be
    235 shown.  A value of 1 indicates that events associated with this calendar should
    236 be shown. This value affects the generation of rows in the {@link
    237 android.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
    245 events stored on the device. A value of 0 says do not sync this calendar or
    246 store its events on the device.  A value of 1 says sync events for this calendar
    247 and 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
    254 user. For simplicity's sake, in this example the query operation is shown in the
    255 user interface thread ("main thread"). In practice, this should be done in an asynchronous
    256 thread 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 
    258 reading 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.
    265 public 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.
    273 private static final int PROJECTION_ID_INDEX = 0;
    274 private static final int PROJECTION_ACCOUNT_NAME_INDEX = 1;
    275 private static final int PROJECTION_DISPLAY_NAME_INDEX = 2;
    276 private static final int PROJECTION_OWNER_ACCOUNT_INDEX = 3;</pre>
    277   
    278 
    279 <div class="sidebox-wrapper"> <div class="sidebox"> <h3>Why must you include
    280 ACCOUNT_TYPE?</h3> <p>If you query on a {@link
    281 android.provider.CalendarContract.Calendars#ACCOUNT_NAME
    282 Calendars.ACCOUNT_NAME}, you must also include 
    283 {@link android.provider.CalendarContract.Calendars#ACCOUNT_TYPE Calendars.ACCOUNT_TYPE}
    284 in the selection. That is because a given account is
    285 only 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
    287 account 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
    289 android.provider.CalendarContract#ACCOUNT_TYPE_LOCAL} for calendars not
    290 associated with a device account. {@link
    291 android.provider.CalendarContract#ACCOUNT_TYPE_LOCAL} accounts do not get
    292 synced.</p> </div> </div> 
    293 
    294 
    295 <p> In the next part of the example, you construct your query. The selection
    296 specifies the criteria for the query. In this example the query is looking for
    297 calendars that have the <code>ACCOUNT_NAME</code>
    298 "sampleuser (a] google.com", the <code>ACCOUNT_TYPE</code>
    299 "com.google", and the <code>OWNER_ACCOUNT</code>
    300 "sampleuser (a] google.com". If you want to see all calendars that a user
    301 has viewed, not just calendars the user owns, omit the <code>OWNER_ACCOUNT</code>.
    302 The query returns a {@link android.database.Cursor}
    303 object that you can use to traverse the result set returned by the database
    304 query. For more discussion of using queries in content providers, 
    305 see <a href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a>.</p>
    306 
    307 
    308 <pre>// Run query
    309 Cursor cur = null;
    310 ContentResolver cr = getContentResolver();
    311 Uri uri = Calendars.CONTENT_URI;   
    312 String selection = "((" + Calendars.ACCOUNT_NAME + " = ?) AND (" 
    313                         + Calendars.ACCOUNT_TYPE + " = ?) AND ("
    314                         + Calendars.OWNER_ACCOUNT + " = ?))";
    315 String[] selectionArgs = new String[] {"sampleuser (a] gmail.com", "com.google",
    316         "sampleuser (a] gmail.com"}; 
    317 // Submit the query and get a Cursor object back. 
    318 cur = 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
    321 constants that were set up at the beginning of the example to return the values
    322 for each field.</p>
    323     
    324 <pre>// Use the cursor to step through the returned records
    325 while (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
    346 android.provider.BaseColumns#_ID} of the calendar either as an appended ID to
    347 the Uri 
    348 
    349 ({@link android.content.ContentUris#withAppendedId(android.net.Uri,long) withAppendedId()}) 
    350 or as the first selection item. The  selection
    351 should start with <code>&quot;_id=?&quot;</code>, and the first
    352 <code>selectionArg</code> should be  the {@link
    353 android.provider.BaseColumns#_ID} of the calendar. 
    354 You can also do updates by encoding the ID in the URI. This example changes a
    355 calendar's display name using the 
    356 ({@link android.content.ContentUris#withAppendedId(android.net.Uri,long) withAppendedId()}) 
    357 approach:</p>
    358 
    359 <pre>private static final String DEBUG_TAG = "MyActivity";
    360 ...
    361 long calID = 2;
    362 ContentValues values = new ContentValues();
    363 // The new display name for the calendar
    364 values.put(Calendars.CALENDAR_DISPLAY_NAME, &quot;Trevor's Calendar&quot;);
    365 Uri updateUri = ContentUris.withAppendedId(Calendars.CONTENT_URI, calID);
    366 int rows = getContentResolver().update(updateUri, values, null, null);
    367 Log.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
    372 should only insert new calendars as a sync adapter. For the most part,
    373 applications can only make superficial changes to calendars, such as changing the display name. If
    374 an application needs to create a local calendar, it can do this by performing
    375 the calendar insertion as a sync adapter, using an {@link
    376 android.provider.CalendarContract.SyncColumns#ACCOUNT_TYPE} of {@link
    377 android.provider.CalendarContract#ACCOUNT_TYPE_LOCAL}.
    378 {@link android.provider.CalendarContract#ACCOUNT_TYPE_LOCAL} 
    379 is a special account type for calendars that are not
    380 associated with a device account. Calendars of this type are not synced to a server. For a
    381 discussion 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
    386 for individual events. To add, update, or delete  events, an application must
    387 include 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
    391 adapter. For a full list of supported fields, see the {@link
    392 android.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
    439 href="http://tools.ietf.org/html/rfc5545#section-3.8.2.5">RFC5545</a> format.
    440 For example, a value of <code>&quot;PT1H&quot;</code> states that the event
    441 should last one hour, and a value of <code>&quot;P2W&quot;</code> indicates a
    442 duration 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
    450 the local time zone. A value of 0 indicates it is a regular event that may start
    451 and 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
    461 example, <code>&quot;FREQ=WEEKLY;COUNT=10;WKST=SU&quot;</code>. You can find
    462 more examples <a
    463 href="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
    473 repeating occurrences. For more discussion, see the <a
    474 href="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 
    481 scheduled 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
    502 href="#intent-insert">Using an intent to insert an event</a>. However, if you
    503 need to, you can insert events directly. This section describes how to do
    504 this.</p>
    505 
    506 
    507 <p>Here are the rules for inserting a new event: </p>
    508 <ul>
    509 
    510   <li>You must include  {@link
    511 android.provider.CalendarContract.EventsColumns#CALENDAR_ID} and {@link
    512 android.provider.CalendarContract.EventsColumns#DTSTART}.</li>
    513 
    514 <li>You must include an {@link
    515 android.provider.CalendarContract.EventsColumns#EVENT_TIMEZONE}. To get a list
    516 of the system's installed time zone IDs, use {@link
    517 java.util.TimeZone#getAvailableIDs()}. Note that this rule does not apply if
    518 you're inserting an event through the {@link
    519 android.content.Intent#ACTION_INSERT INSERT} Intent, described in <a
    520 href="#intent-insert">Using an intent to insert an event</a>&mdash;in that
    521 scenario, a default time zone is supplied.</li>
    522   
    523   <li>For non-recurring events, you must include {@link
    524 android.provider.CalendarContract.EventsColumns#DTEND}. </li>
    525   
    526   
    527   <li>For recurring events, you must include a {@link
    528 android.provider.CalendarContract.EventsColumns#DURATION} in addition to  {@link
    529 android.provider.CalendarContract.EventsColumns#RRULE} or {@link
    530 android.provider.CalendarContract.EventsColumns#RDATE}. Note that this rule does not apply if
    531 you're inserting an event through the {@link
    532 android.content.Intent#ACTION_INSERT INSERT} Intent, described in <a
    533 href="#intent-insert">Using an intent to insert an event</a>&mdash;in that
    534 scenario, you can use an {@link
    535 android.provider.CalendarContract.EventsColumns#RRULE} in conjunction with {@link android.provider.CalendarContract.EventsColumns#DTSTART} and {@link android.provider.CalendarContract.EventsColumns#DTEND}, and the Calendar application 
    536 converts 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
    541 thread for simplicity. In practice, inserts and updates should be done in an
    542 asynchronous thread to move the action into a background thread. For more
    543 information, see {@link android.content.AsyncQueryHandler}.</p>
    544 
    545 
    546 <pre>
    547 long calID = 3;
    548 long startMillis = 0; 
    549 long endMillis = 0;     
    550 Calendar beginTime = Calendar.getInstance();
    551 beginTime.set(2012, 9, 14, 7, 30);
    552 startMillis = beginTime.getTimeInMillis();
    553 Calendar endTime = Calendar.getInstance();
    554 endTime.set(2012, 9, 14, 8, 45);
    555 endMillis = endTime.getTimeInMillis();
    556 ...
    557 
    558 ContentResolver cr = getContentResolver();
    559 ContentValues values = new ContentValues();
    560 values.put(Events.DTSTART, startMillis);
    561 values.put(Events.DTEND, endMillis);
    562 values.put(Events.TITLE, &quot;Jazzercise&quot;);
    563 values.put(Events.DESCRIPTION, &quot;Group workout&quot;);
    564 values.put(Events.CALENDAR_ID, calID);
    565 values.put(Events.EVENT_TIMEZONE, "America/Los_Angeles");
    566 Uri uri = cr.insert(Events.CONTENT_URI, values);
    567 
    568 // get the event ID that is the last element in the Uri
    569 long 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
    576 ID after the event is created. This is the easiest way to get an event ID. You often
    577 need the event ID to perform other calendar operations&mdash;for example, to add
    578 attendees 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
    584 that you use an {@link android.content.Intent#ACTION_EDIT EDIT} Intent, as
    585 described in <a href="#intent-edit">Using an intent to edit an  event</a>.
    586 However, if you need to, you can edit events directly. To perform an update of
    587 an Event, you can provide the <code>_ID</code> of the 
    588 event either as an appended ID to the Uri ({@link
    589 android.content.ContentUris#withAppendedId(android.net.Uri,long) withAppendedId()}) 
    590 or as the first selection item. 
    591 The 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
    593 also do updates using a selection with no ID. Here is an example of updating an
    594 event. It changes the title of the event using the 
    595 {@link android.content.ContentUris#withAppendedId(android.net.Uri,long) withAppendedId()}
    596 approach:</p>
    597 
    598 
    599 <pre>private static final String DEBUG_TAG = "MyActivity";
    600 ...
    601 long eventID = 188;
    602 ...
    603 ContentResolver cr = getContentResolver();
    604 ContentValues values = new ContentValues();
    605 Uri updateUri = null;
    606 // The new title for the event
    607 values.put(Events.TITLE, &quot;Kickboxing&quot;); 
    608 myUri = ContentUris.withAppendedId(Events.CONTENT_URI, eventID);
    609 int rows = getContentResolver().update(updateUri, values, null, null);
    610 Log.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
    615 android.provider.BaseColumns#_ID} as an appended  ID on the URI, or by using
    616 standard selection. If you use an appended ID, you can't also do a selection.
    617 There are two versions of delete: as an application and as a sync adapter. An
    618 application delete sets the <em>deleted</em> column to 1. This flag that tells
    619 the sync adapter that the row was deleted and that this deletion should be
    620 propagated to the server. A sync adapter delete removes the event from the
    621 database along with all its associated data. Here is an example of application
    622 deleting an event through its {@link android.provider.BaseColumns#_ID}:</p>
    623 
    624 
    625 <pre>private static final String DEBUG_TAG = "MyActivity";
    626 ...
    627 long eventID = 201;
    628 ...
    629 ContentResolver cr = getContentResolver();
    630 ContentValues values = new ContentValues();
    631 Uri deleteUri = null;
    632 deleteUri = ContentUris.withAppendedId(Events.CONTENT_URI, eventID);
    633 int rows = getContentResolver().delete(deleteUri, null, null);
    634 Log.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
    640 represents a single attendee or guest of an event. Calling 
    641 {@link android.provider.CalendarContract.Reminders#query(android.content.ContentResolver, long, java.lang.String[]) query()} 
    642 returns a list of attendees for  the
    643 event with the given {@link android.provider.CalendarContract.AttendeesColumns#EVENT_ID}. 
    644 This  {@link android.provider.CalendarContract.AttendeesColumns#EVENT_ID} 
    645 must match the {@link
    646 android.provider.BaseColumns#_ID} of a particular event.</p> 
    647 
    648 <p>The following table lists the
    649 writable fields. When inserting a new attendee, you must include all of them 
    650 except <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} 
    708 is required:</p>
    709 
    710 <pre>
    711 long eventID = 202;
    712 ...
    713 ContentResolver cr = getContentResolver();
    714 ContentValues values = new ContentValues();
    715 values.put(Attendees.ATTENDEE_NAME, &quot;Trevor&quot;);
    716 values.put(Attendees.ATTENDEE_EMAIL, &quot;trevor (a] example.com&quot;);
    717 values.put(Attendees.ATTENDEE_RELATIONSHIP, Attendees.RELATIONSHIP_ATTENDEE);
    718 values.put(Attendees.ATTENDEE_TYPE, Attendees.TYPE_OPTIONAL);
    719 values.put(Attendees.ATTENDEE_STATUS, Attendees.ATTENDEE_STATUS_INVITED);
    720 values.put(Attendees.EVENT_ID, eventID);
    721 Uri 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
    727 represents 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
    729 event 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
    734 be included when inserting a new reminder. Note that sync adapters specify the
    735 types of reminders they support in the {@link
    736 android.provider.CalendarContract.Calendars} table. See 
    737 {@link android.provider.CalendarContract.CalendarColumns#ALLOWED_REMINDERS} 
    738 for 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
    769 minutes before the event.</p>
    770 <pre>
    771 long eventID = 221;
    772 ...
    773 ContentResolver cr = getContentResolver();
    774 ContentValues values = new ContentValues();
    775 values.put(Reminders.MINUTES, 15);
    776 values.put(Reminders.EVENT_ID, eventID);
    777 values.put(Reminders.METHOD, Reminders.METHOD_ALERT);
    778 Uri 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
    784 start and end time for occurrences of an event. Each row in this table
    785 represents a single event occurrence. The instances table is not writable and only
    786 provides 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 
    789 that time zone is defined by 
    790 {@link android.provider.CalendarContract.CalendarCache#KEY_TIMEZONE_TYPE} 
    791 and 
    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
    812 zone. 
    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 the
    820 Calendar'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
    836 Calendar'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
    846 in the URI. In this example, {@link android.provider.CalendarContract.Instances}
    847 gets access to the {@link
    848 android.provider.CalendarContract.EventsColumns#TITLE} field through its
    849 implementation of the {@link android.provider.CalendarContract.EventsColumns} interface. 
    850 In other words, {@link
    851 android.provider.CalendarContract.EventsColumns#TITLE} is returned through a
    852 database view, not through querying the raw {@link
    853 android.provider.CalendarContract.Instances} table.</p>
    854 
    855 <pre>
    856 private static final String DEBUG_TAG = "MyActivity";
    857 public 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.
    864 private static final int PROJECTION_ID_INDEX = 0;
    865 private static final int PROJECTION_BEGIN_INDEX = 1;
    866 private static final int PROJECTION_TITLE_INDEX = 2;
    867 ...
    868 
    869 // Specify the date range you want to search for recurring
    870 // event instances
    871 Calendar beginTime = Calendar.getInstance();
    872 beginTime.set(2011, 9, 23, 8, 0);
    873 long startMillis = beginTime.getTimeInMillis();
    874 Calendar endTime = Calendar.getInstance();
    875 endTime.set(2011, 10, 24, 8, 0);
    876 long endMillis = endTime.getTimeInMillis();
    877   
    878 Cursor cur = null;
    879 ContentResolver cr = getContentResolver();
    880 
    881 // The ID of the recurring event whose instances you are searching
    882 // for in the Instances table
    883 String selection = Instances.EVENT_ID + " = ?";
    884 String[] selectionArgs = new String[] {"207"};
    885 
    886 // Construct the query with the desired date range.
    887 Uri.Builder builder = Instances.CONTENT_URI.buildUpon();
    888 ContentUris.appendId(builder, startMillis);
    889 ContentUris.appendId(builder, endMillis);
    890 
    891 // Submit the query
    892 cur =  cr.query(builder.build(), 
    893     INSTANCE_PROJECTION, 
    894     selection, 
    895     selectionArgs, 
    896     null);
    897    
    898 while (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}. 
    933 For 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}. 
    947 For 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}. 
    964 For 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}. 
    984 For 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
   1007 CalendarContract.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
   1012 CalendarContract.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
   1018 CalendarContract.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
   1024 Events.EVENT_LOCATION}</td>
   1025     
   1026     <td>Location of the event.</td>
   1027   </tr>
   1028   <tr>
   1029     <td>{@link android.provider.CalendarContract.EventsColumns#DESCRIPTION
   1030 Events.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
   1047 Events.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
   1053 Events.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
   1064 lets your application hand off the event insertion task to the Calendar itself.
   1065 With this approach, your application doesn't even need to have the {@link
   1066 android.Manifest.permission#WRITE_CALENDAR} permission included in its <a
   1067 href="#manifest">manifest file</a>.</p>
   1068 
   1069   
   1070 <p>When users run an application that uses this approach, the application sends
   1071 them to the Calendar to finish adding the event. The {@link
   1072 android.content.Intent#ACTION_INSERT INSERT} Intent uses extra fields to
   1073 pre-populate a form with the details of the event in the Calendar. Users can
   1074 then cancel the event, edit the form as needed, or save the event to their
   1075 calendars.</p>
   1076   
   1077 
   1078 
   1079 <p>Here is a code snippet that schedules an event on January 19, 2012, that runs
   1080 from 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
   1087 android.provider.CalendarContract#EXTRA_EVENT_BEGIN_TIME
   1088 CalendarContract.EXTRA_EVENT_BEGIN_TIME} and {@link
   1089 android.provider.CalendarContract#EXTRA_EVENT_END_TIME
   1090 CalendarContract.EXTRA_EVENT_END_TIME} extra fields to pre-populate the form
   1091 with the time of the event. The values  for these times must be in UTC milliseconds
   1092 from the epoch.</li>
   1093   
   1094   <li>It uses the {@link android.content.Intent#EXTRA_EMAIL Intent.EXTRA_EMAIL}
   1095 extra field to provide a comma-separated list of invitees, specified by email address.</li>
   1096   
   1097 </ul>
   1098 <pre>
   1099 Calendar beginTime = Calendar.getInstance();
   1100 beginTime.set(2012, 0, 19, 7, 30);
   1101 Calendar endTime = Calendar.getInstance();
   1102 endTime.set(2012, 0, 19, 8, 30);
   1103 Intent 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 (a] example.com,trevor (a] example.com&quot;);
   1112 startActivity(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
   1118 href="#update-event">Updating events</a>. But using the {@link
   1119 android.content.Intent#ACTION_EDIT EDIT} Intent allows an application that
   1120 doesn't have permission to hand off event editing to the Calendar application.
   1121 When users finish editing their event in Calendar, they're returned to the
   1122 original application.</p> <p>Here is an example of an intent that sets a new
   1123 title for a specified event and lets users edit the event in the Calendar.</p>
   1124 
   1125 
   1126 <pre>long eventID = 208;
   1127 Uri uri = ContentUris.withAppendedId(Events.CONTENT_URI, eventID);
   1128 Intent intent = new Intent(Intent.ACTION_EDIT)
   1129     .setData(uri)
   1130     .putExtra(Events.TITLE, &quot;My New Title&quot;);
   1131 startActivity(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.
   1142 long startMillis;
   1143 ...
   1144 Uri.Builder builder = CalendarContract.CONTENT_URI.buildUpon();
   1145 builder.appendPath(&quot;time&quot;);
   1146 ContentUris.appendId(builder, startMillis);
   1147 Intent intent = new Intent(Intent.ACTION_VIEW)
   1148     .setData(builder.build());
   1149 startActivity(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 ...
   1154 Uri uri = ContentUris.withAppendedId(Events.CONTENT_URI, eventID);
   1155 Intent intent = new Intent(Intent.ACTION_VIEW)
   1156    .setData(uri);
   1157 startActivity(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
   1165 access 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
   1172 android.provider.CalendarContract.SyncColumns#ACCOUNT_NAME} and an {@link
   1173 android.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.
   1180 However, 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