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