Xamarin Android 일정Xamarin.Android Calendar

일정 APICalendar API

Android 4에서 도입 된 새로운 일정 Api 집합은 일정 공급자의 데이터를 읽거나 쓰기 위해 디자인 된 응용 프로그램을 지원 합니다.A new set of calendar APIs introduced in Android 4 supports applications that are designed to read or write data to the calendar provider. 이러한 Api는 이벤트, 참석자 및 미리 알림을 읽고 쓰는 기능을 포함 하 여 일정 데이터를 통해 다양 한 상호 작용 옵션을 지원 합니다.These APIs support a wealth of interaction options with calendar data, including the ability to read and write events, attendees, and reminders. 응용 프로그램에서 달력 공급자를 사용 하 여 API를 통해 추가 하는 데이터는 Android 4와 함께 제공 되는 기본 제공 일정 앱에 표시 됩니다.By using the calendar provider in your application, data you add through the API will appear in the built-in calendar app that comes with Android 4.

권한 추가Adding Permissions

응용 프로그램에서 새로운 일정 Api를 사용할 때 가장 먼저 해야 할 일은 Android 매니페스트에 적절 한 권한을 추가 하는 것입니다.When working with the new calendar APIs in your application, the first thing you need to do is add the appropriate permissions to the Android manifest. 추가 해야 하는 권한은 달력 데이터를 읽고 있는지 아니면 쓰고 있는지에 따라 android.permisson.READ_CALENDARandroid.permission.WRITE_CALENDAR됩니다.The permissions you need to add are android.permisson.READ_CALENDAR and android.permission.WRITE_CALENDAR, depending on whether you are reading and/or writing calendar data.

달력 계약 사용Using the Calendar Contract

사용 권한을 설정 하면 CalendarContract 클래스를 사용 하 여 달력 데이터와 상호 작용할 수 있습니다.Once you set the permissions, you can interact with calendar data by using the CalendarContract class. 이 클래스는 응용 프로그램이 달력 공급자와 상호 작용할 때 사용할 수 있는 데이터 모델을 제공 합니다.This class provides a data model that applications can use when they interact with the calendar provider. CalendarContract를 사용 하면 응용 프로그램에서 일정 엔터티 (예: 달력 및 이벤트)에 대 한 Uri를 확인할 수 있습니다.The CalendarContract allows applications to resolve the Uris to calendar entities, such as calendars and events. 또한 달력의 이름, ID, 이벤트의 시작 및 종료 날짜와 같은 각 엔터티의 다양 한 필드와 상호 작용 하는 방법을 제공 합니다.It also provides a way to interact with various fields in each entity, such as a calendar's name and ID, or an event's start and end date.

Calendar API를 사용 하는 예를 살펴보겠습니다.Let's look at an example that uses the Calendar API. 이 예제에서는 일정 및 해당 이벤트를 열거 하는 방법 뿐만 아니라 일정에 새 이벤트를 추가 하는 방법을 살펴보겠습니다.In this example, we'll examine how to enumerate calendars and their events, as well as how to add a new event to a calendar.

일정 나열Listing Calendars

먼저 달력 앱에 등록 된 달력을 열거 하는 방법을 살펴보겠습니다.First, let's examine how to enumerate the calendars that have been registered in the calendar app. 이렇게 하려면 CursorLoader를 인스턴스화할 수 있습니다.To do this, we can instantiate a CursorLoader. Android 3.0 (API 11)에 도입 된 CursorLoaderContentProvider를 사용 하는 기본 방법입니다.Introduced in Android 3.0 (API 11), CursorLoader is the preferred way to consume a ContentProvider. 최소한 달력 및 반환 하려는 열에 대 한 콘텐츠 Uri를 지정 해야 합니다. 이 열 사양을 _프로젝션_이라고 합니다.At a minimum, we'll need to specify the content Uri for calendars and the columns we want to return; this column specification is known as a projection.

CursorLoader.LoadInBackground 메서드를 호출 하면 일정 공급자와 같은 데이터에 대 한 콘텐츠 공급자를 쿼리할 수 있습니다.Calling the CursorLoader.LoadInBackground method allows us to query a content provider for data, such as the calendar provider. LoadInBackground 실제 로드 작업을 수행 하 고 쿼리 결과와 함께 Cursor을 반환 합니다.LoadInBackground performs the actual load operation and returns a Cursor with the results of the query.

CalendarContract 콘텐츠 Uri와 프로젝션을 모두 지정 하는 데 도움이 됩니다.The CalendarContract assists us in specifying both the content Uri and the projection. 일정 쿼리를 위한 콘텐츠 Uri를 가져오기 위해 다음과 같이 CalendarContract.Calendars.ContentUri 속성을 사용 하면 됩니다.To get the content Uri for querying calendars, we can simply use the CalendarContract.Calendars.ContentUri property like this:

var calendarsUri = CalendarContract.Calendars.ContentUri;

CalendarContract를 사용 하 여 원하는 달력 열을 똑같이 단순하게 지정 합니다.Using the CalendarContract to specify which calendar columns we want is equally simple. CalendarContract.Calendars.InterfaceConsts 클래스의 필드를 배열에 추가 하기만 하면 됩니다.We just add fields in the CalendarContract.Calendars.InterfaceConsts class to an array. 예를 들어 다음 코드에는 달력의 ID, 표시 이름 및 계정 이름이 포함 됩니다.For example, the following code includes the calendar's ID, display name, and account name:

string[] calendarsProjection = {
    CalendarContract.Calendars.InterfaceConsts.Id,
    CalendarContract.Calendars.InterfaceConsts.CalendarDisplayName,
    CalendarContract.Calendars.InterfaceConsts.AccountName
};

IdSimpleCursorAdapter를 사용 하 여 데이터를 UI에 바인딩하는 경우를 포함 하는 것이 중요 합니다.The Id is important to include if you are using a SimpleCursorAdapter to bind the data to the UI, as we will see shortly. 콘텐츠 Uri 및 프로젝션을 준비 하면 CursorLoader을 인스턴스화하고 CursorLoader.LoadInBackground 메서드를 호출 하 여 아래와 같이 달력 데이터를 포함 하는 커서를 반환 합니다.With the content Uri and projection in place, we instantiate the CursorLoader and call the CursorLoader.LoadInBackground method to return a cursor with the calendar data as shown below:

var loader = new CursorLoader(this, calendarsUri, calendarsProjection, null, null, null);
var cursor = (ICursor)loader.LoadInBackground();

이 예제에 대 한 UI에는 단일 달력을 나타내는 목록의 각 항목이 있는 ListView포함 되어 있습니다.The UI for this example contains a ListView, with each item in the list representing a single calendar. 다음 XML은 ListView를 포함 하는 태그를 보여 줍니다.The following XML shows the markup that includes the ListView:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
  <ListView
    android:id="@android:id/android:list"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content" />
</LinearLayout>

또한 다음과 같이 별도의 XML 파일에 저장 되는 각 목록 항목에 대해 UI를 지정 해야 합니다.Also, we need to specify the UI for each list item, which we place in a separate XML file as follows:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
  <TextView android:id="@+id/calDisplayName"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:textSize="16dip" />
  <TextView android:id="@+id/calAccountName"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:textSize="12dip" />
</LinearLayout>

이 시점부터 커서의 데이터를 UI에 바인딩하는 것은 일반적인 Android 코드 일 뿐입니다.From this point on, it's just normal Android code to bind the data from the cursor to the UI. 다음과 같이 SimpleCursorAdapter를 사용 합니다.We'll use a SimpleCursorAdapter as follows:

string[] sourceColumns = {
    CalendarContract.Calendars.InterfaceConsts.CalendarDisplayName,
    CalendarContract.Calendars.InterfaceConsts.AccountName };

int[] targetResources = {
    Resource.Id.calDisplayName, Resource.Id.calAccountName };      

SimpleCursorAdapter adapter = new SimpleCursorAdapter (this,
    Resource.Layout.CalListItem, cursor, sourceColumns, targetResources);

ListAdapter = adapter;

위의 코드에서 어댑터는 sourceColumns 배열에 지정 된 열을 가져와 커서의 각 일정 항목에 대 한 targetResources 배열의 사용자 인터페이스 요소에 기록 합니다.In the above code, the adapter takes the columns specified in the sourceColumns array and writes them to the user interface elements in the targetResources array for each calendar entry in the cursor. 여기에 사용 되는 활동은 ListActivity의 서브 클래스입니다. 여기에는 어댑터를 설정 하는 ListAdapter 속성이 포함 됩니다.The Activity used here is a subclass of ListActivity; it includes the ListAdapter property to which we set the adapter.

다음은 ListView에 표시 되는 달력 정보가 있는 최종 결과를 보여 주는 스크린샷입니다.Here's a screenshot showing the end result, with the calendar info displayed in the ListView:

에뮬레이터에서 실행 되는CalendarDemo, 두 개의 일정 항목 표시CalendarDemo running in emulator, displaying two calendar entries

일정 이벤트 나열Listing Calendar Events

다음으로, 지정 된 일정에 대 한 이벤트를 열거 하는 방법을 살펴보겠습니다.Next let's look at how to enumerate the events for a given calendar. 위의 예제를 기반으로 사용자가 일정 중 하나를 선택 하면 이벤트 목록이 표시 됩니다.Building upon the example above, we'll present a list of events when the user selects one of the calendars. 따라서 이전 코드에서 항목 선택 항목을 처리 해야 합니다.Therefore, we'll need to handle the item selection in the previous code:

ListView.ItemClick += (sender, e) => {
    int i = (e as ItemEventArgs).Position;

    cursor.MoveToPosition(i);
    int calId =
        cursor.GetInt (cursor.GetColumnIndex (calendarsProjection [0]));

    var showEvents = new Intent(this, typeof(EventListActivity));
    showEvents.PutExtra("calId", calId);
    StartActivity(showEvents);
};

이 코드에서는 달력의 ID를 전달 하 여 EventListActivity형식의 활동을 열기 위한 의도를 만듭니다.In this code, we're creating an Intent to open an Activity of type EventListActivity, passing the calendar's ID in the Intent. 이벤트에 대해 쿼리할 달력을 알 수 있는 ID가 필요 합니다.We will need the ID to know which calendar to query for events. EventListActivityOnCreate 메서드에서 아래와 같이 Intent에서 ID를 검색할 수 있습니다.In the EventListActivity's OnCreate method, we can retrieve the ID from the Intent as shown below:

_calId = Intent.GetIntExtra ("calId", -1);

이제이 일정 ID에 대 한 쿼리 이벤트를 살펴보겠습니다.Now let's query events for this calendar ID. 이벤트를 쿼리 하는 프로세스는 이전에 CalendarContract.Events 클래스와 함께 사용할 수 있도록 이전 달력 목록을 쿼리 하는 방법과 비슷합니다.The process to query for events is similar to the way we queried for a list of calendars earlier, only this time we'll work with the CalendarContract.Events class. 다음 코드는 이벤트를 검색 하는 쿼리를 만듭니다.The following code creates a query to retrieve events:

var eventsUri = CalendarContract.Events.ContentUri;

string[] eventsProjection = {
    CalendarContract.Events.InterfaceConsts.Id,
    CalendarContract.Events.InterfaceConsts.Title,
    CalendarContract.Events.InterfaceConsts.Dtstart
};

var loader = new CursorLoader(this, eventsUri, eventsProjection,
                   String.Format ("calendar_id={0}", _calId), null, "dtstart ASC");
var cursor = (ICursor)loader.LoadInBackground();

이 코드에서는 먼저 CalendarContract.Events.ContentUri 속성에서 이벤트에 대 한 콘텐츠 Uri를 가져옵니다.In this code, we first get the content Uri for events from the CalendarContract.Events.ContentUri property. 그런 다음 eventsProjection 배열에서 검색할 이벤트 열을 지정 합니다.Then we specify the event columns we want to retrieve in the eventsProjection array. 마지막으로,이 정보를 사용 하 여 CursorLoader를 인스턴스화하고 로더의 LoadInBackground 메서드를 호출 하 여 이벤트 데이터가 포함 된 Cursor을 반환 합니다.Finally, we instantiate a CursorLoader with this information and call the loader's LoadInBackground method to return a Cursor with the event data.

UI에 이벤트 데이터를 표시 하기 위해 달력 목록을 표시 하기 전과 같은 방식으로 태그와 코드를 사용할 수 있습니다.To display the event data in the UI, we can use markup and code just like we did before to display the list of calendars. 다음 코드와 같이 SimpleCursorAdapter 사용 하 여 데이터를 ListView에 바인딩합니다.Again, we use SimpleCursorAdapter to bind the data to a ListView as shown in the following code:

string[] sourceColumns = {
    CalendarContract.Events.InterfaceConsts.Title,
    CalendarContract.Events.InterfaceConsts.Dtstart };

int[] targetResources = {
    Resource.Id.eventTitle,
    Resource.Id.eventStartDate };

var adapter = new SimpleCursorAdapter (this, Resource.Layout.EventListItem,
    cursor, sourceColumns, targetResources);

adapter.ViewBinder = new ViewBinder ();       
ListAdapter = adapter;

이 코드와 앞에서 달력 목록을 표시 하기 위해 사용한 코드의 주요 차이점은 줄에 설정 된 ViewBinder의 사용입니다.The main difference between this code and the code that we used earlier to show the calendar list is the use of a ViewBinder, which is set on the line:

adapter.ViewBinder = new ViewBinder ();

ViewBinder 클래스를 사용 하 여 보기에 값을 바인딩하는 방법을 세부적으로 제어할 수 있습니다.The ViewBinder class allows us to further control how we bind values to views. 이 경우 다음 구현에 표시 된 것 처럼이를 사용 하 여 이벤트 시작 시간을 밀리초에서 날짜 문자열로 변환 합니다.In this case, we use it to convert the event start time from milliseconds to a date string, as shown in the following implementation:

class ViewBinder : Java.Lang.Object, SimpleCursorAdapter.IViewBinder
{    
    public bool SetViewValue (View view, Android.Database.ICursor cursor,
        int columnIndex)
    {
        if (columnIndex == 2) {
            long ms = cursor.GetLong (columnIndex);

            DateTime date = new DateTime (1970, 1, 1, 0, 0, 0,
                DateTimeKind.Utc).AddMilliseconds (ms).ToLocalTime ();

            TextView textView = (TextView)view;
            textView.Text = date.ToLongDateString ();

            return true;
        }
        return false;
    }    
}

그러면 다음과 같이 이벤트 목록이 표시 됩니다.This displays a list of events as shown below:

3 개의 일정 이벤트를 표시 하는 예제 앱의스크린샷Screenshot of example app displaying three calendar events

일정 이벤트 추가Adding a Calendar Event

일정 데이터를 읽는 방법을 알아보았습니다.We've seen how to read calendar data. 이제 일정에 이벤트를 추가 하는 방법을 살펴보겠습니다.Now let's see how to add an event to a calendar. 이 작업을 수행 하려면 앞에서 언급 한 android.permission.WRITE_CALENDAR 권한을 포함 해야 합니다.For this to work, be sure to include the android.permission.WRITE_CALENDAR permission we mentioned earlier. 일정에 이벤트를 추가 하려면 다음을 수행 합니다.To add an event to a calendar, we will:

  1. ContentValues 인스턴스를 만듭니다.Create a ContentValues instance.
  2. CalendarContract.Events.InterfaceConsts 클래스의 키를 사용 하 여 ContentValues 인스턴스를 채웁니다.Use keys from the CalendarContract.Events.InterfaceConsts class to populate the ContentValues instance.
  3. 이벤트 시작 시간과 종료 시간에 대 한 표준 시간대를 설정 합니다.Set the time zones for the event start and end times.
  4. ContentResolver를 사용 하 여 일정에 이벤트 데이터를 삽입 합니다.Use a ContentResolver to insert the event data into the calendar.

아래 코드에서는 이러한 단계를 보여 줍니다.The code below illustrates these steps:

ContentValues eventValues = new ContentValues ();

eventValues.Put (CalendarContract.Events.InterfaceConsts.CalendarId,
    _calId);
eventValues.Put (CalendarContract.Events.InterfaceConsts.Title,
    "Test Event from M4A");
eventValues.Put (CalendarContract.Events.InterfaceConsts.Description,
    "This is an event created from Xamarin.Android");
eventValues.Put (CalendarContract.Events.InterfaceConsts.Dtstart,
    GetDateTimeMS (2011, 12, 15, 10, 0));
eventValues.Put (CalendarContract.Events.InterfaceConsts.Dtend,
    GetDateTimeMS (2011, 12, 15, 11, 0));

eventValues.Put(CalendarContract.Events.InterfaceConsts.EventTimezone,
    "UTC");
eventValues.Put(CalendarContract.Events.InterfaceConsts.EventEndTimezone,
    "UTC");

var uri = ContentResolver.Insert (CalendarContract.Events.ContentUri,
    eventValues);

표준 시간대를 설정 하지 않으면 Java.Lang.IllegalArgumentException 형식의 예외가 throw 됩니다.Note that if we do not set the time zone, an exception of type Java.Lang.IllegalArgumentException will be thrown. 이벤트 시간 값은 epoch 이후 밀리초 단위로 표시 되어야 하므로 날짜 사양을 밀리초 형식으로 변환 하는 GetDateTimeMS 메서드 (EventListActivity)를 만듭니다.Because event time values must be expressed in milliseconds since epoch, we create a GetDateTimeMS method (in EventListActivity) to convert our date specifications into millisecond format:

long GetDateTimeMS (int yr, int month, int day, int hr, int min)
{
    Calendar c = Calendar.GetInstance (Java.Util.TimeZone.Default);

    c.Set (Java.Util.CalendarField.DayOfMonth, 15);
    c.Set (Java.Util.CalendarField.HourOfDay, hr);
    c.Set (Java.Util.CalendarField.Minute, min);
    c.Set (Java.Util.CalendarField.Month, Calendar.December);
    c.Set (Java.Util.CalendarField.Year, 2011);

    return c.TimeInMillis;
}

이벤트 목록 UI에 단추를 추가 하 고 단추의 click 이벤트 처리기에서 위의 코드를 실행 하는 경우 이벤트가 달력에 추가 되 고 아래와 같이 목록에서 업데이트 됩니다.If we add a button to the event list UI and run the above code in the button's click event handler, the event is added to the calendar and updated in our list as shown below:

일정 이벤트와 샘플 이벤트 추가 단추가 있는 예제 앱의스크린샷Screenshot of example app with calendar events followed by Add Sample Event button

일정 앱을 여는 경우에도 이벤트가 기록 됩니다.If we open the calendar app, then we will see that the event is written there as well:

선택한 일정 이벤트를 표시 하는 일정 앱의스크린샷Screenshot of calendar app displaying the selected calendar event

여기에서 볼 수 있듯이 Android를 사용 하면 쉽고 간편 하 게 일정 데이터를 검색 및 유지할 수 있으므로 응용 프로그램에서 일정 기능을 원활 하 게 통합할 수 있습니다.As you can see, Android allows powerful and easy access to retrieve and persist calendar data, allowing applications to seamlessly integrate calendar capabilities.