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 ListView
z 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
:
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:
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:
- Utwórz
ContentValues
wystąpienie. - Użyj kluczy z
CalendarContract.Events.InterfaceConsts
klasy, aby wypełnićContentValues
wystąpienie. - Ustaw strefy czasowe dla godzin rozpoczęcia i zakończenia zdarzenia.
- 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:
Jeśli otworzymy aplikację kalendarza, zobaczymy, że zdarzenie jest tam również zapisywane:
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.