ㅈㅅㄹ

안드로이드 단말에 탑재된 캘린더와 연동되는 어플을 작성하려면 우선 ContentProvider에 대해 이해할 필요가 있다. 뭐 다들 알고 있겠지만 간단하게 얘기하자면 어플에서 자신의 데이터를 export하는 메커니즘이라고 하겠다. 관련 부분은 책자나 안드로이드 개발자 사이트에서도 다루고 있으니 넘어가고, 구글 캘린더의 provider에 대해서만 살펴보자.

아 물론 그 전에, 캘린더의 ContentProvider는 사실 정식으로 문서화 되어 있는 것이 아니므로 구글에서 하위 호환성을 지켜줘야할 의무가 없다. 이를 기반으로 작성한 어플이 특정 버전, 혹은 특정 단말에서 오동작할 수도 있다는 점을 항상 염두해 두자.

우선 가장 간단하게 캘린더에 일정 하나를 집어 넣는 작업을 해보자. 이 기능을 사용하려면 당연히 AndroidManifest.xml에 다음과 같은 사용권한 요청 구문을 포함하고 있어야 한다.

<uses-permission android:name="android.permission.WRITE_CALENDAR"/>
<uses-permission android:name="android.permission.READ_CALENDAR"/>

캘린더 하나는 계정 하나에 일대일로 매칭되므로 일정을 가져오기 위해선 우선 계정이 하나 등록되어 있어야 한다. (일부 국내 단말의 경우 꼭 필요 하지 않은 경우도 있다) 그리고 그 계정에 대응하는 캘린더를 가져와야 한다. 일단은 기본 (계정의) 캘린더를 가져오는 것부터 하자.

final String CONTENT_URI = "content://com.android.calendar";
Uri uri = Uri.parse(CONTENT_URI + "/calendars");
Cursor c = getContentResolver().query(
             uri, new String[] { "_id" }, 
             "selected=?", new String[] { "1" }, null);
if(c == null || !c.moveToFirst()) {
    // 시스템에 캘린더가 존재하지 않음(계정이 등록되어 있지 않음) 오류 처리 필요
}
final int id = c.getInt(c.getColumnIndex("_id"));

위의 코드를 통해 id 변수에 calendar id 값을 저장할 수 있다. 그리고 해당 캘린더의 이벤트의 질의 및 수정은 이 id 값을 키로 사용하여 이루어진다.

ContentValues cv = new ContentValues();
cv.put("calendar_id", id);
cv.put("title", "birthday");
cv.put("description", "my birthday");
cv.put("dtstart", Date.UTC(77, 2, 26, 00, 00, 00)); // 1977.02.26
cv.put("duration", "P1D");
cv.put("allDay", 1);
cv.put("rrule", "FREQ=YEARLY;WKST=SU");
getContentResolver().insert(Uri.parse(CONTENT_URI + "/events"), cv); 

위의 코드를 실행하면 1977년 2월 26일부터 매년마다 반복되는 일정 하나를 추가할 수 있을 것이다. 각 필드의 의미와 규격에 대해선 차후에 따로 자세히 설명할테지만, 일단 calendar_id는 일종의 foreign key로써 현재 이벤트가 등록될 캘린더(위에서 가져온 기본 캘린더)를 지정하는 것이고, dtstart는 시작 시간, durationRFC2445 형식의 문자열로써 일정의 지속시간을 의미한다. rrule 역시 RFC2445 형식의 문자열이며 위의 경우 연간 일정임을 나타낸다. 

위의 Calendar와 Event의 경우와 마찬가지로 안드로이드 캘린더 ContentProvider는 몇 가지 Entity를 여러 테이블로 나누어 관리하고 있으며 ER Diagram으로 대략적으로 표시한 형태는 다음과 같다.


그리다가 귀찮음의 압박을 못 이겨 대충 그렸지만 -_- 어쨌건 calendar와 event가 1:N의 관계를 가지는 것과 마찬가지로, 나머지 attendee나 reminder 등등도 역시나 event와 1:N 관계로 연결되어 있다. 그 외 몇가지 테이블도 존재하나 크게 쓸 일은 없을 듯 하고 위의 것들만 적절히 사용하면 될 듯 하다. 

캘린더의 ContentProvider에 대한 가장 정확한 정보는 사실 소스코드에 있다. 보다 자세한 내용을 원한다면 타겟 버전의 안드로이드 풀 소스에서 framework/base/core/java/android/provider/Calendar.java를 참조하자.

Part 2에서는 events 테이블의 필드에 대해 보다 자세히 살펴볼까 한다. 물론 위에서 언급만 한 RFC2445 형식 필드에 대해서도 보다 자세히 짚고 넘어갈 예정이다.

언젠가는 연재 합니다.