다음을 통해 공유


Xamarin.Android 일정

일정 API

Android 4에 도입된 새로운 일정 API 집합은 일정 공급자에게 데이터를 읽거나 쓰도록 설계된 애플리케이션을 지원합니다. 이러한 API는 이벤트, 참석자 및 미리 알림을 읽고 쓰는 기능을 포함하여 일정 데이터와의 다양한 상호 작용 옵션을 지원합니다. 애플리케이션에서 일정 공급자를 사용하면 API를 통해 추가한 데이터가 Android 4와 함께 제공되는 기본 제공 일정 앱에 표시됩니다.

사용 권한 추가

애플리케이션에서 새 일정 API를 사용할 때 가장 먼저 해야 할 일은 Android 매니페스트에 적절한 권한을 추가하는 것입니다. 추가해야 하는 사용 권한은 android.permisson.READ_CALENDARandroid.permission.WRITE_CALENDAR일정 데이터를 읽고 쓰는지 또는 쓰는지에 따라 달라집니다.

일정 계약 사용

사용 권한을 설정하면 클래스를 사용하여 CalendarContract 일정 데이터와 상호 작용할 수 있습니다. 이 클래스는 애플리케이션이 일정 공급자와 상호 작용할 때 사용할 수 있는 데이터 모델을 제공합니다. 이를 통해 애플리케이션은 CalendarContract 일정 및 이벤트와 같은 일정 엔터티에 대한 URI를 확인할 수 있습니다. 또한 일정의 이름 및 ID, 이벤트의 시작 및 종료 날짜 등 각 엔터티의 다양한 필드와 상호 작용하는 방법을 제공합니다.

일정 API를 사용하는 예제를 살펴보겠습니다. 이 예제에서는 일정 및 해당 이벤트를 열거하는 방법과 달력에 새 이벤트를 추가하는 방법을 살펴봅니다.

일정 나열

먼저 일정 앱에 등록된 일정을 열거하는 방법을 살펴보겠습니다. 이렇게 하려면 .를 CursorLoader인스턴스화할 수 있습니다. Android 3.0(API 11) CursorLoader 에 도입된 것이 선호되는 사용 방법입니다 ContentProvider. 최소한 일정의 콘텐츠 URI와 반환하려는 열을 지정해야 합니다. 이 열 사양을 프로젝션이라고합니다.

메서드를 CursorLoader.LoadInBackground 호출하면 일정 공급자와 같은 데이터에 대한 콘텐츠 공급자를 쿼리할 수 있습니다. LoadInBackground 는 실제 로드 작업을 수행하고 쿼리 결과와 함께 반환 Cursor 합니다.

콘텐츠 CalendarContract 와 프로젝션을 모두 Uri 지정하는 데 도움이 됩니다. 일정을 쿼리하기 위한 콘텐츠를 Uri 가져오기 위해 다음과 같은 속성을 사용하면 CalendarContract.Calendars.ContentUri 됩니다.

var calendarsUri = CalendarContract.Calendars.ContentUri;

CalendarContract 원하는 달력 열을 지정하는 데 사용하는 것은 똑같이 간단합니다. 클래스의 필드를 배열에 CalendarContract.Calendars.InterfaceConsts 추가하기만 하면 됩니다. 예를 들어 다음 코드에는 일정의 ID, 표시 이름 및 계정 이름이 포함됩니다.

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

Id 곧 볼 수 있듯이 데이터를 UI에 바인딩하는 데 사용하는 SimpleCursorAdapter 경우 포함해야 합니다. 콘텐츠 URI 및 프로젝션이 적용되면 아래와 같이 메서드를 CursorLoader 인스턴스화하고 메서드를 호출 CursorLoader.LoadInBackground 하여 달력 데이터를 사용하여 커서를 반환합니다.

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

이 예제의 UI에는 목록의 각 항목이 단일 달력을 나타내는 UI가 포함 ListView됩니다. 다음 XML은 다음을 포함하는 태그를 보여 줍니다 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를 지정해야 합니다.

<?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 코드일 뿐입니다. 다음과 같이 사용합니다 SimpleCursorAdapter .

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 사용자 인터페이스 요소에 씁니다. 여기서 사용되는 활동은 어댑터를 설정하는 속성을 포함하는 ListAdapter 하위 클래스ListActivity입니다.

다음은 다음과 같은 일정 정보가 표시된 최종 결과를 보여 주는 스크린샷입니다 ListView.

에뮬레이터에서 실행되는 CalendarDemo, 두 개의 일정 항목 표시

일정 이벤트 나열

다음으로 지정된 일정에 대한 이벤트를 열거하는 방법을 살펴보겠습니다. 위의 예제를 바탕으로 사용자가 일정 중 하나를 선택할 때 이벤트 목록을 제공합니다. 따라서 이전 코드에서 항목 선택을 처리해야 합니다.

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의 활동을 여는 의도를 만듭니다. 이벤트를 쿼리할 일정을 알 수 있는 ID가 필요합니다. EventListActivity's OnCreate 메서드에서 아래와 같이 ID를 검색할 Intent 수 있습니다.

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

이제 이 일정 ID에 대한 이벤트를 쿼리해 보겠습니다. 이벤트를 쿼리하는 프로세스는 이전에 일정 목록을 쿼리한 방식과 유사하며, 이번에는 클래스로 CalendarContract.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 가져옵니다. 그런 다음 eventsProjection 배열에서 검색하려는 이벤트 열을 지정합니다. 마지막으로 이 정보를 사용하여 CursorLoader 인스턴스화하고 로더의 LoadInBackground 메서드를 호출하여 이벤트 데이터와 함께 반환 Cursor 합니다.

이벤트 데이터를 UI에 표시하기 위해 이전과 마찬가지로 태그와 코드를 사용하여 일정 목록을 표시할 수 있습니다. 다시, 다음 코드와 같이 데이터를 바인딩하는 ListView 데 사용합니다SimpleCursorAdapter.

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사용하는 것입니다.

adapter.ViewBinder = new ViewBinder ();

클래스 ViewBinder 를 사용하면 뷰에 값을 바인딩하는 방법을 추가로 제어할 수 있습니다. 이 경우 다음 구현과 같이 이벤트 시작 시간을 밀리초에서 날짜 문자열로 변환하는 데 사용합니다.

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

아래와 같이 이벤트 목록이 표시됩니다.

세 개의 일정 이벤트를 표시하는 예제 앱의 스크린샷

일정 이벤트 추가

일정 데이터를 읽는 방법을 살펴보았습니다. 이제 일정에 이벤트를 추가하는 방법을 살펴보겠습니다. 이렇게 하려면 앞에서 멘션 권한을 포함 android.permission.WRITE_CALENDAR 해야 합니다. 일정에 이벤트를 추가하려면 다음을 수행합니다.

  1. ContentValues 인스턴스를 만듭니다.
  2. 클래스의 CalendarContract.Events.InterfaceConsts 키를 사용하여 인스턴스를 ContentValues 채웁다.
  3. 이벤트 시작 및 종료 시간에 대한 표준 시간대를 설정합니다.
  4. 이벤트 ContentResolver 데이터를 일정에 삽입하는 데 사용합니다.

아래 코드는 다음 단계를 보여 줍니다.

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됩니다. 이벤트 시간 값은 epoch 이후 밀리초 단위로 표현되어야 하므로 날짜 사양을 밀리초 형식으로 변환하는 메서드(inEventListActivity)를 만듭니 GetDateTimeMS 다.

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에 단추를 추가하고 단추의 클릭 이벤트 처리기에서 위의 코드를 실행하면 이벤트가 일정에 추가되고 아래와 같이 목록에서 업데이트됩니다.

일정 이벤트와 샘플 이벤트 추가 단추가 있는 예제 앱의 스크린샷

일정 앱을 열면 이벤트도 기록됩니다.

선택한 일정 이벤트를 표시하는 일정 앱의 스크린샷

보듯이 Android를 사용하면 강력하고 쉽게 일정 데이터를 검색하고 유지할 수 있으므로 애플리케이션이 일정 기능을 원활하게 통합할 수 있습니다.