Udostępnij za pośrednictwem


Kalendarz platformy Xamarin.Android

Interfejs API kalendarza

Nowy zestaw interfejsów API kalendarza wprowadzony w systemie Android 4 obsługuje aplikacje przeznaczone do odczytywania lub zapisywania danych u dostawcy kalendarza. Te interfejsy API obsługują wiele opcji interakcji z danymi kalendarza, w tym możliwość odczytywania i zapisywania zdarzeń, uczestników i przypomnień. Korzystając z dostawcy kalendarza w aplikacji, dane dodawane za pośrednictwem interfejsu API będą wyświetlane w wbudowanej aplikacji kalendarza dostarczanej z systemem Android 4.

Dodawanie uprawnień

Podczas pracy z nowymi interfejsami API kalendarza w aplikacji należy najpierw dodać odpowiednie uprawnienia do manifestu systemu Android. Uprawnienia, które należy dodać, to android.permisson.READ_CALENDAR i android.permission.WRITE_CALENDAR, w zależności od tego, czy odczytujesz i/lub zapisujesz dane kalendarza.

Korzystanie z kontraktu kalendarza

Po ustawieniu uprawnień możesz wchodzić w interakcje z danymi kalendarza przy użyciu CalendarContract klasy . Ta klasa udostępnia model danych, którego aplikacje mogą używać podczas interakcji z dostawcą kalendarza. Aplikacja CalendarContract umożliwia aplikacjom rozpoznawanie jednostki kalendarza, takich jak kalendarze i zdarzenia. Umożliwia również interakcję z różnymi polami w każdej jednostce, takimi jak nazwa i identyfikator kalendarza, lub data rozpoczęcia i zakończenia zdarzenia.

Przyjrzyjmy się przykładowi korzystającego z interfejsu API kalendarza. W tym przykładzie sprawdzimy, jak wyliczać kalendarze i ich wydarzenia, a także jak dodawać nowe wydarzenie do kalendarza.

Wyświetlanie listy kalendarzy

Najpierw sprawdźmy, jak wyliczyć kalendarze zarejestrowane w aplikacji kalendarza. W tym celu możemy utworzyć wystąpienie obiektu CursorLoader. Wprowadzony w systemie Android 3.0 (interfejs API 11) CursorLoader jest preferowanym sposobem korzystania z programu ContentProvider. Co najmniej musimy określić identyfikator URI zawartości dla kalendarzy i kolumn, które chcemy zwrócić; ta specyfikacja kolumny jest znana jako projekcja.

CursorLoader.LoadInBackground Wywołanie metody umożliwia wykonywanie zapytań o dostawcę zawartości dla danych, takich jak dostawca kalendarza. LoadInBackground wykonuje rzeczywistą operację ładowania i zwraca element Cursor z wynikami zapytania.

Pomaga CalendarContract nam określić zarówno zawartość Uri , jak i projekcję. Aby uzyskać zawartość Uri do wykonywania zapytań dotyczących kalendarzy, możemy po prostu użyć właściwości podobnej do następującej CalendarContract.Calendars.ContentUri :

var calendarsUri = CalendarContract.Calendars.ContentUri;

Użyj elementu , CalendarContract aby określić, które kolumny kalendarza chcemy, są równie proste. Wystarczy dodać pola w CalendarContract.Calendars.InterfaceConsts klasie do tablicy. Na przykład następujący kod zawiera identyfikator kalendarza, nazwę wyświetlaną i nazwę konta:

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

Jest Id to ważne, jeśli używasz elementu SimpleCursorAdapter do powiązania danych z interfejsem użytkownika, jak wkrótce zobaczymy. Po utworzeniu identyfikatora URI zawartości i projekcji CursorLoader tworzymy wystąpienie metody i wywołujemy CursorLoader.LoadInBackground metodę , aby zwrócić kursor z danymi kalendarza, jak pokazano poniżej:

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

Interfejs użytkownika dla tego przykładu zawiera element ListViewz każdym elementem na liście reprezentującym pojedynczy kalendarz. Poniższy kod XML przedstawia znaczniki, które obejmują element 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>

Ponadto musimy określić interfejs użytkownika dla każdego elementu listy, który umieszczamy w osobnym pliku XML w następujący sposób:

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

Od tego momentu jest to zwykły kod systemu Android, aby powiązać dane z kursora z interfejsu użytkownika. Użyjemy elementu w SimpleCursorAdapter następujący sposób:

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;

W powyższym kodzie adapter pobiera kolumny określone w sourceColumns tablicy i zapisuje je w elementach interfejsu użytkownika w targetResources tablicy dla każdego wpisu kalendarza w kursorze. Działanie używane w tym miejscu jest podklasą ListActivity; zawiera ListAdapter właściwość, do której ustawiamy adapter.

Oto zrzut ekranu przedstawiający wynik końcowy z informacjami kalendarza wyświetlanymi w pliku ListView:

CalendarDemo uruchomione w emulatorze, wyświetlając dwa wpisy kalendarza

Wyświetlanie listy zdarzeń kalendarza

Następnie przyjrzyjmy się, jak wyliczyć zdarzenia dla danego kalendarza. Korzystając z powyższego przykładu, przedstawimy listę zdarzeń, gdy użytkownik wybierze jeden z kalendarzy. W związku z tym musimy obsłużyć wybór elementu w poprzednim kodzie:

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

W tym kodzie tworzysz intencję, aby otworzyć działanie typu EventListActivity, przekazując identyfikator kalendarza w intencji. Będziemy potrzebować identyfikatora, aby wiedzieć, który kalendarz będzie wysyłać zapytania dotyczące zdarzeń. W metodzie EventListActivity"s OnCreate " możemy pobrać identyfikator z obiektu , Intent jak pokazano poniżej:

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

Teraz odpytujmy zdarzenia dla tego identyfikatora kalendarza. Proces wykonywania zapytań o zdarzenia jest podobny do sposobu, w jaki wykonaliśmy zapytanie o listę kalendarzy wcześniej, tym razem będziemy pracować z klasą CalendarContract.Events . Poniższy kod tworzy zapytanie w celu pobrania zdarzeń:

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();

W tym kodzie najpierw uzyskujemy zawartość Uri zdarzeń z CalendarContract.Events.ContentUri właściwości . Następnie określamy kolumny zdarzeń, które chcemy pobrać w tablicy eventsProjection. Na koniec utworzymy wystąpienie CursorLoader elementu za pomocą tych informacji i wywołamy metodę modułu ładującego LoadInBackground , aby zwrócić Cursor element z danymi zdarzenia.

Aby wyświetlić dane zdarzenia w interfejsie użytkownika, możemy użyć znaczników i kodu tak jak wcześniej, aby wyświetlić listę kalendarzy. Ponownie użyjemy polecenia SimpleCursorAdapter , aby powiązać dane z elementem ListView , jak pokazano w poniższym kodzie:

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;

Główną różnicą między tym kodem a kodem użytym wcześniej do pokazania listy kalendarzy jest użycie elementu ViewBinder, który jest ustawiony w wierszu:

adapter.ViewBinder = new ViewBinder ();

Klasa ViewBinder umożliwia nam dalszą kontrolę nad tym, jak wiążemy wartości z widokami. W tym przypadku używamy go do konwertowania czasu rozpoczęcia zdarzenia z milisekund na ciąg daty, jak pokazano w następującej implementacji:

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

Spowoduje to wyświetlenie listy zdarzeń, jak pokazano poniżej:

Zrzut ekranu przedstawiający przykładowej aplikacji z trzema zdarzeniami kalendarza

Dodawanie zdarzenia kalendarza

Widzieliśmy, jak odczytywać dane kalendarza. Teraz zobaczmy, jak dodać zdarzenie do kalendarza. Aby to zadziałało, pamiętaj o dołączeniu wspomnianego android.permission.WRITE_CALENDAR wcześniej uprawnienia. Aby dodać zdarzenie do kalendarza, będziemy:

  1. Utwórz ContentValues wystąpienie.
  2. Użyj kluczy z CalendarContract.Events.InterfaceConsts klasy, aby wypełnić ContentValues wystąpienie.
  3. Ustaw strefy czasowe dla godzin rozpoczęcia i zakończenia zdarzenia.
  4. Użyj kontrolki , ContentResolver aby wstawić dane zdarzenia do kalendarza.

Poniższy kod ilustruje następujące kroki:

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

Pamiętaj, że jeśli nie ustawimy strefy czasowej, zostanie zgłoszony wyjątek typu Java.Lang.IllegalArgumentException . Ponieważ wartości czasu zdarzenia muszą być wyrażone w milisekundach od epoki, tworzymy metodę GetDateTimeMS (w EventListActivity), aby przekonwertować nasze specyfikacje dat na format milisekund:

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

Jeśli dodamy przycisk do interfejsu użytkownika listy zdarzeń i uruchomimy powyższy kod w procedurze obsługi zdarzeń kliknięcia przycisku, zdarzenie zostanie dodane do kalendarza i zaktualizowane na naszej liście, jak pokazano poniżej:

Zrzut ekranu przykładowej aplikacji ze zdarzeniami kalendarza, po którym następuje przycisk Dodaj przykładowe zdarzenie

Jeśli otworzymy aplikację kalendarza, zobaczymy, że zdarzenie jest tam również zapisywane:

Zrzut ekranu przedstawiający aplikację kalendarza wyświetlającą wybrane zdarzenie kalendarza

Jak widać, system Android umożliwia zaawansowany i łatwy dostęp do pobierania i utrwalania danych kalendarza, dzięki czemu aplikacje mogą bezproblemowo integrować funkcje kalendarza.