• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1page.title=캘린더 제공자
2@jd:body
3
4<div id="qv-wrapper">
5<div id="qv">
6    <h2>이 문서의 내용</h2>
7    <ol>
8  <li><a href="#overview">기본 정보</a></li>
9  <li><a href="#manifest">사용자 권한</a></li>
10  <li><a href="#calendar">캘린더 테이블</a>
11<ol>
12      <li><a href="#query">캘린더 쿼리</a></li>
13      <li><a href="#modify-calendar">캘린더 수정</a></li>
14      <li><a href="#insert-calendar">캘린더 삽입</a></li>
15    </ol>
16  </li>
17  <li><a href="#events">이벤트 테이블</a>
18<ol>
19      <li><a href="#add-event">이벤트 추가</a></li>
20      <li><a href="#update-event">이벤트 업데이트</a></li>
21      <li><a href="#delete-event">이벤트 삭제</a></li>
22    </ol>
23  </li>
24  <li><a href="#attendees">참석자 테이블</a>
25<ol>
26      <li><a href="#add-attendees">참석자 추가</a></li>
27    </ol>
28  </li>
29  <li><a href="#reminders">알림 테이블</a>
30<ol>
31      <li><a href="#add-reminders">알림 추가</a></li>
32    </ol>
33  </li>
34  <li><a href="#instances">인스턴스 테이블</a>
35  <ol>
36      <li><a href="#query-instances">인스턴스 테이블 쿼리</a></li>
37  </ol></li>
38  <li><a href="#intents">캘린더 인텐트</a>
39  <ol>
40      <li><a href="#intent-insert">인텐트를 사용하여 이벤트 삽입</a></li>
41      <li><a href="#intent-edit">인텐트를 사용하여 이벤트 편집</a></li>
42      <li><a href="#intent-view">인텐트를 사용하여 캘린더 데이터 보기</a></li>
43    </ol>
44  </li>
45
46  <li><a href="#sync-adapter">동기화 어댑터</a></li>
47</ol>
48
49    <h2>Key 클래스</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>캘린더 제공자는 사용자의 캘린더 이벤트를 저장하는 리포지토리입니다.
60캘린더 제공자 API를 사용하면 캘린더, 이벤트, 참석자, 알림 등의 쿼리, 삽입, 업데이트 및
61삭제 등의 작업을 수행할 수 있습니다.</p>
62
63
64<p>캘린더 제공자 API는 애플리케이션과 동기화 어댑터에서 사용할 수 있습니다.
65어떤 유형의 프로그램이 호출을 하는 주체인지에 따라 규칙이 각기 다릅니다.
66이 문서는 주로 캘린더 제공자 API를 애플리케이션으로 사용하는 것에 주안점을 두었습니다.
67여러 동기화 어댑터가 서로 어떻게 다른지 논의한 내용은
68<a href="#sync-adapter">동기화 어댑터</a>를 참조하십시오.</p>
69
70
71<p>캘린더 데이터를 읽거나 쓰려면 보통 애플리케이션의 매니페스트에
72적절한 권한이 포함되어 있어야 합니다. 이는 <a href="#manifest">사용자
73권한</a>에 설명되어 있습니다. 공통 작업을 쉽게 수행하기 위해 캘린더
74제공자는 <a href="#intents">캘린더
75인텐트</a>에 설명된 바와 같이 인텐트 집합을 제공합니다. 이와 같은 인텐트는 사용자를 캘린더 애플리케이션으로 이동시켜
76이벤트 삽입, 보기 및 편집을 할 수 있게 해줍니다. 사용자는 캘린더 애플리케이션과 상호 작용한 다음
77원래 애플리케이션으로 돌아옵니다. 따라서, 여러분의 애플리케이션이 이벤트를 보거나
78생성하기 위해 권한 허가를 요청할 필요도 없고 사용자 인터페이스를 제공할 필요도 없는 것입니다.</p>
79
80<h2 id="overview">기본 정보</h2>
81
82<p><a href="{@docRoot}guide/topics/providers/content-providers.html">콘텐츠 제공자</a>는 데이터를 저장하여 애플리케이션에서
83이에 액세스할 수 있도록 합니다. 일반적으로, Android 플랫폼에서 제공하는 콘텐츠 제공자(캘린더 제공자 포함)는
84관계 데이터베이스 모델에 기초하여 테이블 집합으로 데이터를 노출합니다. 이 모델에서 각 행은 레코드이고,
85각 열은 특정한 유형과 의미를 가진 데이터입니다. 애플리케이션과 동기화 어댑터는
86캘린더 제공자 API를 통해 사용자의 캘린더 데이터를 보관하고 있는 데이터베이스 테이블에
87읽기/쓰기 액세스 권한을 얻을 수 있습니다.</p>
88
89<p>모든 콘텐츠 제공자는 데이터 세트를 고유하게 식별하는 공개 URI(
90{@link android.net.Uri}
91개체로 래핑됨)를 노출합니다.  여러 데이터 세트(여러 테이블)를 제어하는 콘텐츠 제공자는
92각 데이터 세트에 별도의 URI를 노출합니다.
93제공자에 대한 URI는 모두 문자열 "content://"로 시작합니다.
94이것을 보면 데이터를 콘텐츠 제공자가 제어하고 있다는 것을 알아볼 수 있습니다.
95캘린더 제공자가 각각의 클래스(테이블)에 대한 URI의 상수를 정의합니다.
96이와 같은 URI는 <code><em>&lt;class&gt;</em>.CONTENT_URI</code> 형식을 취합니다.
97예를 들면 다음과 같습니다. {@link android.provider.CalendarContract.Events#CONTENT_URI Events.CONTENT_URI}</p>
98
99<p>그림 1은 캘린더 제공자 데이터 모델을 그림으로 나타낸 것입니다.
100이 그림에는 메인 테이블과이들을 서로 연결하는 필드가 표시되어 있습니다.</p>
101
102<img src="{@docRoot}images/providers/datamodel.png" alt="Calendar Provider Data Model" />
103<p class="img-caption"><strong>그림 1.</strong> 캘린더 제공자 데이터 모델.</p>
104
105<p>한 사용자가 여러 개의 캘린더를 가질 수 있으며, 여러 가지 캘린더는 각기 다른 유형의 계정(Google 캘린더, Exchange 등)과 연결될 수 있습니다.</p>
106
107<p>{@link android.provider.CalendarContract}가 캘린더의 데이터 모델과 이벤트 관련 정보를 정의합니다. 이 데이터는 아래에 나열한 것과 같은 여러 테이블에 저장됩니다.</p>
108
109<table>
110  <tr>
111    <th>테이블(클래스)</th>
112    <th>설명</th>
113  </tr>
114  <tr>
115    <td><p>{@link android.provider.CalendarContract.Calendars}</p></td>
116
117    <td>이 테이블에는 캘린더별 정보가 담겨 있습니다.
118 이 테이블의 행마다 한 캘린더의 세부 정보,
119예를 들어 이름, 색상, 동기화 정보 등이 들어갑니다.</td>
120  </tr>
121  <tr>
122    <td>{@link android.provider.CalendarContract.Events}</td>
123
124    <td>이 테이블에는 이벤트별 정보가 담겨 있습니다.
125 이 테이블의 행마다 한 이벤트의 세부 정보
126예를 들어 이벤트 제목, 위치, 시작 시간, 종료 시간 등의 정보가 들어갑니다.
127 이벤트는 일회성일 수도 있고 여러 번 반복될 수도 있습니다.
128참석자, 알림 및 확장된 속성 등은 별도의 테이블에 저장됩니다.
129이들 테이블에는 각기 {@link android.provider.CalendarContract.AttendeesColumns#EVENT_ID}가 있어
130이벤트 테이블의 {@link android.provider.BaseColumns#_ID}를 참조합니다.</td>
131
132  </tr>
133  <tr>
134    <td>{@link android.provider.CalendarContract.Instances}</td>
135
136    <td>이 테이블에는 각 이벤트 발생의 시작 시간과 종료 시간이
137담겨 있습니다. 이 테이블의 각 행이 하나의 이벤트 발생을 나타냅니다.
138 일회성 이벤트의 경우, 이벤트에 대한 1:1 인스턴스 매핑이 있습니다.
139 반복되는 이벤트의 경우, 해당 이벤트가 여러 번 발생하는 것에 맞추어
140자동으로 여러 행이 생성됩니다.</td>
141  </tr>
142  <tr>
143    <td>{@link android.provider.CalendarContract.Attendees}</td>
144
145    <td>이 테이블에는 이벤트 참석자(게스트) 정보가 담겨 있습니다.
146 각 행이 주어진 이벤트의 게스트 한 사람을 나타냅니다.
147 이것이 게스트의 유형과, 이벤트에 대한 해당 게스트의 참석 여부 응답을
148나타냅니다.</td>
149  </tr>
150  <tr>
151    <td>{@link android.provider.CalendarContract.Reminders}</td>
152
153    <td>이 테이블에는 경고/알림 데이터가 담겨 있습니다.
154 각 행이 주어진 이벤트에 대한 경고 하나를 나타냅니다.
155이벤트 하나에 여러 개의 알림이 있을 수 있습니다. 이벤트당 최대 알림 개수는
156
157{@link android.provider.CalendarContract.CalendarColumns#MAX_REMINDERS}에서 지정되고,
158이는 주어진 캘린더를 소유한 동기화 어댑터가 설정합니다.
159 알림은 이벤트 몇 분 전에 지정되며 사용자에게 어떻게 경고할 것인지를
160결정하는 메서드를 가지고 있습니다.</td>
161  </tr>
162
163</table>
164
165<p>캘린더 제공자 API는 유연성과 강력함을 염두에 두고 만들어진 것입니다.
166그와 동시에 우수한 최종 사용자 경험을 제공하고 캘린더와 그 데이터의
167무결성을 보호하는 것 또한 중요합니다. 이를 위해서
168API를 사용할 때 유념해야 할 사항은 다음과 같습니다.</p>
169
170<ul>
171
172<li><strong>캘린더 이벤트 삽입, 업데이트 및 보기.</strong> 캘린더 제공자로부터 직접 이벤트를 삽입, 변경하고 읽으려면 적절한 <a href="#manifest">권한</a>이 필요합니다. 그러나, 완전한 캘린더 애플리케이션 또는 동기화 어댑터를 구축하는 경우가 아니라면 이와 같은 권한을 요청할 필요가 없습니다. 대신 Android의 캘린더 애플리케이션이 지원하는 인텐트를 사용하여 해당 애플리케이션에 읽기 및 쓰기 작업을 분배하면 됩니다. 인텐트를 사용하면, 애플리케이션이 사용자를 캘린더 애플리케이션으로 보내 사전에 작성된 양식으로 원하는 작업을
173수행하게 합니다. 작업이 끝나면 사용자는 애플리케이션으로 돌아옵니다.
174캘린더를 통해 공통 작업을 수행하도록 애플리케이션을 설계함으로써 사용자에게 일관되고 강력한
175사용자 인터페이스를 제공하는 것입니다. 이것이 권장 방법입니다.
176 자세한 정보는 <a href="#intents">캘린더
177인텐트</a>를 참조하십시오.</p>
178
179
180<li><strong>동기화 어댑터.</strong>
181동기화 어댑터는 사용자의 기기에 있는 캘린더 데이터를 다른 서버 또는 데이터 소스와 동기화합니다.
182{@link android.provider.CalendarContract.Calendars}와
183{@link android.provider.CalendarContract.Events} 테이블에는
184동기화 어댑터가 사용하도록 예약된 열이 있습니다.
185제공자와 애플리케이션은 이를 수정해서는 안 됩니다. 사실, 동기화 어댑터로 액세스하지 않는 한
186이 열이 표시되지 않습니다.
187동기화 어댑터에 대한 자세한 정보는 <a href="#sync-adapter">동기화 어댑터</a>를 참조하십시오.</li>
188
189</ul>
190
191
192<h2 id="manifest">사용자 권한</h2>
193
194<p>캘린더 데이터를 읽으려면 애플리케이션의 매니페스트 파일에 {@link
195android.Manifest.permission#READ_CALENDAR} 권한이 포함되어 있어야 합니다.
196캘린더 데이터를 삭제, 삽입 또는 업데이트하려면{@link android.Manifest.permission#WRITE_CALENDAR}
197권한이 포함되어 있어야 합니다.</p>
198
199<pre>
200&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
201&lt;manifest xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;...&gt;
202    &lt;uses-sdk android:minSdkVersion=&quot;14&quot; /&gt;
203    &lt;uses-permission android:name=&quot;android.permission.READ_CALENDAR&quot; /&gt;
204    &lt;uses-permission android:name=&quot;android.permission.WRITE_CALENDAR&quot; /&gt;
205    ...
206&lt;/manifest&gt;
207</pre>
208
209
210<h2 id="calendar">캘린더 테이블</h2>
211
212<p>{@link android.provider.CalendarContract.Calendars}
213테이블에는 각각의 캘린더에 대한 세부 정보가 들어 있습니다.
214다음 캘린더 열은 애플리케이션과 <a href="#sync-adapter">동기화 어댑터</a> 모두 쓸 수 있는 것입니다.
215지원되는 필드의 전체 목록은
216{@link android.provider.CalendarContract.Calendars} 참조를 확인하십시오.</p>
217<table>
218  <tr>
219    <th>상수</th>
220    <th>설명</th>
221  </tr>
222  <tr>
223    <td>{@link android.provider.CalendarContract.Calendars#NAME}</td>
224    <td>캘린더 이름입니다.</td>
225  </tr>
226  <tr>
227    <td>{@link android.provider.CalendarContract.Calendars#CALENDAR_DISPLAY_NAME}</td>
228    <td>사용자에게 표시되는 이 캘린더의 이름입니다.</td>
229  </tr>
230  <tr>
231    <td>{@link android.provider.CalendarContract.Calendars#VISIBLE}</td>
232
233    <td>캘린더를 표시하기로 선택했는지를 나타내는 부울입니다.
234값이 0이면 이 캘린더와 연관된 이벤트는 표시하면 안 된다는 뜻입니다.
235  값이 1이면 이 캘린더와 연관된 이벤트를 표시해야 한다는 뜻입니다.
236 이 값이 {@link
237android.provider.CalendarContract.Instances} 테이블의 행 생성에 영향을 미칩니다.</td>
238
239
240  </tr>
241  <tr>
242    <td>{@link android.provider.CalendarContract.CalendarColumns#SYNC_EVENTS}</td>
243
244    <td>캘린더를 동기화하고 이 캘린더의 이벤트를 기기에 저장해야할지를
245나타내는 부울입니다. 값이 0이면 이 캘린더를 동기화하거나 이에 속한 이벤트를
246기기에 저장하면 안 된다는 뜻입니다.  값이 1이면 이 캘린더에 대한 이벤트를 동기화하고 이에 속한
247이벤트를 기기에 저장하라는 뜻입니다.</td>
248  </tr>
249</table>
250
251<h3 id="query">캘린더 쿼리</h3>
252
253<p>다음은 특정한 사용자가 소유한 캘린더를 가져오는 법을 나타낸 예시입니다.
254 이 예시에서는 단순하게 나타내기 위해 쿼리 작업을 사용자 인터페이스 스레드("주 스레드")에 표시했습니다.
255 실제로는, 이 작업은 주 스레드 대신 비동기화 스레드에서 해야 합니다.
256 자세한 논의는
257<a href="{@docRoot}guide/components/loaders.html">로더</a>를 참조하십시오. 데이터를 읽기만 하는 것이 아니라 변경도 하는 경우라면,
258{@link android.content.AsyncQueryHandler}를 참조하십시오.
259</p>
260
261
262<pre>
263// Projection array. Creating indices for this array instead of doing
264// dynamic lookups improves performance.
265public static final String[] EVENT_PROJECTION = new String[] {
266    Calendars._ID,                           // 0
267    Calendars.ACCOUNT_NAME,                  // 1
268    Calendars.CALENDAR_DISPLAY_NAME,         // 2
269    Calendars.OWNER_ACCOUNT                  // 3
270};
271
272// The indices for the projection array above.
273private static final int PROJECTION_ID_INDEX = 0;
274private static final int PROJECTION_ACCOUNT_NAME_INDEX = 1;
275private static final int PROJECTION_DISPLAY_NAME_INDEX = 2;
276private static final int PROJECTION_OWNER_ACCOUNT_INDEX = 3;</pre>
277
278
279<div class="sidebox-wrapper"> <div class="sidebox"> <h3>
280ACCOUNT_TYPE을 반드시 포함시켜야 하는 이유는 무엇일까요?</h3> <p>{@link
281android.provider.CalendarContract.Calendars#ACCOUNT_NAME
282Calendars.ACCOUNT_NAME}에 대해 쿼리하는 경우, 해당 선택에
283{@link android.provider.CalendarContract.Calendars#ACCOUNT_TYPE Calendars.ACCOUNT_TYPE}
284도 포함시켜야 합니다. 이는 주어진 계정을 고유하다고 간주하는 것은 해당 계정의
285<code>ACCOUNT_NAME</code> 및
286<code>ACCOUNT_TYPE</code>이 모두 있을 때뿐이기 때문입니다. <code>ACCOUNT_TYPE</code>은 계정이
287
288{@link android.accounts.AccountManager}로 등록되었을 때 사용된 계정 인증자에 상응하는 문자열입니다. 기기와 연관되지 않은 캘린더에 적용되는 특별한 유형의 계정도 있으며 이를 {@link
289android.provider.CalendarContract#ACCOUNT_TYPE_LOCAL}이라고 합니다.
290{@link
291android.provider.CalendarContract#ACCOUNT_TYPE_LOCAL} 계정은 동기화되지 않습니다.
292</p> </div> </div>
293
294
295<p> 다음 예시에서는 여러분이 직접 나름의 쿼리를 생성해보십시오. 선택 영역이 쿼리의 기준을 나타냅니다.
296 이 예시에서 쿼리는
297<code>ACCOUNT_NAME</code>
298"sampleuser@google.com", <code>ACCOUNT_TYPE</code>
299"com.google" 및 <code>OWNER_ACCOUNT</code>
300"sampleuser@google.com"을 가지고 있는 캘린더를 찾고 있습니다. 사용자가 소유한 캘린더뿐만 아니라 사용자가 전에 본 캘린더까지 모두 확인하려면
301<code>OWNER_ACCOUNT</code>를 생략합니다.
302쿼리가 {@link android.database.Cursor}
303개체를 반환하여 이를 시용하면 데이터베이스 쿼리가 반환한 결과 집합을 트래버스할 수 있습니다.
304 콘텐츠 제공자에서 쿼리를 사용하는 법에 대한 자세한 논의는
305<a href="{@docRoot}guide/topics/providers/content-providers.html">콘텐츠 제공자</a>를 참조하십시오.</p>
306
307
308<pre>// Run query
309Cursor cur = null;
310ContentResolver cr = getContentResolver();
311Uri uri = Calendars.CONTENT_URI;
312String selection = "((" + Calendars.ACCOUNT_NAME + " = ?) AND ("
313                        + Calendars.ACCOUNT_TYPE + " = ?) AND ("
314                        + Calendars.OWNER_ACCOUNT + " = ?))";
315String[] selectionArgs = new String[] {"sampleuser@gmail.com", "com.google",
316        "sampleuser@gmail.com"};
317// Submit the query and get a Cursor object back.
318cur = cr.query(uri, EVENT_PROJECTION, selection, selectionArgs, null);</pre>
319
320<p>다음에 표시된 섹션에서는 커서를 사용하여 결과 집합을 단계별로 살펴봅니다.
321여기에서는 예시의 시작 부분에서 설정된 상수를 사용하여 각 필드에 대한 값을 반환합니다.
322</p>
323
324<pre>// Use the cursor to step through the returned records
325while (cur.moveToNext()) {
326    long calID = 0;
327    String displayName = null;
328    String accountName = null;
329    String ownerName = null;
330
331    // Get the field values
332    calID = cur.getLong(PROJECTION_ID_INDEX);
333    displayName = cur.getString(PROJECTION_DISPLAY_NAME_INDEX);
334    accountName = cur.getString(PROJECTION_ACCOUNT_NAME_INDEX);
335    ownerName = cur.getString(PROJECTION_OWNER_ACCOUNT_INDEX);
336
337    // Do something with the values...
338
339   ...
340}
341</pre>
342
343<h3 id="modify-calendar">캘린더 수정</h3>
344
345<p>캘린더 업데이트를 수행하려면 캘린더의 {@link
346android.provider.BaseColumns#_ID}를
347URI에 추가된 ID로
348
349({@link android.content.ContentUris#withAppendedId(android.net.Uri,long) withAppendedId()}), 또는 첫 번째 선택 항목으로 제공하면 됩니다.
350
351선택은 <code>&quot;_id=?&quot;</code>로 시작해야 하며, 첫 번째
352<code>selectionArg</code>는 캘린더의 {@link
353android.provider.BaseColumns#_ID}여야 합니다.
354또한 ID를 URI에 인코딩해서도 업데이트를 수행할 수 있습니다. 이 예시에서는 캘린더의 표시 이름을
355
356({@link android.content.ContentUris#withAppendedId(android.net.Uri,long) withAppendedId()})
357방식으로 변경하였습니다.</p>
358
359<pre>private static final String DEBUG_TAG = "MyActivity";
360...
361long calID = 2;
362ContentValues values = new ContentValues();
363// The new display name for the calendar
364values.put(Calendars.CALENDAR_DISPLAY_NAME, &quot;Trevor's Calendar&quot;);
365Uri updateUri = ContentUris.withAppendedId(Calendars.CONTENT_URI, calID);
366int rows = getContentResolver().update(updateUri, values, null, null);
367Log.i(DEBUG_TAG, &quot;Rows updated: &quot; + rows);</pre>
368
369<h3 id="insert-calendar">캘린더 삽입</h2>
370
371<p>캘린더는 주로 동기화 어댑터가 관리하도록 설계되어 있습니다. 따라서 새 캘린더는
372동기화 어댑터로서만 삽입해야 합니다. 대다수의 경우 애플리케이션은 캘린더에
373표면적인 사항만 변경할 수 있게 되어 있습니다(예: 표시 이름 변경 등).
374어떤 애플리케이션이 로컬 캘린더를 생성해야 하는 경우, 캘린더 삽입을 동기화 어댑터로 수행하면 됩니다.
375이때 {@link
376android.provider.CalendarContract#ACCOUNT_TYPE_LOCAL}의 {@link
377android.provider.CalendarContract.SyncColumns#ACCOUNT_TYPE}을 사용합니다.
378{@link android.provider.CalendarContract#ACCOUNT_TYPE_LOCAL}
379은 기기 계정과 연관되지 않은 캘린더에 적용되는 특별한 유형의 계정입니다.
380 이 유형의 캘린더는 서버에 동기화되지 않습니다.
381동기화 어댑터에 대한 논의는 <a href="#sync-adapter">동기화 어댑터</a>를 참조하십시오.</p>
382
383<h2 id="events">이벤트 테이블</h2>
384
385<p>{@link android.provider.CalendarContract.Events}
386테이블에는 각각의 이벤트에 대한 세부 정보가 들어 있습니다. 이벤트를 추가, 업데이트 또는 삭제하려면 애플리케이션의
387<a href="#manifest">매니페스트 파일</a>에 {@link android.Manifest.permission#WRITE_CALENDAR}
388권한이 포함되어 있어야 합니다.</p>
389
390<p>다음 이벤트 열은 애플리케이션과
391동기화 어댑터 모두 쓸 수 있는 것입니다. 지원되는 필드의 전체 목록은 {@link
392android.provider.CalendarContract.Events} 참조를 확인하십시오.</p>
393
394<table>
395  <tr>
396    <th>상수</th>
397    <th>설명</th>
398  </tr>
399  <tr>
400    <td>{@link android.provider.CalendarContract.EventsColumns#CALENDAR_ID}</td>
401    <td>이벤트가 속한 캘린더의 {@link android.provider.BaseColumns#_ID}입니다.</td>
402  </tr>
403  <tr>
404    <td>{@link android.provider.CalendarContract.EventsColumns#ORGANIZER}</td>
405    <td>이벤트 조직자(소유자)의 이메일입니다.</td>
406  </tr>
407  <tr>
408    <td>{@link android.provider.CalendarContract.EventsColumns#TITLE}</td>
409    <td>이벤트 제목입니다.</td>
410  </tr>
411  <tr>
412    <td>{@link android.provider.CalendarContract.EventsColumns#EVENT_LOCATION}</td>
413    <td>이벤트가 일어나는 장소입니다. </td>
414  </tr>
415  <tr>
416    <td>{@link android.provider.CalendarContract.EventsColumns#DESCRIPTION}</td>
417    <td>이벤트 설명입니다.</td>
418  </tr>
419  <tr>
420    <td>{@link android.provider.CalendarContract.EventsColumns#DTSTART}</td>
421    <td>이벤트가 시작되는 시간을 Epoch 이후 UTC 밀리초 단위로 나타낸 것입니다. </td>
422  </tr>
423  <tr>
424    <td>{@link android.provider.CalendarContract.EventsColumns#DTEND}</td>
425    <td>이벤트가 종료되는 시간을 Epoch 이후 UTC 밀리초 단위로 나타낸 것입니다. </td>
426  </tr>
427  <tr>
428    <td>{@link android.provider.CalendarContract.EventsColumns#EVENT_TIMEZONE}</td>
429    <td>이벤트의 표준 시간대입니다.</td>
430  </tr>
431  <tr>
432    <td>{@link android.provider.CalendarContract.EventsColumns#EVENT_END_TIMEZONE}</td>
433    <td>이벤트 종료 시간의 표준 시간대입니다.</td>
434  </tr>
435  <tr>
436    <td>{@link android.provider.CalendarContract.EventsColumns#DURATION}</td>
437
438    <td>이벤트 기간을 <a href="http://tools.ietf.org/html/rfc5545#section-3.8.2.5">RFC5545</a> 형식으로 나타낸 것입니다.
439예를 들어 <code>&quot;PT1H&quot;</code> 값을 보면 이벤트가 한 시간 지속될 것임을 알 수 있고,
440<code>&quot;P2W&quot;</code>는 2주의 지속 기간을 나타냅니다.
441 </td>
442
443
444  </tr>
445  <tr>
446    <td>{@link android.provider.CalendarContract.EventsColumns#ALL_DAY}</td>
447
448    <td>값이 1이면 이 이벤트가 현지 시간대에서 정의한 바에 의해 하루 종일 걸린다는 것을 나타냅니다.
449 값이 0이면 이것이 하루 중 언제라도 시작하고 종료될 수 있는 정기 이벤트라는 것을 나타냅니다.
450</td>
451
452
453  </tr>
454
455
456  <tr>
457    <td>{@link android.provider.CalendarContract.EventsColumns#RRULE}</td>
458
459    <td>이벤트 형식의 반복 규칙입니다.
460예를 들면 다음과 같습니다. <code>&quot;FREQ=WEEKLY;COUNT=10;WKST=SU&quot;</code> 더 많은 예시를 확인하려면
461<a href="http://tools.ietf.org/html/rfc5545#section-3.8.5.3">여기</a>를 참조하십시오.</td>
462
463  </tr>
464
465  <tr>
466    <td>{@link android.provider.CalendarContract.EventsColumns#RDATE}</td>
467    <td>이벤트의 반복 날짜입니다.
468일반적으로 {@link android.provider.CalendarContract.EventsColumns#RDATE}
469를 {@link android.provider.CalendarContract.EventsColumns#RRULE}
470과 함께 사용하여 반복되는 발생의 집계 집합을 정의하게 됩니다.
471 자세한 논의는 <a href="http://tools.ietf.org/html/rfc5545#section-3.8.5.2">RFC5545 사양</a>을 참조하십시오.</td>
472</tr>
473
474  <tr>
475    <td>{@link android.provider.CalendarContract.EventsColumns#AVAILABILITY}</td>
476
477    <td>이 이벤트가 사용 중인 시간으로 간주되는지, 다시 일정을 예약할 수 있는 자유 시간으로 간주되는지를 나타냅니다.
478 </td>
479
480  </tr>
481  <tr>
482    <td>{@link android.provider.CalendarContract.EventsColumns#GUESTS_CAN_MODIFY}</td>
483    <td>게스트가 이벤트를 수정할 수 있는지를 나타냅니다. </td>
484  </tr>
485  <tr>
486    <td>{@link android.provider.CalendarContract.EventsColumns#GUESTS_CAN_INVITE_OTHERS}</td>
487    <td>게스트가 다른 게스트를 초대할 수 있는지를 나타냅니다. </td>
488  </tr>
489  <tr>
490    <td>{@link android.provider.CalendarContract.EventsColumns#GUESTS_CAN_SEE_GUESTS}</td>
491    <td>게스트가 참석자 목록을 볼 수 있는지를 나타냅니다.</td>
492  </tr>
493</table>
494
495<h3 id="add-event">이벤트 추가</h3>
496
497<p>애플리케이션이 새 이벤트를 추가하는 경우,
498{@link android.content.Intent#ACTION_INSERT INSERT} 인텐트를 사용하는 것이 좋습니다. 이때 <a href="#intent-insert">인텐트를 사용하여 이벤트 삽입</a>에서 설명한 대로 따릅니다. 그러나, 필요한 경우 직접 이벤트를 삽입해도 됩니다.
499 이 섹션에서는 이렇게 하는 방법을 설명합니다.
500</p>
501
502
503<p>다음은 새 이벤트를 삽입할 때 따라야 하는 규칙입니다. </p>
504<ul>
505
506  <li>{@link
507android.provider.CalendarContract.EventsColumns#CALENDAR_ID}와 {@link
508android.provider.CalendarContract.EventsColumns#DTSTART}를 포함해야 합니다.</li>
509
510<li>{@link
511android.provider.CalendarContract.EventsColumns#EVENT_TIMEZONE}을 포함해야 합니다.
512시스템에 설치된 표준 시간대 ID 목록을 가져오려면 {@link
513java.util.TimeZone#getAvailableIDs()}를 사용하십시오. 이 규칙은 <a href="#intent-insert">인텐트를 사용하여 이벤트 삽입</a>에서 설명한 바와 같이
514{@link
515android.content.Intent#ACTION_INSERT INSERT} 인텐트를 통해서 이벤트를 삽입할 경우에는 적용되지 않습니다. 이 시나리오의 경우,
516기본 시간대가 제공됩니다.</li>
517
518  <li>비반복적인 이벤트의 경우, {@link
519android.provider.CalendarContract.EventsColumns#DTEND}를 포함해야 합니다. </li>
520
521
522  <li>반복적인 이벤트의 경우 {@link
523android.provider.CalendarContract.EventsColumns#DURATION}과 {@link
524android.provider.CalendarContract.EventsColumns#RRULE} 또는 {@link
525android.provider.CalendarContract.EventsColumns#RDATE}를 포함해야 합니다. 이 규칙은 <a href="#intent-insert">인텐트를 사용하여 이벤트 삽입</a>에서 설명한 바와 같이
526{@link
527android.content.Intent#ACTION_INSERT INSERT} 인텐트를 통해서 이벤트를 삽입할 경우에는 적용되지 않습니다.
528이 시나리오에서는 {@link android.provider.CalendarContract.EventsColumns#DTSTART} 및 {@link android.provider.CalendarContract.EventsColumns#DTEND}와 함께 {@link
529android.provider.CalendarContract.EventsColumns#RRULE}를 사용할 수 있고, 캘린더 애플리케이션이 이것을 기간으로 자동 변환해줍니다.
530</li>
531
532</ul>
533
534<p>다음은 이벤트 삽입의 예입니다. 단순하게 나타내기 위해 UI 스레드에서 수행한 것입니다.
535 실제로, 삽입과 업데이트는 비동기화 스레드에서 수행해야 작업을 배경 스레드로 이동시킬 수 있습니다.
536
537자세한 정보는 {@link android.content.AsyncQueryHandler}를 참조하십시오.</p>
538
539
540<pre>
541long calID = 3;
542long startMillis = 0;
543long endMillis = 0;
544Calendar beginTime = Calendar.getInstance();
545beginTime.set(2012, 9, 14, 7, 30);
546startMillis = beginTime.getTimeInMillis();
547Calendar endTime = Calendar.getInstance();
548endTime.set(2012, 9, 14, 8, 45);
549endMillis = endTime.getTimeInMillis();
550...
551
552ContentResolver cr = getContentResolver();
553ContentValues values = new ContentValues();
554values.put(Events.DTSTART, startMillis);
555values.put(Events.DTEND, endMillis);
556values.put(Events.TITLE, &quot;Jazzercise&quot;);
557values.put(Events.DESCRIPTION, &quot;Group workout&quot;);
558values.put(Events.CALENDAR_ID, calID);
559values.put(Events.EVENT_TIMEZONE, "America/Los_Angeles");
560Uri uri = cr.insert(Events.CONTENT_URI, values);
561
562// get the event ID that is the last element in the Uri
563long eventID = Long.parseLong(uri.getLastPathSegment());
564//
565// ... do something with event ID
566//
567//</pre>
568
569<p class="note"><strong>참고:</strong> 이벤트가 생성된 다음 이 예시가 이벤트 ID를 캡처하는 법을 눈여겨 보십시오.
570 이것이 이벤트 ID를 가져오는 가장 쉬운 방법입니다.
571다른 캘린더 작업을 수행하기 위해 이벤트 ID가 필요한 경우가 자주 있습니다. 예를 들어 이벤트에 참석자나 알림을 추가하는 데 필요합니다.
572</p>
573
574
575<h3 id="update-event">이벤트 업데이트</h3>
576
577<p>애플리케이션이 사용자에게 이벤트 편집을 허용할 경우, <a href="#intent-edit">인텐트로 이벤트 편집</a>에서 설명한 바와 같이
578{@link android.content.Intent#ACTION_EDIT EDIT} 인텐트
579를 사용하는 것이 좋습니다.
580그러나 필요한 경우 직접 이벤트를 편집해도 됩니다.
581이벤트 업데이트를 수행하려면 이벤트의 <code>_ID</code>를 URI에 추가된 ID로({@link
582android.content.ContentUris#withAppendedId(android.net.Uri,long) withAppendedId()})
583또는 첫 번째 선택 항목으로 제공하면 됩니다.
584
585선택은 <code>&quot;_id=?&quot;</code>로 시작해야 하며, 첫 번째
586<code>selectionArg</code>는 이벤트의 <code>_ID</code>여야 합니다.
587ID 없이 선택을 사용해도 업데이트를 수행할 수 있습니다. 다음은 이벤트 업데이트의 예입니다.
588 여기에서는 이벤트 제목을 변경할 때
589{@link android.content.ContentUris#withAppendedId(android.net.Uri,long) withAppendedId()}
590 방법을 사용합니다.</p>
591
592
593<pre>private static final String DEBUG_TAG = "MyActivity";
594...
595long eventID = 188;
596...
597ContentResolver cr = getContentResolver();
598ContentValues values = new ContentValues();
599Uri updateUri = null;
600// The new title for the event
601values.put(Events.TITLE, &quot;Kickboxing&quot;);
602updateUri = ContentUris.withAppendedId(Events.CONTENT_URI, eventID);
603int rows = getContentResolver().update(updateUri, values, null, null);
604Log.i(DEBUG_TAG, &quot;Rows updated: &quot; + rows);  </pre>
605
606<h3 id="delete-event">이벤트 삭제</h3>
607
608<p>이벤트를 삭제하려면 이벤트의 {@link
609android.provider.BaseColumns#_ID}를 URI에 추가된 ID로 써도 되고, 표준 선택을 사용해도 됩니다.
610 추가된 ID를 사용하는 경우, 선택도 할 수 없습니다.
611삭제에는 두 가지 버전이 있습니다. 애플리케이션으로 삭제와 동기화 어댑터로의 삭제입니다.
612애플리케이션 삭제의 경우 <em>삭제된</em> 열을 1로 설정합니다.
613이것은 동기화 어댑터에 행이 삭제되었다고 알리는 플래그이며,
614이 삭제를 서버에 알려야 한다는 것을 나타내기도 합니다.
615동기화 어댑터 삭제의 경우, 이벤트를 연관된 데이터 일체와 함께 데이터베이스에서 제거합니다.
616다음은 애플리케이션이 이벤트를 {@link android.provider.BaseColumns#_ID}를 통해 삭제하는 예입니다.</p>
617
618
619<pre>private static final String DEBUG_TAG = "MyActivity";
620...
621long eventID = 201;
622...
623ContentResolver cr = getContentResolver();
624ContentValues values = new ContentValues();
625Uri deleteUri = null;
626deleteUri = ContentUris.withAppendedId(Events.CONTENT_URI, eventID);
627int rows = getContentResolver().delete(deleteUri, null, null);
628Log.i(DEBUG_TAG, &quot;Rows deleted: &quot; + rows);
629</pre>
630
631<h2 id="attendees">참석자 테이블</h2>
632
633<p>{@link android.provider.CalendarContract.Attendees} 테이블의 각 행은
634이벤트의 참석자 또는 게스트 하나를 나타냅니다.
635{@link android.provider.CalendarContract.Reminders#query(android.content.ContentResolver, long, java.lang.String[]) query()}
636를호출하면 주어진
637{@link android.provider.CalendarContract.AttendeesColumns#EVENT_ID}와 함께 해당 이벤트의 참석자 목록을 반환합니다.
638이 {@link android.provider.CalendarContract.AttendeesColumns#EVENT_ID}는
639 특정 이벤트의 {@link
640android.provider.BaseColumns#_ID}와 반드시 일치해야 합니다.</p>
641
642<p>다음 표는 쓸 수 있는 필드를 목록으로 나열한 것입니다.
643 새 참석자를 삽입하는 경우 이 모두를 포함해야 하며,
644단 <code>ATTENDEE_NAME</code>은 예외입니다.
645</p>
646
647
648<table>
649  <tr>
650    <th>상수</th>
651    <th>설명</th>
652  </tr>
653  <tr>
654    <td>{@link android.provider.CalendarContract.AttendeesColumns#EVENT_ID}</td>
655    <td>이벤트 ID입니다.</td>
656  </tr>
657  <tr>
658    <td>{@link android.provider.CalendarContract.AttendeesColumns#ATTENDEE_NAME}</td>
659    <td>참석자 이름입니다.</td>
660  </tr>
661  <tr>
662    <td>{@link android.provider.CalendarContract.AttendeesColumns#ATTENDEE_EMAIL}</td>
663    <td>참석자 이메일 주소입니다.</td>
664  </tr>
665  <tr>
666    <td>{@link android.provider.CalendarContract.AttendeesColumns#ATTENDEE_RELATIONSHIP}</td>
667    <td><p>참석자와 이벤트의 관계입니다. 다음 중 하나로 정해집니다.</p>
668      <ul>
669        <li>{@link android.provider.CalendarContract.AttendeesColumns#RELATIONSHIP_ATTENDEE}</li>
670        <li>{@link android.provider.CalendarContract.AttendeesColumns#RELATIONSHIP_NONE}</li>
671        <li>{@link android.provider.CalendarContract.AttendeesColumns#RELATIONSHIP_ORGANIZER}</li>
672        <li>{@link android.provider.CalendarContract.AttendeesColumns#RELATIONSHIP_PERFORMER}</li>
673        <li>{@link android.provider.CalendarContract.AttendeesColumns#RELATIONSHIP_SPEAKER}</li>
674    </ul>
675    </td>
676  </tr>
677  <tr>
678    <td>{@link android.provider.CalendarContract.AttendeesColumns#ATTENDEE_TYPE}</td>
679    <td><p>참석자 유형입니다. 다음 중 하나로 정해집니다. </p>
680      <ul>
681        <li>{@link android.provider.CalendarContract.AttendeesColumns#TYPE_REQUIRED}</li>
682        <li>{@link android.provider.CalendarContract.AttendeesColumns#TYPE_OPTIONAL}</li>
683    </ul></td>
684  </tr>
685  <tr>
686    <td>{@link android.provider.CalendarContract.AttendeesColumns#ATTENDEE_STATUS}</td>
687    <td><p>참석자의 참석 상태입니다. 다음 중 하나로 정해집니다.</p>
688      <ul>
689        <li>{@link android.provider.CalendarContract.AttendeesColumns#ATTENDEE_STATUS_ACCEPTED}</li>
690        <li>{@link android.provider.CalendarContract.AttendeesColumns#ATTENDEE_STATUS_DECLINED}</li>
691        <li>{@link android.provider.CalendarContract.AttendeesColumns#ATTENDEE_STATUS_INVITED}</li>
692        <li>{@link android.provider.CalendarContract.AttendeesColumns#ATTENDEE_STATUS_NONE}</li>
693        <li>{@link android.provider.CalendarContract.AttendeesColumns#ATTENDEE_STATUS_TENTATIVE}</li>
694    </ul></td>
695  </tr>
696</table>
697
698<h3 id="add-attendees">참석자 추가</h3>
699
700<p>다음은 이벤트에 참석자 한 명을 추가하는 예입니다.
701{@link android.provider.CalendarContract.AttendeesColumns#EVENT_ID}
702가 필수인 점을 유념하십시오.</p>
703
704<pre>
705long eventID = 202;
706...
707ContentResolver cr = getContentResolver();
708ContentValues values = new ContentValues();
709values.put(Attendees.ATTENDEE_NAME, &quot;Trevor&quot;);
710values.put(Attendees.ATTENDEE_EMAIL, &quot;trevor@example.com&quot;);
711values.put(Attendees.ATTENDEE_RELATIONSHIP, Attendees.RELATIONSHIP_ATTENDEE);
712values.put(Attendees.ATTENDEE_TYPE, Attendees.TYPE_OPTIONAL);
713values.put(Attendees.ATTENDEE_STATUS, Attendees.ATTENDEE_STATUS_INVITED);
714values.put(Attendees.EVENT_ID, eventID);
715Uri uri = cr.insert(Attendees.CONTENT_URI, values);
716</pre>
717
718<h2 id="reminders">알림 테이블</h2>
719
720<p>{@link android.provider.CalendarContract.Reminders}
721테이블의 각 행은 이벤트의 알림 하나를 나타냅니다.
722{@link android.provider.CalendarContract.Reminders#query(android.content.ContentResolver, long, java.lang.String[]) query()} 를 호출하면
723
724주어진 {@link android.provider.CalendarContract.AttendeesColumns#EVENT_ID}와 함께 이벤트 알림 목록을 반환합니다.</p>
725
726
727<p>다음 표는 알림의 쓸 수 있는 필드를 목록으로 나열한 것입니다. 새 알림을 삽입하는 경우 이 모두를 포함해야 합니다.
728 동기화 어댑터가 {@link
729android.provider.CalendarContract.Calendars} 테이블에서 지원하는 알림을 나타낸다는 점을 눈여겨 보십시오.
730 자세한 내용은
731{@link android.provider.CalendarContract.CalendarColumns#ALLOWED_REMINDERS}
732를 참조하십시오.</p>
733
734
735<table>
736  <tr>
737    <th>상수</th>
738    <th>설명</th>
739  </tr>
740  <tr>
741    <td>{@link android.provider.CalendarContract.RemindersColumns#EVENT_ID}</td>
742    <td>이벤트 ID입니다.</td>
743  </tr>
744  <tr>
745    <td>{@link android.provider.CalendarContract.RemindersColumns#MINUTES}</td>
746    <td>이벤트 몇 분 전에 알림을 보내야 하는지 나타냅니다.</td>
747  </tr>
748  <tr>
749    <td>{@link android.provider.CalendarContract.RemindersColumns#METHOD}</td>
750    <td><p>알림 메서드이며, 서버에서 설정한 대로 따릅니다. 다음 중 하나로 정해집니다.</p>
751      <ul>
752        <li>{@link android.provider.CalendarContract.RemindersColumns#METHOD_ALERT}</li>
753        <li>{@link android.provider.CalendarContract.RemindersColumns#METHOD_DEFAULT}</li>
754        <li>{@link android.provider.CalendarContract.RemindersColumns#METHOD_EMAIL}</li>
755        <li>{@link android.provider.CalendarContract.RemindersColumns#METHOD_SMS}</li>
756    </ul></td>
757  </tr>
758</table>
759
760<h3 id="add-reminders">알림 추가</h3>
761
762<p>이 예시는 이벤트에 알림을 추가하는 것입니다. 알림이 이벤트 15분 전에 발송됩니다.
763</p>
764<pre>
765long eventID = 221;
766...
767ContentResolver cr = getContentResolver();
768ContentValues values = new ContentValues();
769values.put(Reminders.MINUTES, 15);
770values.put(Reminders.EVENT_ID, eventID);
771values.put(Reminders.METHOD, Reminders.METHOD_ALERT);
772Uri uri = cr.insert(Reminders.CONTENT_URI, values);</pre>
773
774<h2 id="instances">인스턴스 테이블</h2>
775
776<p>
777{@link android.provider.CalendarContract.Instances} 테이블에는
778이벤트 발생의 시작 및 종료 시간이 담겨 있습니다. 이 테이블의 각 행이 하나의 이벤트 발생을 나타냅니다.
779 이 인스턴스 테이블은 쓸 수 없으며 이벤트 발생 쿼리 방법을 제공할 뿐입니다.
780 </p>
781
782<p>다음 표에는 인스턴스에 대해 쿼리할 수 있는 몇 가지 필드를 목록으로 나열하였습니다.
783표준 시간대가
784{@link android.provider.CalendarContract.CalendarCache#KEY_TIMEZONE_TYPE}
785786{@link android.provider.CalendarContract.CalendarCache#KEY_TIMEZONE_INSTANCES}에 의해 정의된다는 점을 눈여겨 보십시오.</p>
787
788
789<table>
790  <tr>
791    <th>상수</th>
792    <th>설명</th>
793  </tr>
794  <tr>
795    <td>{@link android.provider.CalendarContract.Instances#BEGIN}</td>
796    <td>인스턴스 시작 시간을 UTC 밀리초로 나타낸 것입니다.</td>
797  </tr>
798  <tr>
799    <td>{@link android.provider.CalendarContract.Instances#END}</td>
800    <td>인스턴스 종료 시간을 UTC 밀리초로 나타낸 것입니다.</td>
801  </tr>
802  <tr>
803    <td>{@link android.provider.CalendarContract.Instances#END_DAY}</td>
804
805    <td>인스턴스의 율리우스력 종료 날짜를 캘린더의 시간대에 비례하여 나타낸 것입니다.
806
807
808</td>
809  </tr>
810  <tr>
811    <td>{@link android.provider.CalendarContract.Instances#END_MINUTE}</td>
812
813    <td>인스턴스의 종료 시간(분 단위)을 캘린더 시간대의 자정부터 측정한 것입니다.
814</td>
815
816  </tr>
817  <tr>
818    <td>{@link android.provider.CalendarContract.Instances#EVENT_ID}</td>
819    <td>이 인스턴스에 대한 이벤트의 <code>_ID</code>입니다.</td>
820  </tr>
821    <tr>
822    <td>{@link android.provider.CalendarContract.Instances#START_DAY}</td>
823    <td>인스턴스의 율리우스력 시작 날짜를 캘린더의 시간대에 비례하여 나타낸 것입니다.
824 </td>
825  </tr>
826  <tr>
827    <td>{@link android.provider.CalendarContract.Instances#START_MINUTE}</td>
828
829    <td>인스턴스의 시작 시간(분 단위)을 캘린더 시간대에 비례하여 자정부터 측정한 것입니다.
830
831</td>
832
833  </tr>
834
835</table>
836
837<h3 id="query-instances">인스턴스 테이블 쿼리</h3>
838
839<p>인스턴스 테이블을 쿼리하려면, 해당 쿼리에 대한 범위 시간을 URI에 지정해야 합니다.
840 이 예시에서는 {@link android.provider.CalendarContract.Instances}
841가 {@link
842android.provider.CalendarContract.EventsColumns#TITLE} 필드에 액세스 권한을 얻으며, 이때
843{@link android.provider.CalendarContract.EventsColumns} 인터페이스의 구현을 통합니다.
844바꿔 말하면, {@link
845android.provider.CalendarContract.EventsColumns#TITLE}이
846데이터베이스 보기를 통해 반환되며 원시 {@link
847android.provider.CalendarContract.Instances} 테이블 쿼리를 통해서가 아니라는 뜻입니다.</p>
848
849<pre>
850private static final String DEBUG_TAG = "MyActivity";
851public static final String[] INSTANCE_PROJECTION = new String[] {
852    Instances.EVENT_ID,      // 0
853    Instances.BEGIN,         // 1
854    Instances.TITLE          // 2
855  };
856
857// The indices for the projection array above.
858private static final int PROJECTION_ID_INDEX = 0;
859private static final int PROJECTION_BEGIN_INDEX = 1;
860private static final int PROJECTION_TITLE_INDEX = 2;
861...
862
863// Specify the date range you want to search for recurring
864// event instances
865Calendar beginTime = Calendar.getInstance();
866beginTime.set(2011, 9, 23, 8, 0);
867long startMillis = beginTime.getTimeInMillis();
868Calendar endTime = Calendar.getInstance();
869endTime.set(2011, 10, 24, 8, 0);
870long endMillis = endTime.getTimeInMillis();
871
872Cursor cur = null;
873ContentResolver cr = getContentResolver();
874
875// The ID of the recurring event whose instances you are searching
876// for in the Instances table
877String selection = Instances.EVENT_ID + " = ?";
878String[] selectionArgs = new String[] {"207"};
879
880// Construct the query with the desired date range.
881Uri.Builder builder = Instances.CONTENT_URI.buildUpon();
882ContentUris.appendId(builder, startMillis);
883ContentUris.appendId(builder, endMillis);
884
885// Submit the query
886cur =  cr.query(builder.build(),
887    INSTANCE_PROJECTION,
888    selection,
889    selectionArgs,
890    null);
891
892while (cur.moveToNext()) {
893    String title = null;
894    long eventID = 0;
895    long beginVal = 0;
896
897    // Get the field values
898    eventID = cur.getLong(PROJECTION_ID_INDEX);
899    beginVal = cur.getLong(PROJECTION_BEGIN_INDEX);
900    title = cur.getString(PROJECTION_TITLE_INDEX);
901
902    // Do something with the values.
903    Log.i(DEBUG_TAG, "Event:  " + title);
904    Calendar calendar = Calendar.getInstance();
905    calendar.setTimeInMillis(beginVal);
906    DateFormat formatter = new SimpleDateFormat("MM/dd/yyyy");
907    Log.i(DEBUG_TAG, "Date: " + formatter.format(calendar.getTime()));
908    }
909 }</pre>
910
911<h2 id="intents">캘린더 인텐트</h2>
912<p>캘린더 데이터를 읽고 쓰려면 애플리케이션에 <a href="#manifest">권한</a>이 없어도 됩니다. 대신 Android의 캘린더 애플리케이션이 지원하는 인텐트를 사용하여 해당 애플리케이션에 읽기 및 쓰기 작업을 분배하면 됩니다. 다음 표는 캘린더 제공자가 지원하는 인텐트를 목록으로 나열한 것입니다.</p>
913<table>
914  <tr>
915    <th>동작</th>
916    <th>URI</th>
917
918    <th>설명</th>
919    <th>추가</th>
920  </tr>
921  <tr>
922    <td><br>
923    {@link android.content.Intent#ACTION_VIEW VIEW} <br></td>
924    <td><p><code>content://com.android.calendar/time/&lt;ms_since_epoch&gt;</code></p>
925
926{@link android.provider.CalendarContract#CONTENT_URI CalendarContract.CONTENT_URI}로도 URI를 참조할 수 있습니다.
927이 인텐트 사용법의 예시를 보려면 <a href="{@docRoot}guide/topics/providers/calendar-provider.html#intent-view">인텐트를 사용하여 캘린더 데이터 보기</a>를 참조하십시오.
928
929    </td>
930    <td>캘린더를 <code>&lt;ms_since_epoch&gt;</code>에 의해 지정된 시간으로 엽니다.</td>
931    <td>없음.</td>
932  </tr>
933  <tr>
934    <td><p>{@link android.content.Intent#ACTION_VIEW VIEW} </p>
935
936     </td>
937    <td><p><code>content://com.android.calendar/events/&lt;event_id&gt;</code></p>
938
939
940{@link android.provider.CalendarContract.Events#CONTENT_URI Events.CONTENT_URI}로도 URI를 참조할 수 있습니다.
941이 인텐트 사용법의 예시를 보려면 <a href="{@docRoot}guide/topics/providers/calendar-provider.html#intent-view">인텐트를 사용하여 캘린더 데이터 보기</a>를 참조하십시오.
942
943    </td>
944    <td><code>&lt;event_id&gt;</code>에 의해 지정된 이벤트를 봅니다.</td>
945
946    <td>{@link android.provider.CalendarContract#EXTRA_EVENT_BEGIN_TIME CalendarContract.EXTRA_EVENT_BEGIN_TIME}<br>
947      <br>
948      <br>
949    {@link android.provider.CalendarContract#EXTRA_EVENT_END_TIME CalendarContract.EXTRA_EVENT_END_TIME}</td>
950  </tr>
951
952  <tr>
953    <td>{@link android.content.Intent#ACTION_EDIT EDIT} </td>
954    <td><p><code>content://com.android.calendar/events/&lt;event_id&gt;</code></p>
955
956
957{@link android.provider.CalendarContract.Events#CONTENT_URI Events.CONTENT_URI}로도 URI를 참조할 수 있습니다.
958이 인텐트 사용법의 예시를 보려면 <a href="{@docRoot}guide/topics/providers/calendar-provider.html#intent-edit">인텐트를 사용하여 이벤트 편집</a>을 참조하십시오.
959
960
961    </td>
962    <td><code>&lt;event_id&gt;</code>에 의해 지정된 이벤트를 편집합니다.</td>
963
964    <td>{@link android.provider.CalendarContract#EXTRA_EVENT_BEGIN_TIME CalendarContract.EXTRA_EVENT_BEGIN_TIME}<br>
965      <br>
966      <br>
967    {@link android.provider.CalendarContract#EXTRA_EVENT_END_TIME CalendarContract.EXTRA_EVENT_END_TIME}</td>
968  </tr>
969
970  <tr>
971    <td>{@link android.content.Intent#ACTION_EDIT EDIT} <br>
972    <br>
973    {@link android.content.Intent#ACTION_INSERT INSERT} </td>
974    <td><p><code>content://com.android.calendar/events</code></p>
975
976
977{@link android.provider.CalendarContract.Events#CONTENT_URI Events.CONTENT_URI}로도 URI를 참조할 수 있습니다.
978이 인텐트 사용법의 예시를 보려면 <a href="{@docRoot}guide/topics/providers/calendar-provider.html#intent-insert">인텐트를 사용하여 이벤트 삽입</a>을 참조하십시오.
979
980    </td>
981
982    <td>이벤트를 생성합니다.</td>
983    <td>아래 테이블에 목록으로 표시된 추가 사항 모두입니다.</td>
984  </tr>
985</table>
986
987<p>다음 표에는 캘린더 제공자가 지원하는 인텐트 추가 사항이 목록으로 나열되어 있습니다.
988</p>
989<table>
990  <tr>
991    <th>인텐트 추가 사항</th>
992    <th>설명</th>
993  </tr>
994  <tr>
995    <td>{@link android.provider.CalendarContract.EventsColumns#TITLE Events.TITLE}</td>
996    <td>이벤트의 이름입니다.</td>
997  </tr>
998  <tr>
999
1000    <td>{@link android.provider.CalendarContract#EXTRA_EVENT_BEGIN_TIME
1001CalendarContract.EXTRA_EVENT_BEGIN_TIME}</td>
1002    <td>이벤트 시작 시간을 Epoch로부터 밀리초 단위로 나타낸 것입니다.</td>
1003  </tr>
1004  <tr>
1005    <td>{@link android.provider.CalendarContract#EXTRA_EVENT_END_TIME
1006CalendarContract.EXTRA_EVENT_END_TIME}</td>
1007
1008    <td>이벤트 종료 시간을 Epoch로부터 밀리초 단위로 나타낸 것입니다.</td>
1009  </tr>
1010  <tr>
1011    <td>{@link android.provider.CalendarContract#EXTRA_EVENT_ALL_DAY
1012CalendarContract.EXTRA_EVENT_ALL_DAY}</td>
1013
1014    <td>이벤트가 종일 이벤트인지 나타내는 부울입니다. 값은
1015<code>true</code> 또는 <code>false</code>가 될 수 있습니다.</td> </tr>
1016  <tr>
1017    <td>{@link android.provider.CalendarContract.EventsColumns#EVENT_LOCATION
1018Events.EVENT_LOCATION}</td>
1019
1020    <td>이벤트 위치입니다.</td>
1021  </tr>
1022  <tr>
1023    <td>{@link android.provider.CalendarContract.EventsColumns#DESCRIPTION
1024Events.DESCRIPTION}</td>
1025
1026    <td>이벤트 설명입니다.</td>
1027  </tr>
1028  <tr>
1029    <td>
1030    {@link android.content.Intent#EXTRA_EMAIL Intent.EXTRA_EMAIL}</td>
1031    <td>초대할 사람의 이메일 주소를 쉼표로 구분한 목록입니다.</td>
1032  </tr>
1033  <tr>
1034    <td>
1035    {@link android.provider.CalendarContract.EventsColumns#RRULE Events.RRULE}</td>
1036    <td>이벤트의 반복 규칙입니다.</td>
1037  </tr>
1038  <tr>
1039    <td>
1040    {@link android.provider.CalendarContract.EventsColumns#ACCESS_LEVEL
1041Events.ACCESS_LEVEL}</td>
1042
1043    <td>이벤트가 비공개인지 공개인지 나타냅니다.</td>
1044  </tr>
1045  <tr>
1046    <td>{@link android.provider.CalendarContract.EventsColumns#AVAILABILITY
1047Events.AVAILABILITY}</td>
1048
1049    <td>이 이벤트가 사용 중인 시간으로 간주되는지, 다시 일정을 예약할 수 있는 자유 시간으로 간주되는지를 나타냅니다.</td>
1050
1051</table>
1052<p>아래 섹션에서는 이와 같은 인텐트의 사용법을 설명합니다.</p>
1053
1054
1055<h3 id="intent-insert">인텐트를 사용하여 이벤트 삽입</h3>
1056
1057<p>{@link android.content.Intent#ACTION_INSERT INSERT} 인텐트를 사용하면
1058캘린더에 이벤트 삽입 작업을 분배할 수 있습니다.
1059이 방법을 사용하는 경우, 애플리케이션의 <a href="#manifest">매니페스트 파일</a>에 {@link
1060android.Manifest.permission#WRITE_CALENDAR} 권한을 포함할 필요가 없습니다.</p>
1061
1062
1063<p>사용자가 이 방법을 사용하는 애플리케이션을 실행하면 해당 애플리케이션이
1064사용자를 캘린더로 보내 이벤트 추가를 완료합니다. {@link
1065android.content.Intent#ACTION_INSERT INSERT} 인텐트는 추가 필드를 사용하여
1066캘린더에 있는 이벤트 세부 정보로 양식을 미리 채웁니다.
1067그러면 사용자가 이벤트를 취소하거나 양식을 필요에 따라 편집할 수 있고,
1068이벤트를 본인의 캘린더에 저장할 수도 있습니다.</p>
1069
1070
1071
1072<p>다음은 2012년 1월 19일에 이벤트 일정을 예약하는 코드 조각으로,
1073이는 오전 7:30~오전 8:30까지 실행됩니다. 이 코드 조각에 관해서는 다음 내용을 주의하십시오.</p>
1074
1075<ul>
1076  <li>이것은 {@link android.provider.CalendarContract.Events#CONTENT_URI Events.CONTENT_URI}를 URI로 지정합니다.
1077</li>
1078
1079  <li>이것은 {@link
1080android.provider.CalendarContract#EXTRA_EVENT_BEGIN_TIME
1081CalendarContract.EXTRA_EVENT_BEGIN_TIME} 및 {@link
1082android.provider.CalendarContract#EXTRA_EVENT_END_TIME
1083CalendarContract.EXTRA_EVENT_END_TIME} 추가 필드를 사용하여 이벤트 시간으로 양식을 미리 채웁니다.
1084 이러한 시간에 해당하는 값은 Epoch로부터 UTC 밀리초 단위로 표시해야 합니다.
1085</li>
1086
1087  <li>이것은 {@link android.content.Intent#EXTRA_EMAIL Intent.EXTRA_EMAIL}
1088추가 필드를 사용하여 쉼표로 구분된 초청인 목록을 제공하며, 이는 이메일 주소로 나타납니다.</li>
1089
1090</ul>
1091<pre>
1092Calendar beginTime = Calendar.getInstance();
1093beginTime.set(2012, 0, 19, 7, 30);
1094Calendar endTime = Calendar.getInstance();
1095endTime.set(2012, 0, 19, 8, 30);
1096Intent intent = new Intent(Intent.ACTION_INSERT)
1097        .setData(Events.CONTENT_URI)
1098        .putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, beginTime.getTimeInMillis())
1099        .putExtra(CalendarContract.EXTRA_EVENT_END_TIME, endTime.getTimeInMillis())
1100        .putExtra(Events.TITLE, &quot;Yoga&quot;)
1101        .putExtra(Events.DESCRIPTION, &quot;Group class&quot;)
1102        .putExtra(Events.EVENT_LOCATION, &quot;The gym&quot;)
1103        .putExtra(Events.AVAILABILITY, Events.AVAILABILITY_BUSY)
1104        .putExtra(Intent.EXTRA_EMAIL, &quot;rowan@example.com,trevor@example.com&quot;);
1105startActivity(intent);
1106</pre>
1107
1108<h3 id="intent-edit">인텐트를 사용하여 이벤트 편집</h3>
1109
1110<p><a href="#update-event">이벤트 업데이트</a>에서 설명한 바와 같이 이벤트를 직접 업데이트할 수 있습니다. 그러나 {@link
1111android.content.Intent#ACTION_EDIT EDIT} 인텐트를 사용하면
1112캘린더 애플리케이션에 이벤트 편집을 분배할 권한이 없는 애플리케이션을 허용합니다.
1113사용자가 캘린더에서 이벤트 편집을 마치면 원래 애플리케이션으로 돌아오게 됩니다.
1114</p> <p>다음은 지정된 이벤트에 새 제목을 설정하여 사용자에게 캘린더에서 이벤트를 편집할 수 있도록 해주는 인텐트의 예입니다.
1115</p>
1116
1117
1118<pre>long eventID = 208;
1119Uri uri = ContentUris.withAppendedId(Events.CONTENT_URI, eventID);
1120Intent intent = new Intent(Intent.ACTION_EDIT)
1121    .setData(uri)
1122    .putExtra(Events.TITLE, &quot;My New Title&quot;);
1123startActivity(intent);</pre>
1124
1125<h3 id="intent-view">인텐트를 사용하여 캘린더 데이터 보기</h3>
1126<p>캘린더 제공자는 {@link android.content.Intent#ACTION_VIEW VIEW} 인텐트를 사용하는 두 가지 방식을 제공합니다.</p>
1127<ul>
1128  <li>캘린더를 특정 날짜에 여는 방식</li>
1129  <li>이벤트를 보는 방식</li>
1130
1131</ul>
1132<p>다음은 캘린더를 특정 날짜에 여는 방법을 보여주는 예입니다.</p>
1133<pre>// A date-time specified in milliseconds since the epoch.
1134long startMillis;
1135...
1136Uri.Builder builder = CalendarContract.CONTENT_URI.buildUpon();
1137builder.appendPath(&quot;time&quot;);
1138ContentUris.appendId(builder, startMillis);
1139Intent intent = new Intent(Intent.ACTION_VIEW)
1140    .setData(builder.build());
1141startActivity(intent);</pre>
1142
1143<p>다음은 이벤트를 보기 위해 여는 방법을 나타낸 예입니다.</p>
1144<pre>long eventID = 208;
1145...
1146Uri uri = ContentUris.withAppendedId(Events.CONTENT_URI, eventID);
1147Intent intent = new Intent(Intent.ACTION_VIEW)
1148   .setData(uri);
1149startActivity(intent);
1150</pre>
1151
1152
1153<h2 id="sync-adapter">동기화 어댑터</h2>
1154
1155
1156<p>애플리케이션과 동기화 어댑터가 캘린더 제공자에 액세스하는 방식에는 사소한 차이만이 있을 뿐입니다.
1157</p>
1158
1159<ul>
1160  <li>동기화 어댑터는 {@link android.provider.CalendarContract#CALLER_IS_SYNCADAPTER}를 <code>true</code>로 설정하여 이것이 동기화 어댑터라는 것을 나타내야 합니다.</li>
1161
1162
1163  <li>동기화 어댑터는 URI에서 쿼리 매개변수로 {@link
1164android.provider.CalendarContract.SyncColumns#ACCOUNT_NAME}과 {@link
1165android.provider.CalendarContract.SyncColumns#ACCOUNT_TYPE}을 제공해야 합니다. </li>
1166
1167  <li>동기화 어댑터에는 애플리케이션 또는 위젯에 비해 더 많은 열에 대한 쓰기 액세스 권한이 있습니다.
1168  예를 들어, 애플리케이션은 캘린더의 몇 가지 특성만 수정할 수 있습니다.
1169즉 이름, 표시 이름, 가시성 설정 및 캘린더 동기화 여부 등만 해당됩니다.
1170 이에 비해 동기화 어댑터의 경우 이 열만이 아니라 다른 수많은 열에도 액세스할 수 있습니다.
1171예를 들어 캘린더 색상, 표준 시간대, 액세스 수준 등이 해당됩니다.
1172다만, 동기화 어댑터는 지정된 <code>ACCOUNT_NAME</code> 및
1173<code>ACCOUNT_TYPE</code>에 한정됩니다.</li> </ul>
1174
1175<p>다음은 URI를 반환하여 동기화 어댑터와 사용하도록 할 때 쓸 수 있는 도우미 메서드입니다.</p>
1176<pre> static Uri asSyncAdapter(Uri uri, String account, String accountType) {
1177    return uri.buildUpon()
1178        .appendQueryParameter(android.provider.CalendarContract.CALLER_IS_SYNCADAPTER,&quot;true&quot;)
1179        .appendQueryParameter(Calendars.ACCOUNT_NAME, account)
1180        .appendQueryParameter(Calendars.ACCOUNT_TYPE, accountType).build();
1181 }
1182</pre>
1183<p>동기화 어댑터의 샘플 구현(캘린더에 구체적으로 관련된 것이 아님)은
1184<a href="{@docRoot}resources/samples/SampleSyncAdapter/index.html">SampleSyncAdpater</a>를 참조하십시오.
1185