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 "content://". 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><class></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—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 <?xml version="1.0" encoding="utf-8"?> 201 <manifest xmlns:android="http://schemas.android.com/apk/res/android"...> 202 <uses-sdk android:minSdkVersion="14" /> 203 <uses-permission android:name="android.permission.READ_CALENDAR" /> 204 <uses-permission android:name="android.permission.WRITE_CALENDAR" /> 205 ... 206 </manifest> 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>"_id=?"</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, "Trevor's Calendar"); 354 Uri updateUri = ContentUris.withAppendedId(Calendars.CONTENT_URI, calID); 355 int rows = getContentResolver().update(updateUri, values, null, null); 356 Log.i(DEBUG_TAG, "Rows updated: " + 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>"PT1H"</code> states that the event 430 should last one hour, and a value of <code>"P2W"</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>"FREQ=WEEKLY;COUNT=10;WKST=SU"</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>—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>—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, "Jazzercise"); 552 values.put(Events.DESCRIPTION, "Group workout"); 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—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>"_id=?"</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, "Kickboxing"); 597 myUri = ContentUris.withAppendedId(Events.CONTENT_URI, eventID); 598 int rows = getContentResolver().update(updateUri, values, null, null); 599 Log.i(DEBUG_TAG, "Rows updated: " + 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, "Rows deleted: " + 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, "Trevor"); 705 values.put(Attendees.ATTENDEE_EMAIL, "trevor (a] example.com"); 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/<ms_since_epoch></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><ms_since_epoch></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/<event_id></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><event_id></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/<event_id></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><event_id></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, "Yoga") 1097 .putExtra(Events.DESCRIPTION, "Group class") 1098 .putExtra(Events.EVENT_LOCATION, "The gym") 1099 .putExtra(Events.AVAILABILITY, Events.AVAILABILITY_BUSY) 1100 .putExtra(Intent.EXTRA_EMAIL, "rowan (a] example.com,trevor (a] example.com"); 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, "My New Title"); 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("time"); 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,"true") 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