summaryrefslogtreecommitdiffstats
path: root/docs/html/guide/topics/providers/calendar-provider.jd
blob: d30dda423ec5c95b720b71fe1572a00f1d3d61f6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
page.title=Calendar Provider
@jd:body

<div id="qv-wrapper">
<div id="qv">
    <h2>In this document</h2>
    <ol>
  <li><a href="#overview">Basics</a></li>
  <li><a href="#manifest">User Permissions</a></li>
  <li><a href="#calendar">Calendars table</a>
<ol>
      <li><a href="#query">Querying a calendar</a></li>
      <li><a href="#modify-calendar">Modifying a calendar</a></li>
      <li><a href="#insert-calendar">Inserting a calendar</a></li>
    </ol>
  </li>
  <li><a href="#events">Events table</a>
<ol>
      <li><a href="#add-event">Adding Events</a></li>
      <li><a href="#update-event">Updating Events</a></li>
      <li><a href="#delete-event">Deleting Events</a></li>
    </ol>
  </li>
  <li><a href="#attendees">Attendees table</a>
<ol>
      <li><a href="#add-attendees">Adding Attendees</a></li>
    </ol>
  </li>
  <li><a href="#reminders">Reminders table</a>
<ol>
      <li><a href="#add-reminders">Adding Reminders</a></li>
    </ol>
  </li>
  <li><a href="#instances">Instances table</a>
  <ol>
      <li><a href="#query-instances">Querying the Instances table</a></li>
  </ol></li>
  <li><a href="#intents">Calendar Intents</a>
  <ol>
      <li><a href="#intent-insert">Using an intent to insert an event</a></li>
      <li><a href="#intent-edit">Using an intent to edit an event</a></li>
      <li><a href="#intent-view">Using intents to view calendar data</a></li>
    </ol>
  </li>
  
  <li><a href="#sync-adapter">Sync Adapters</a></li>
</ol>

    <h2>Key classes</h2>
    <ol>
      <li>{@link android.provider.CalendarContract.Calendars}</li>
      <li>{@link android.provider.CalendarContract.Events}</li>
      <li>{@link android.provider.CalendarContract.Attendees}</li>
      <li>{@link android.provider.CalendarContract.Reminders}</li>
    </ol>
</div>
</div>

<p>The Calendar Provider is a repository for a user's calendar events. The
Calendar Provider API allows you to perform query, insert, update, and delete
operations on calendars, events, attendees, reminders, and so on.</p>


<p>The Calender Provider API can be used by applications and sync adapters. The
rules vary depending on what type of program is making the calls. This document
focuses primarily on using the Calendar Provider API as an application. For 
a discussion of how sync adapters are different, see 
<a href="#sync-adapter">Sync Adapters</a>.</p>


<p>Normally, to read or write calendar data, an application's manifest must
include the proper permissions, described in <a href="#manifest">User
Permissions</a>. To make performing common operations easier, the Calendar
Provider offers a set of intents, as described in <a href="#intents">Calendar
Intents</a>. These intents take users to the Calendar application to insert, view,
and edit events. The user interacts with the Calendar application and then
returns to the original application. Thus your application doesn't need to request permissions,
nor does it need to provide a user interface to view or create events.</p>

<h2 id="overview">Basics</h2>

<p><a href="{@docRoot}guide/topics/providers/content-providers.html">Content providers</a> store data and make it accessible to 
applications. The content providers offered by the Android platform (including the Calendar Provider) typically expose data as a set of tables based on a
relational database model, where each row is a record and each column is data of
a particular type and meaning. Through the Calendar Provider API, applications
and sync adapters can get read/write access to the database tables that hold a
user's calendar data.</p>

<p>Every content provider exposes a public URI (wrapped as a 
{@link android.net.Uri} 
object) that uniquely identifies its data set.  A content provider that controls
 multiple data sets (multiple tables) exposes a separate URI for each one.  All 
URIs for providers begin with the string &quot;content://&quot;.  This
identifies the data as being controlled by a content provider. The Calendar
Provider defines constants for the URIs for each of its classes (tables). These
URIs have the format <code><em>&lt;class&gt;</em>.CONTENT_URI</code>. For
example, {@link android.provider.CalendarContract.Events#CONTENT_URI Events.CONTENT_URI}.</p>

<p>Figure 1 shows a graphical representation of the Calendar Provider data model. It shows the
main tables and the fields that link them to each other.</p>

<img src="{@docRoot}images/providers/datamodel.png" alt="Calendar Provider Data Model"/>
<p class="img-caption"><strong>Figure 1.</strong> Calendar Provider data model.</p>

<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>

<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>

<table>
  <tr>
    <th>Table (Class)</th>
    <th>Description</th>
  </tr>
  <tr>
    <td><p>{@link android.provider.CalendarContract.Calendars}</p></td>
    
    <td>This table holds 
the calendar-specific information. Each  row in this table contains the details for
a single calendar, such as the  name, color, sync information, and so on.</td>
  </tr>
  <tr>
    <td>{@link android.provider.CalendarContract.Events}</td>
    
    <td>This table holds the
event-specific information. Each row  in this table has the information for a single
event&mdash;for example, event title, location, start time, end
time, and so on. The event can occur one-time or can recur multiple times. Attendees,
reminders, and extended  properties are stored in separate tables. 
They each have an {@link android.provider.CalendarContract.AttendeesColumns#EVENT_ID} 
that references the {@link android.provider.BaseColumns#_ID} in the Events table.</td>

  </tr>
  <tr>
    <td>{@link android.provider.CalendarContract.Instances}</td>
    
    <td>This table holds the
start and end time for each occurrence of an event. Each row in this table
represents a single event occurrence. For one-time events there is a 1:1 mapping
of instances to events. For recurring events, multiple rows are automatically
 generated that correspond to multiple occurrences of that event.</td>
  </tr>
  <tr>
    <td>{@link android.provider.CalendarContract.Attendees}</td>
    
    <td>This table holds the
event attendee (guest) information. Each row represents a single guest of an
event. It specifies the type of guest and the guest's attendance response
for the event.</td>
  </tr>
  <tr>
    <td>{@link android.provider.CalendarContract.Reminders}</td>
    
    <td>This table holds the
alert/notification data. Each row represents a single alert for an event. An
event can have multiple reminders. The maximum number of reminders per event is
specified in 
{@link android.provider.CalendarContract.CalendarColumns#MAX_REMINDERS}, 
which is set by the sync adapter that
owns  the given calendar. Reminders are specified in minutes before the event
and have a method that determines how the user will be alerted.</td>
  </tr>
  
</table>

<p>The Calendar Provider API is designed to be flexible and powerful. At the
same time, it's important to provide a good end user experience and
protect the integrity of the calendar and its data. To this end, here are
some things to keep in mind when using the API:</p>

<ul>

<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
in a pre-filled form. After they're done, they're returned to your application.
By designing your application to perform common operations through the Calendar,
you provide users with a consistent, robust user interface. This is the
recommended approach. For more information, see <a href="#intents">Calendar
Intents</a>.</p>


<li><strong>Sync adapters.</strong> A sync adapter synchronizes the calendar data
on a user's device with another server or data source. In the 
{@link android.provider.CalendarContract.Calendars} and
{@link android.provider.CalendarContract.Events} tables, 
there are columns that are reserved for the sync adapters to use.
The provider and applications should not modify them. In fact, they are not
visible unless they are accessed as a sync adapter. For more information about
sync adapters, see <a href="#sync-adapter">Sync Adapters</a>.</li>

</ul>


<h2 id="manifest">User Permissions</h2>

<p>To read calendar data, an application must include the {@link
android.Manifest.permission#READ_CALENDAR} permission in its manifest file. It
must include the {@link android.Manifest.permission#WRITE_CALENDAR} permission
to delete, insert or update calendar data:</p>

<pre>
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;manifest xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;...&gt;
    &lt;uses-sdk android:minSdkVersion=&quot;14&quot; /&gt;
    &lt;uses-permission android:name=&quot;android.permission.READ_CALENDAR&quot; /&gt;
    &lt;uses-permission android:name=&quot;android.permission.WRITE_CALENDAR&quot; /&gt;
    ...
&lt;/manifest&gt;
</pre>


<h2 id="calendar">Calendars Table</h2>

<p>The {@link android.provider.CalendarContract.Calendars} table contains details 
for individual calendars. The following
Calendars columns are writable by both an application and a <a href="#sync-adapter">sync adapter</a>. 
For a full list of supported fields, see the
{@link android.provider.CalendarContract.Calendars} reference.</p>
<table>
  <tr>
    <th>Constant</th>
    <th>Description</th>
  </tr>
  <tr>
    <td>{@link android.provider.CalendarContract.Calendars#NAME}</td>
    <td>The name of the calendar.</td>
  </tr>
  <tr>
    <td>{@link android.provider.CalendarContract.Calendars#CALENDAR_DISPLAY_NAME}</td>
    <td>The name of this calendar that is displayed to the user.</td>
  </tr>
  <tr>
    <td>{@link android.provider.CalendarContract.Calendars#VISIBLE}</td>
    
    <td>A boolean indicating whether the calendar is selected to be displayed. A
value of 0 indicates that events associated with this calendar should not be
shown.  A value of 1 indicates that events associated with this calendar should
be shown. This value affects the generation of rows in the {@link
android.provider.CalendarContract.Instances} table.</td>


  </tr>
  <tr>
    <td>{@link android.provider.CalendarContract.CalendarColumns#SYNC_EVENTS}</td>
    
    <td>A boolean indicating whether the calendar should be synced and have its
events stored on the device. A value of 0 says do not sync this calendar or
store its events on the device.  A value of 1 says sync events for this calendar
and store its events on the device.</td>
  </tr>
</table>

<h3 id="query">Querying a calendar</h3>

<p>Here is an example that shows how to get all the calendars for a particular
user. For simplicity's sake, in this example the query operation is shown in the
user interface thread ("main thread"). In practice, this should be done in an asynchronous
thread instead of on the main thread. For more discussion, see 
<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}.
</p>


<pre>
  // Projection array. Creating indices for this array instead of doing
  // dynamic lookups improves performance.
  public static final String[] EVENT_PROJECTION = new String[] {
    Calendars._ID,                           // 0
    Calendars.ACCOUNT_NAME,                  // 1
    Calendars.CALENDAR_DISPLAY_NAME          // 2
  };
  
  // The indices for the projection array above.
  private static final int PROJECTION_ID_INDEX = 0;
  private static final int PROJECTION_ACCOUNT_NAME_INDEX = 1;
  private static final int PROJECTION_DISPLAY_NAME_INDEX = 2;</pre>
  

<div class="sidebox-wrapper"> <div class="sidebox"> <h3>Why must you include
ACCOUNT_TYPE?</h3> <p>If you query on a {@link
android.provider.CalendarContract.Calendars#ACCOUNT_NAME
Calendars.ACCOUNT_NAME}, you must also include 
{@link android.provider.CalendarContract.Calendars#ACCOUNT_TYPE Calendars.ACCOUNT_TYPE}
in the selection. That is because a given account is
only considered unique given both its <code>ACCOUNT_NAME</code> and its
<code>ACCOUNT_TYPE</code>. The <code>ACCOUNT_TYPE</code> is the string corresponding to the
account authenticator that was used when the account was registered with the
{@link android.accounts.AccountManager}. There is also a special type of account called {@link
android.provider.CalendarContract#ACCOUNT_TYPE_LOCAL} for calendars not
associated with a device account. {@link
android.provider.CalendarContract#ACCOUNT_TYPE_LOCAL} accounts do not get
synced.</p> </div> </div> 


<p> In the next part of the example, you construct your query. The selection
specifies the criteria for the query. In this example the query is looking for
all calendars that have the <code>ACCOUNT_NAME</code>
"sampleuser@google.com" and the <code>ACCOUNT_TYPE</code>
"com.google". The query returns a {@link android.database.Cursor}
object that you can use to traverse the result set returned by the database
query. For more discussion of using queries in content providers, see <a href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a>.</p>


<pre>// Run query
Cursor cur = null;
ContentResolver cr = getContentResolver();
Uri uri = Calendars.CONTENT_URI;   
String selection = "((" + Calendars.ACCOUNT_NAME + " = ?) AND (" 
                        + Calendars.ACCOUNT_TYPE + " = ?))";
String[] selectionArgs = new String[] {"sampleuser@gmail.com", "com.google"}; 
// Submit the query and get a Cursor object back. 
cur = cr.query(uri, EVENT_PROJECTION, selection, selectionArgs, null);</pre>

<p>This next section uses the cursor to step through the result set. It uses the
constants that were set up at the beginning of the example to return the values
for each field.</p>
    
<pre>// Use the cursor to step through the returned records
while (cur.moveToNext()) {
    long calID = 0;
    String displayName = null;
    String accountName = null;        
      
    // Get the field values
    calID = cur.getLong(PROJECTION_ID_INDEX);
    displayName = cur.getString(PROJECTION_DISPLAY_NAME_INDEX);
    accountName = cur.getString(PROJECTION_ACCOUNT_NAME_INDEX);
              
    // Do something with the values...

   ...
}
</pre>
  
<h3 id="modify-calendar">Modifying a calendar</h3>

<p>To perform an update of an calendar, you can provide the {@link
android.provider.BaseColumns#_ID} of the calendar either as an appended ID to
the Uri 

({@link android.content.ContentUris#withAppendedId(android.net.Uri,long) withAppendedId()}) 
or as the first selection item. The  selection
should start with <code>&quot;_id=?&quot;</code>, and the first
<code>selectionArg</code> should be  the {@link
android.provider.BaseColumns#_ID} of the calendar. 
You can also do updates by encoding the ID in the URI. This example changes a
calendar's display name using the 
({@link android.content.ContentUris#withAppendedId(android.net.Uri,long) withAppendedId()}) 
approach:</p>

<pre>private static final String DEBUG_TAG = "MyActivity";
...
long calID = 2;
ContentValues values = new ContentValues();
// The new display name for the calendar
values.put(Calendars.CALENDAR_DISPLAY_NAME, &quot;Trevor's Calendar&quot;);
Uri updateUri = ContentUris.withAppendedId(Calendars.CONTENT_URI, calID);
int rows = getContentResolver().update(updateUri, values, null, null);
Log.i(DEBUG_TAG, &quot;Rows updated: &quot; + rows);</pre>

<h3 id="insert-calendar">Inserting a calendar</h2>

<p>Calendars are  designed to be primarily managed by a sync adapter, so you
should only insert new calendars as a sync adapter. For the most part,
applications can only make superficial changes to calendars, such as changing the display name. If
an application needs to create a local calendar, it can do this by performing
the calendar insertion as a sync adapter, using an {@link
android.provider.CalendarContract.SyncColumns#ACCOUNT_TYPE} of {@link
android.provider.CalendarContract#ACCOUNT_TYPE_LOCAL}.
{@link android.provider.CalendarContract#ACCOUNT_TYPE_LOCAL} 
is a special account type for calendars that are not
associated with a device account. Calendars of this type are not synced to a server. For a
discussion of sync adapters, see <a href="#sync-adapter">Sync Adapters</a>.</p>

<h2 id="events">Events Table</h2>

<p>The {@link android.provider.CalendarContract.Events} table contains details
for individual events. To add, update, or delete  events, an application must
include the {@link android.Manifest.permission#WRITE_CALENDAR} permission in its
<a href="#manifest">manifest file</a>.</p>

<p>The following Events columns are writable by both an application and a sync
adapter. For a full list of supported fields, see the {@link
android.provider.CalendarContract.Events} reference.</p>

<table>
  <tr>
    <th>Constant</th>
    <th>Description</th>
  </tr>
  <tr>
    <td>{@link android.provider.CalendarContract.EventsColumns#CALENDAR_ID}</td>
    <td>The {@link android.provider.BaseColumns#_ID} of the calendar the event belongs to.</td>
  </tr>
  <tr>
    <td>{@link android.provider.CalendarContract.EventsColumns#ORGANIZER}</td>
    <td>Email of the organizer (owner) of the event.</td>
  </tr>
  <tr>
    <td>{@link android.provider.CalendarContract.EventsColumns#TITLE}</td>
    <td>The title of the event.</td>
  </tr>
  <tr>
    <td>{@link android.provider.CalendarContract.EventsColumns#EVENT_LOCATION}</td>
    <td>Where the event takes place. </td>
  </tr>
  <tr>
    <td>{@link android.provider.CalendarContract.EventsColumns#DESCRIPTION}</td>
    <td>The description of the event.</td>
  </tr>
  <tr>
    <td>{@link android.provider.CalendarContract.EventsColumns#DTSTART}</td>
    <td>The time the event starts in UTC milliseconds since the epoch. </td>
  </tr>
  <tr>
    <td>{@link android.provider.CalendarContract.EventsColumns#DTEND}</td>
    <td>The time the event ends in UTC milliseconds since the epoch. </td>
  </tr>
  <tr>
    <td>{@link android.provider.CalendarContract.EventsColumns#EVENT_TIMEZONE}</td>
    <td>The time zone for the event.</td>
  </tr>
  <tr>
    <td>{@link android.provider.CalendarContract.EventsColumns#EVENT_END_TIMEZONE}</td>
    <td>The time zone for the end time of the event.</td>
  </tr>
  <tr>
    <td>{@link android.provider.CalendarContract.EventsColumns#DURATION}</td>
    
    <td>The duration of the event in <a
href="http://tools.ietf.org/html/rfc5545#section-3.8.2.5">RFC5545</a> format.
For example, a value of <code>&quot;PT1H&quot;</code> states that the event
should last one hour, and a value of <code>&quot;P2W&quot;</code> indicates a
duration of 2 weeks. </td>


  </tr>
  <tr>
    <td>{@link android.provider.CalendarContract.EventsColumns#ALL_DAY}</td>
    
    <td>A value of 1 indicates this event occupies the entire day, as defined by
the local time zone. A value of 0 indicates it is a regular event that may start
and end at any time during a day.</td>

    
  </tr>
  
  
  <tr>
    <td>{@link android.provider.CalendarContract.EventsColumns#RRULE}</td>
    
    <td>The recurrence rule for the event format. For
example, <code>&quot;FREQ=WEEKLY;COUNT=10;WKST=SU&quot;</code>. You can find
more examples <a
href="http://tools.ietf.org/html/rfc5545#section-3.8.5.3">here</a>.</td>
    
  </tr>
  
  <tr>
    <td>{@link android.provider.CalendarContract.EventsColumns#RDATE}</td>
    <td>The recurrence dates for the event. 
    You typically use {@link android.provider.CalendarContract.EventsColumns#RDATE} 
    in conjunction with {@link android.provider.CalendarContract.EventsColumns#RRULE} 
    to define an aggregate set of
repeating occurrences. For more discussion, see the <a
href="http://tools.ietf.org/html/rfc5545#section-3.8.5.2">RFC5545 spec</a>.</td>
</tr>
 
  <tr>
    <td>{@link android.provider.CalendarContract.EventsColumns#AVAILABILITY}</td>
    
    <td>If this event counts as busy time or is free time that can be 
scheduled over. </td>
    
  </tr>
  <tr>
    <td>{@link android.provider.CalendarContract.EventsColumns#GUESTS_CAN_MODIFY}</td>
    <td>Whether guests can modify the event. </td>
  </tr>
  <tr>
    <td>{@link android.provider.CalendarContract.EventsColumns#GUESTS_CAN_INVITE_OTHERS}</td>
    <td>Whether guests can invite other guests. </td>
  </tr>
  <tr>
    <td>{@link android.provider.CalendarContract.EventsColumns#GUESTS_CAN_SEE_GUESTS}</td>
    <td>Whether guests can see the list of attendees.</td>
  </tr>
</table>

<h3 id="add-event">Adding Events</h3>

<p>When your application inserts a new event, we recommend that you use an
{@link android.content.Intent#ACTION_INSERT INSERT} Intent, as described in <a
href="#intent-insert">Using an intent to insert an event</a>. However, if you
need to, you can insert events directly. This section describes how to do
this.</p>


<p>Here are the rules for inserting a new event: </p>
<ul>

  <li>You must include  {@link
android.provider.CalendarContract.EventsColumns#CALENDAR_ID} and {@link
android.provider.CalendarContract.EventsColumns#DTSTART}.</li>

<li>You must include an {@link
android.provider.CalendarContract.EventsColumns#EVENT_TIMEZONE}. To get a list
of the system's installed time zone IDs, use {@link
java.util.TimeZone#getAvailableIDs()}. Note that this rule does not apply if
you're inserting an event through the {@link
android.content.Intent#ACTION_INSERT INSERT} Intent, described in <a
href="#intent-insert">Using an intent to insert an event</a>&mdash;in that
scenario, a default time zone is supplied.</li>
  
  <li>For non-recurring events, you must include {@link
android.provider.CalendarContract.EventsColumns#DTEND}. </li>
  
  
  <li>For recurring events, you must include a {@link
android.provider.CalendarContract.EventsColumns#DURATION} in addition to  {@link
android.provider.CalendarContract.EventsColumns#RRULE} or {@link
android.provider.CalendarContract.EventsColumns#RDATE}. Note that this rule does not apply if
you're inserting an event through the {@link
android.content.Intent#ACTION_INSERT INSERT} Intent, described in <a
href="#intent-insert">Using an intent to insert an event</a>&mdash;in that
scenario, you can use an {@link
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 
converts it to a duration automatically.</li>
  
</ul>

<p>Here is an example of inserting an event. This is being performed in the UI
thread for simplicity. In practice, inserts and updates should be done in an
asynchronous thread to move the action into a background thread. For more
information, see {@link android.content.AsyncQueryHandler}.</p>


<pre>
long calID = 3;
long startMillis = 0; 
long endMillis = 0;     
Calendar beginTime = Calendar.getInstance();
beginTime.set(2012, 9, 14, 7, 30);
startMillis = beginTime.getTimeInMillis();
Calendar endTime = Calendar.getInstance();
endTime.set(2012, 9, 14, 8, 45);
endMillis = endTime.getTimeInMillis();
...

ContentResolver cr = getContentResolver();
ContentValues values = new ContentValues();
values.put(Events.DTSTART, startMillis);
values.put(Events.DTEND, endMillis);
values.put(Events.TITLE, &quot;Jazzercise&quot;);
values.put(Events.DESCRIPTION, &quot;Group workout&quot;);
values.put(Events.CALENDAR_ID, calID);
values.put(Events.EVENT_TIMEZONE, "America/Los_Angeles");
Uri uri = cr.insert(Events.CONTENT_URI, values);

// get the event ID that is the last element in the Uri
long eventID = Long.parseLong(uri.getLastPathSegment());
// 
// ... do something with event ID
//
//</pre>

<p class="note"><strong>Note:</strong> See how this example captures the event
ID after the event is created. This is the easiest way to get an event ID. You often
need the event ID to perform other calendar operations&mdash;for example, to add
attendees or reminders to an event.</p>


<h3 id="update-event">Updating Events</h3>

<p>When your application wants to allow the user to edit an event, we recommend
that you use an {@link android.content.Intent#ACTION_EDIT EDIT} Intent, as
described in <a href="#intent-edit">Using an intent to edit an  event</a>.
However, if you need to, you can edit events directly. To perform an update of
an Event, you can provide the <code>_ID</code> of the 
event either as an appended ID to the Uri ({@link
android.content.ContentUris#withAppendedId(android.net.Uri,long) withAppendedId()}) 
or as the first selection item. 
The selection should start with <code>&quot;_id=?&quot;</code>, and the first
<code>selectionArg</code> should be  the <code>_ID</code> of the event. You can
also do updates using a selection with no ID. Here is an example of updating an
event. It changes the title of the event using the 
{@link android.content.ContentUris#withAppendedId(android.net.Uri,long) withAppendedId()}
approach:</p>


<pre>private static final String DEBUG_TAG = "MyActivity";
...
long eventID = 188;
...
ContentResolver cr = getContentResolver();
ContentValues values = new ContentValues();
Uri updateUri = null;
// The new title for the event
values.put(Events.TITLE, &quot;Kickboxing&quot;); 
myUri = ContentUris.withAppendedId(Events.CONTENT_URI, eventID);
int rows = getContentResolver().update(updateUri, values, null, null);
Log.i(DEBUG_TAG, &quot;Rows updated: &quot; + rows);  </pre>

<h3 id="delete-event">Deleting Events</h3>

<p>You can delete an event either by its {@link
android.provider.BaseColumns#_ID} as an appended  ID on the URI, or by using
standard selection. If you use an appended ID, you can't also do a selection.
There are two versions of delete: as an application and as a sync adapter. An
application delete sets the <em>deleted</em> column to 1. This flag that tells
the sync adapter that the row was deleted and that this deletion should be
propagated to the server. A sync adapter delete removes the event from the
database along with all its associated data. Here is an example of application
deleting an event through its {@link android.provider.BaseColumns#_ID}:</p>


<pre>private static final String DEBUG_TAG = "MyActivity";
...
long eventID = 201;
...
ContentResolver cr = getContentResolver();
ContentValues values = new ContentValues();
Uri deleteUri = null;
deleteUri = ContentUris.withAppendedId(Events.CONTENT_URI, eventID);
int rows = getContentResolver().delete(deleteUri, null, null);
Log.i(DEBUG_TAG, &quot;Rows deleted: &quot; + rows);  
</pre>

<h2 id="attendees">Attendees Table</h2>

<p>Each row of the {@link android.provider.CalendarContract.Attendees} table
represents a single attendee or guest of an event. Calling 
{@link android.provider.CalendarContract.Reminders#query(android.content.ContentResolver, long, java.lang.String[]) query()} 
returns a list of attendees for  the
event with the given {@link android.provider.CalendarContract.AttendeesColumns#EVENT_ID}. 
This  {@link android.provider.CalendarContract.AttendeesColumns#EVENT_ID} 
must match the {@link
android.provider.BaseColumns#_ID} of a particular event.</p> 

<p>The following table lists the
writable fields. When inserting a new attendee, you must include all of them 
except <code>ATTENDEE_NAME</code>.
</p>


<table>
  <tr>
    <th>Constant</th>
    <th>Description</th>
  </tr>
  <tr>
    <td>{@link android.provider.CalendarContract.AttendeesColumns#EVENT_ID}</td>
    <td>The ID of the event.</td>
  </tr>
  <tr>
    <td>{@link android.provider.CalendarContract.AttendeesColumns#ATTENDEE_NAME}</td>
    <td>The name of the attendee.</td>
  </tr>
  <tr>
    <td>{@link android.provider.CalendarContract.AttendeesColumns#ATTENDEE_EMAIL}</td>
    <td>The email address of the attendee.</td>
  </tr>
  <tr>
    <td>{@link android.provider.CalendarContract.AttendeesColumns#ATTENDEE_RELATIONSHIP}</td>
    <td><p>The relationship of the attendee to the event. One of:</p>
      <ul>
        <li>{@link android.provider.CalendarContract.AttendeesColumns#RELATIONSHIP_ATTENDEE}</li>
        <li>{@link android.provider.CalendarContract.AttendeesColumns#RELATIONSHIP_NONE}</li>
        <li>{@link android.provider.CalendarContract.AttendeesColumns#RELATIONSHIP_ORGANIZER}</li>
        <li>{@link android.provider.CalendarContract.AttendeesColumns#RELATIONSHIP_PERFORMER}</li>
        <li>{@link android.provider.CalendarContract.AttendeesColumns#RELATIONSHIP_SPEAKER}</li>
    </ul>
    </td>
  </tr>
  <tr>
    <td>{@link android.provider.CalendarContract.AttendeesColumns#ATTENDEE_TYPE}</td>
    <td><p>The type of attendee. One of: </p>
      <ul>
        <li>{@link android.provider.CalendarContract.AttendeesColumns#TYPE_REQUIRED}</li>
        <li>{@link android.provider.CalendarContract.AttendeesColumns#TYPE_OPTIONAL}</li>
    </ul></td>
  </tr>
  <tr>
    <td>{@link android.provider.CalendarContract.AttendeesColumns#ATTENDEE_STATUS}</td>
    <td><p>The attendance status of the attendee. One of:</p>
      <ul>
        <li>{@link android.provider.CalendarContract.AttendeesColumns#ATTENDEE_STATUS_ACCEPTED}</li>
        <li>{@link android.provider.CalendarContract.AttendeesColumns#ATTENDEE_STATUS_DECLINED}</li>
        <li>{@link android.provider.CalendarContract.AttendeesColumns#ATTENDEE_STATUS_INVITED}</li>
        <li>{@link android.provider.CalendarContract.AttendeesColumns#ATTENDEE_STATUS_NONE}</li>
        <li>{@link android.provider.CalendarContract.AttendeesColumns#ATTENDEE_STATUS_TENTATIVE}</li>
    </ul></td>
  </tr>
</table>

<h3 id="add-attendees">Adding Attendees</h3>

<p>Here is an example that adds a single attendee to an event. Note that the
{@link android.provider.CalendarContract.AttendeesColumns#EVENT_ID} 
is required:</p>

<pre>
long eventID = 202;
...
ContentResolver cr = getContentResolver();
ContentValues values = new ContentValues();
values.put(Attendees.ATTENDEE_NAME, &quot;Trevor&quot;);
values.put(Attendees.ATTENDEE_EMAIL, &quot;trevor@example.com&quot;);
values.put(Attendees.ATTENDEE_RELATIONSHIP, Attendees.RELATIONSHIP_ATTENDEE);
values.put(Attendees.ATTENDEE_TYPE, Attendees.TYPE_OPTIONAL);
values.put(Attendees.ATTENDEE_STATUS, Attendees.ATTENDEE_STATUS_INVITED);
values.put(Attendees.EVENT_ID, eventID);
Uri uri = cr.insert(Attendees.CONTENT_URI, values);
</pre>

<h2 id="reminders">Reminders Table</h2>

<p>Each row of the {@link android.provider.CalendarContract.Reminders} table
represents a single reminder for an event. Calling 
{@link android.provider.CalendarContract.Reminders#query(android.content.ContentResolver, long, java.lang.String[]) query()}  returns a list of reminders for the
event with the given 
{@link android.provider.CalendarContract.AttendeesColumns#EVENT_ID}.</p>


<p>The following table lists the writable fields for reminders. All of them must
be included when inserting a new reminder. Note that sync adapters specify the
types of reminders they support in the {@link
android.provider.CalendarContract.Calendars} table. See 
{@link android.provider.CalendarContract.CalendarColumns#ALLOWED_REMINDERS} 
for details.</p>


<table>
  <tr>
    <th>Constant</th>
    <th>Description</th>
  </tr>
  <tr>
    <td>{@link android.provider.CalendarContract.RemindersColumns#EVENT_ID}</td>
    <td>The ID of the event.</td>
  </tr>
  <tr>
    <td>{@link android.provider.CalendarContract.RemindersColumns#MINUTES}</td>
    <td>The minutes prior to the event that the reminder should fire.</td>
  </tr>
  <tr>
    <td>{@link android.provider.CalendarContract.RemindersColumns#METHOD}</td>
    <td><p>The alarm method, as set on the server. One of:</p>
      <ul>
        <li>{@link android.provider.CalendarContract.RemindersColumns#METHOD_ALERT}</li>
        <li>{@link android.provider.CalendarContract.RemindersColumns#METHOD_DEFAULT}</li>
        <li>{@link android.provider.CalendarContract.RemindersColumns#METHOD_EMAIL}</li>
        <li>{@link android.provider.CalendarContract.RemindersColumns#METHOD_SMS}</li>
    </ul></td>
  </tr>
</table>

<h3 id="add-reminders">Adding Reminders</h3>

<p>This example adds a reminder to an event. The reminder fires 15
minutes before the event.</p>
<pre>
long eventID = 221;
...
ContentResolver cr = getContentResolver();
ContentValues values = new ContentValues();
values.put(Reminders.MINUTES, 15);
values.put(Reminders.EVENT_ID, eventID);
values.put(Reminders.METHOD, Reminders.METHOD_ALERT);
Uri uri = cr.insert(Reminders.CONTENT_URI, values);</pre>

<h2 id="instances">Instances Table</h2>

<p>The 
{@link android.provider.CalendarContract.Instances} table holds the
start and end time for occurrences of an event. Each row in this table
represents a single event occurrence. The instances table is not writable and only
provides a  way to query event occurrences. </p>

<p>The following table lists some of the fields you can query on for an instance. Note 
that time zone is defined by 
{@link android.provider.CalendarContract.CalendarCache#KEY_TIMEZONE_TYPE} 
and 
{@link android.provider.CalendarContract.CalendarCache#KEY_TIMEZONE_INSTANCES}.</p>


<table>
  <tr>
    <th>Constant</th>
    <th>Description</th>
  </tr>
  <tr>
    <td>{@link android.provider.CalendarContract.Instances#BEGIN}</td>
    <td>The beginning time of the instance, in UTC milliseconds.</td>
  </tr>
  <tr>
    <td>{@link android.provider.CalendarContract.Instances#END}</td>
    <td>The ending time of the instance, in UTC milliseconds.</td>
  </tr>
  <tr>
    <td>{@link android.provider.CalendarContract.Instances#END_DAY}</td>
    
    <td>The Julian end day of the instance, relative to the Calendar's time
zone. 
    
</td>
  </tr>
  <tr>
    <td>{@link android.provider.CalendarContract.Instances#END_MINUTE}</td>
    
    <td>The end minute of the instance measured from midnight in the the
Calendar's time zone.</td>
    
  </tr>
  <tr>
    <td>{@link android.provider.CalendarContract.Instances#EVENT_ID}</td>
    <td>The <code>_ID</code> of the event for this instance.</td>
  </tr>
    <tr>
    <td>{@link android.provider.CalendarContract.Instances#START_DAY}</td>
    <td>The Julian start day of the instance, relative to the Calendar's time zone. 
 </td>
  </tr>
  <tr>
    <td>{@link android.provider.CalendarContract.Instances#START_MINUTE}</td>
    
    <td>The start minute of the instance measured from midnight, relative to the
Calendar's time zone. 
</td>
    
  </tr>

</table>

<h3 id="query-instances">Querying the Instances table</h3>

<p>To query the Instances table, you need to specify a range time for the query
in the URI. In this example, {@link android.provider.CalendarContract.Instances}
gets access to the {@link
android.provider.CalendarContract.EventsColumns#TITLE} field through its
implementation of the {@link android.provider.CalendarContract.EventsColumns} interface. 
In other words, {@link
android.provider.CalendarContract.EventsColumns#TITLE} is returned through a
database view, not through querying the raw {@link
android.provider.CalendarContract.Instances} table.</p>

<pre>
private static final String DEBUG_TAG = "MyActivity";
public static final String[] INSTANCE_PROJECTION = new String[] {
    Instances.EVENT_ID,      // 0
    Instances.BEGIN,         // 1
    Instances.TITLE          // 2
  };
  
// The indices for the projection array above.
private static final int PROJECTION_ID_INDEX = 0;
private static final int PROJECTION_BEGIN_INDEX = 1;
private static final int PROJECTION_TITLE_INDEX = 2;
...

// Specify the date range you want to search for recurring
// event instances
Calendar beginTime = Calendar.getInstance();
beginTime.set(2011, 9, 23, 8, 0);
long startMillis = beginTime.getTimeInMillis();
Calendar endTime = Calendar.getInstance();
endTime.set(2011, 10, 24, 8, 0);
long endMillis = endTime.getTimeInMillis();
  
Cursor cur = null;
ContentResolver cr = getContentResolver();

// The ID of the recurring event whose instances you are searching
// for in the Instances table
String selection = Instances.EVENT_ID + " = ?";
String[] selectionArgs = new String[] {"207"};

// Construct the query with the desired date range.
Uri.Builder builder = Instances.CONTENT_URI.buildUpon();
ContentUris.appendId(builder, startMillis);
ContentUris.appendId(builder, endMillis);

// Submit the query
cur =  cr.query(builder.build(), 
    INSTANCE_PROJECTION, 
    selection, 
    selectionArgs, 
    null);
   
while (cur.moveToNext()) {
    String title = null;
    long eventID = 0;
    long beginVal = 0;    
    
    // Get the field values
    eventID = cur.getLong(PROJECTION_ID_INDEX);
    beginVal = cur.getLong(PROJECTION_BEGIN_INDEX);
    title = cur.getString(PROJECTION_TITLE_INDEX);
              
    // Do something with the values. 
    Log.i(DEBUG_TAG, "Event:  " + title); 
    Calendar calendar = Calendar.getInstance();
    calendar.setTimeInMillis(beginVal);  
    DateFormat formatter = new SimpleDateFormat("MM/dd/yyyy");
    Log.i(DEBUG_TAG, "Date: " + formatter.format(calendar.getTime()));    
    }
 }</pre>

<h2 id="intents">Calendar Intents</h2>
<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>
<table>
  <tr>
    <th>Action</th>
    <th>URI</th>

    <th>Description</th>
    <th>Extras</th>
  </tr>
  <tr>
    <td><br>
    {@link android.content.Intent#ACTION_VIEW VIEW} <br></td>
    <td><p><code>content://com.android.calendar/time/&lt;ms_since_epoch&gt;</code></p>
    You can also refer to the URI with 
{@link android.provider.CalendarContract#CONTENT_URI CalendarContract.CONTENT_URI}. 
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>. 

    </td>
    <td>Open calendar to the time specified by <code>&lt;ms_since_epoch&gt;</code>.</td>
    <td>None.</td>
  </tr>
  <tr>
    <td><p>{@link android.content.Intent#ACTION_VIEW VIEW} </p>

     </td>
    <td><p><code>content://com.android.calendar/events/&lt;event_id&gt;</code></p>
    
    You can also refer to the URI with 
{@link android.provider.CalendarContract.Events#CONTENT_URI Events.CONTENT_URI}. 
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>.
    
    </td>
    <td>View the event specified by <code>&lt;event_id&gt;</code>.</td>

    <td>{@link android.provider.CalendarContract#EXTRA_EVENT_BEGIN_TIME CalendarContract.EXTRA_EVENT_BEGIN_TIME}<br>
      <br>
      <br>
    {@link android.provider.CalendarContract#EXTRA_EVENT_END_TIME CalendarContract.EXTRA_EVENT_END_TIME}</td>
  </tr>

  <tr>
    <td>{@link android.content.Intent#ACTION_EDIT EDIT} </td>
    <td><p><code>content://com.android.calendar/events/&lt;event_id&gt;</code></p>
    
  You can also refer to the URI with 
{@link android.provider.CalendarContract.Events#CONTENT_URI Events.CONTENT_URI}. 
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>.
    
    
    </td>
    <td>Edit the event specified by <code>&lt;event_id&gt;</code>.</td>

    <td>{@link android.provider.CalendarContract#EXTRA_EVENT_BEGIN_TIME CalendarContract.EXTRA_EVENT_BEGIN_TIME}<br>
      <br>
      <br>
    {@link android.provider.CalendarContract#EXTRA_EVENT_END_TIME CalendarContract.EXTRA_EVENT_END_TIME}</td>
  </tr>

  <tr>
    <td>{@link android.content.Intent#ACTION_EDIT EDIT} <br>
    <br>
    {@link android.content.Intent#ACTION_INSERT INSERT} </td>
    <td><p><code>content://com.android.calendar/events</code></p>
    
   You can also refer to the URI with 
{@link android.provider.CalendarContract.Events#CONTENT_URI Events.CONTENT_URI}. 
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>.
    
    </td>

    <td>Create an event.</td>
    <td>Any of the extras listed in the table below.</td>
  </tr>
</table>

<p>The following table lists the intent extras supported by the Calendar Provider:
</p>
<table>
  <tr>
    <th>Intent Extra</th>
    <th>Description</th>
  </tr>
  <tr>
    <td>{@link android.provider.CalendarContract.EventsColumns#TITLE Events.TITLE}</td>
    <td>Name for the event.</td>
  </tr>
  <tr>
  
    <td>{@link android.provider.CalendarContract#EXTRA_EVENT_BEGIN_TIME
CalendarContract.EXTRA_EVENT_BEGIN_TIME}</td>
    <td>Event begin time in milliseconds from the epoch.</td>
  </tr>
  <tr>
    <td>{@link android.provider.CalendarContract#EXTRA_EVENT_END_TIME
CalendarContract.EXTRA_EVENT_END_TIME}</td>
    
    <td>Event end time in milliseconds from the epoch.</td>
  </tr>
  <tr>
    <td>{@link android.provider.CalendarContract#EXTRA_EVENT_ALL_DAY
CalendarContract.EXTRA_EVENT_ALL_DAY}</td>
    
    <td>A boolean that indicates that an event is all day. Value can be
<code>true</code> or <code>false</code>.</td> </tr>
  <tr>
    <td>{@link android.provider.CalendarContract.EventsColumns#EVENT_LOCATION
Events.EVENT_LOCATION}</td>
    
    <td>Location of the event.</td>
  </tr>
  <tr>
    <td>{@link android.provider.CalendarContract.EventsColumns#DESCRIPTION
Events.DESCRIPTION}</td>
    
    <td>Event description.</td>
  </tr>
  <tr>
    <td>
    {@link android.content.Intent#EXTRA_EMAIL Intent.EXTRA_EMAIL}</td>
    <td>Email addresses of those to invite as a comma-separated list.</td>
  </tr>
  <tr>
    <td>
    {@link android.provider.CalendarContract.EventsColumns#RRULE Events.RRULE}</td>
    <td>The recurrence rule for the event.</td>
  </tr>
  <tr>
    <td>
    {@link android.provider.CalendarContract.EventsColumns#ACCESS_LEVEL
Events.ACCESS_LEVEL}</td>
    
    <td>Whether the event is private or public.</td>
  </tr>
  <tr>
    <td>{@link android.provider.CalendarContract.EventsColumns#AVAILABILITY
Events.AVAILABILITY}</td>
    
    <td>If this event counts as busy time or is free time that can be scheduled over.</td>
    
</table> 
<p>The following sections describe how to use these intents.</p>


<h3 id="intent-insert">Using an intent to insert an event</h3>

<p>Using the {@link android.content.Intent#ACTION_INSERT INSERT} Intent
lets your application hand off the event insertion task to the Calendar itself.
With this approach, your application doesn't even need to have the {@link
android.Manifest.permission#WRITE_CALENDAR} permission included in its <a
href="#manifest">manifest file</a>.</p>

  
<p>When users run an application that uses this approach, the application sends
them to the Calendar to finish adding the event. The {@link
android.content.Intent#ACTION_INSERT INSERT} Intent uses extra fields to
pre-populate a form with the details of the event in the Calendar. Users can
then cancel the event, edit the form as needed, or save the event to their
calendars.</p>
  


<p>Here is a code snippet that schedules an event on January 19, 2012, that runs
from 7:30 a.m. to 8:30 a.m. Note the following about this code snippet:</p>

<ul>
  <li>It specifies {@link android.provider.CalendarContract.Events#CONTENT_URI Events.CONTENT_URI} 
  as the Uri.</li>
  
  <li>It uses the {@link
android.provider.CalendarContract#EXTRA_EVENT_BEGIN_TIME
CalendarContract.EXTRA_EVENT_BEGIN_TIME} and {@link
android.provider.CalendarContract#EXTRA_EVENT_END_TIME
CalendarContract.EXTRA_EVENT_END_TIME} extra fields to pre-populate the form
with the time of the event. The values  for these times must be in UTC milliseconds
from the epoch.</li>
  
  <li>It uses the {@link android.content.Intent#EXTRA_EMAIL Intent.EXTRA_EMAIL}
extra field to provide a comma-separated list of invitees, specified by email address.</li>
  
</ul>
<pre>
Calendar beginTime = Calendar.getInstance();
beginTime.set(2012, 0, 19, 7, 30);
Calendar endTime = Calendar.getInstance();
endTime.set(2012, 0, 19, 8, 30);
Intent intent = new Intent(Intent.ACTION_INSERT)
        .setData(Events.CONTENT_URI)
        .putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, beginTime.getTimeInMillis())
        .putExtra(CalendarContract.EXTRA_EVENT_END_TIME, endTime.getTimeInMillis())
        .putExtra(Events.TITLE, &quot;Yoga&quot;)
        .putExtra(Events.DESCRIPTION, &quot;Group class&quot;)
        .putExtra(Events.EVENT_LOCATION, &quot;The gym&quot;)
        .putExtra(Events.AVAILABILITY, Events.AVAILABILITY_BUSY)
        .putExtra(Intent.EXTRA_EMAIL, &quot;rowan@example.com,trevor@example.com&quot;);
startActivity(intent);
</pre>

<h3 id="intent-edit">Using an intent to edit an event</h3>

<p>You can update an event directly, as described in <a
href="#update-event">Updating events</a>. But using the {@link
android.content.Intent#ACTION_EDIT EDIT} Intent allows an application that
doesn't have permission to hand off event editing to the Calendar application.
When users finish editing their event in Calendar, they're returned to the
original application.</p> <p>Here is an example of an intent that sets a new
title for a specified event and lets users edit the event in the Calendar.</p>


<pre>long eventID = 208;
Uri uri = ContentUris.withAppendedId(Events.CONTENT_URI, eventID);
Intent intent = new Intent(Intent.ACTION_EDIT)
    .setData(uri)
    .putExtra(Events.TITLE, &quot;My New Title&quot;);
startActivity(intent);</pre>

<h3 id="intent-view">Using  intents to view calendar data</h3>
<p>Calender Provider offers two different ways to use the {@link android.content.Intent#ACTION_VIEW VIEW} Intent:</p>
<ul>
  <li>To open the Calendar to a particular date.</li>
  <li>To view an event.</li>

</ul>
<p>Here is an example that shows how to open the Calendar to a particular date:</p>
<pre>// A date-time specified in milliseconds since the epoch.
long startMillis;
...
Uri.Builder builder = CalendarContract.CONTENT_URI.buildUpon();
builder.appendPath(&quot;time&quot;);
ContentUris.appendId(builder, startMillis);
Intent intent = new Intent(Intent.ACTION_VIEW)
    .setData(builder.build());
startActivity(intent);</pre>

<p>Here is an example that shows how to open an event for viewing:</p>
<pre>long eventID = 208;
...
Uri uri = ContentUris.withAppendedId(Events.CONTENT_URI, eventID);
Intent intent = new Intent(Intent.ACTION_VIEW)
   .setData(uri);
startActivity(intent);
</pre>


<h2 id="sync-adapter">Sync Adapters</h2>


<p>There are only minor differences in how an application and a sync adapter
access the Calendar Provider:</p>

<ul>
  <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>
  
  
  <li>A sync adapter needs to provide an {@link
android.provider.CalendarContract.SyncColumns#ACCOUNT_NAME} and an {@link
android.provider.CalendarContract.SyncColumns#ACCOUNT_TYPE} as query parameters in the URI. </li>
  
  <li>A sync adapter has write access to more columns than an application or widget.
  For example, an application can only modify a few characteristics of a calendar, 
  such as its name, display name, visibility setting, and whether the calendar is
  synced. By comparison, a sync adapter can access not only those columns, but many others,
  such as calendar color, time zone, access level, location, and so on.
However, a sync adapter is restricted to the <code>ACCOUNT_NAME</code> and 
<code>ACCOUNT_TYPE</code> it specified.</li> </ul>

<p>Here is a helper method you can use to return a URI for use with a sync adapter:</p>
<pre> static Uri asSyncAdapter(Uri uri, String account, String accountType) {
    return uri.buildUpon()
        .appendQueryParameter(android.provider.CalendarContract.CALLER_IS_SYNCADAPTER,&quot;true&quot;)
        .appendQueryParameter(Calendars.ACCOUNT_NAME, account)
        .appendQueryParameter(Calendars.ACCOUNT_TYPE, accountType).build();
 }
</pre>
<p>For a sample implementation of a sync adapter (not specifically related to Calendar), see 
<a href="{@docRoot}resources/samples/SampleSyncAdapter/index.html">SampleSyncAdapter</a>.
</body>
</html>