Xamarin.Android-Kalender
Kalender-API
Eine neue Gruppe von Kalender-APIs, die in Android 4 eingeführt wurden, unterstützt Anwendungen, die zum Lesen oder Schreiben von Daten in den Kalenderanbieter konzipiert sind. Diese APIs unterstützen eine Vielzahl von Interaktionsoptionen mit Kalenderdaten, einschließlich der Möglichkeit zum Lesen und Schreiben von Ereignissen, Teilnehmern und Erinnerungen. Wenn Sie den Kalenderanbieter in Ihrer Anwendung verwenden, werden daten, die Sie über die API hinzufügen, in der integrierten Kalender-App angezeigt, die im Lieferumfang von Android 4 enthalten ist.
Hinzufügen von Berechtigungen
Beim Arbeiten mit den neuen Kalender-APIs in Ihrer Anwendung müssen Sie zunächst die entsprechenden Berechtigungen zum Android-Manifest hinzufügen. Die Berechtigungen, die Sie hinzufügen müssen, sind android.permisson.READ_CALENDAR
und android.permission.WRITE_CALENDAR
, je nachdem, ob Sie Kalenderdaten lesen und/oder schreiben.
Verwenden des Kalendervertrags
Nachdem Sie die Berechtigungen festgelegt haben, können Sie mithilfe der CalendarContract
Klasse mit Kalenderdaten interagieren. Diese Klasse stellt ein Datenmodell bereit, das Anwendungen verwenden können, wenn sie mit dem Kalenderanbieter interagieren. Die CalendarContract
Anwendungen können die URIs in Kalenderentitäten auflösen, z. B. Kalender und Ereignisse. Außerdem bietet es eine Möglichkeit, mit verschiedenen Feldern in jeder Entität zu interagieren, z. B. den Namen und die ID eines Kalenders oder das Start- und Enddatum eines Ereignisses.
Sehen wir uns ein Beispiel an, das die Kalender-API verwendet. In diesem Beispiel untersuchen wir, wie Kalender und deren Ereignisse aufgezählt werden, und wie sie einem Kalender ein neues Ereignis hinzufügen.
Auflisten von Kalendern
Zunächst untersuchen wir, wie Sie die Kalender aufzählen, die in der Kalender-App registriert wurden. Dazu können wir eine Instanziierung durchführen CursorLoader
. In Android 3.0 (API 11) eingeführt, CursorLoader
ist die bevorzugte Methode zum Nutzen eines ContentProvider
. Mindestens müssen wir den Inhalts-URI für Kalender und die Spalten angeben, die zurückgegeben werden sollen. Diese Spaltenspezifikation wird als Projektion bezeichnet.
Durch Aufrufen der CursorLoader.LoadInBackground
Methode können wir einen Inhaltsanbieter für Daten abfragen, z. B. den Kalenderanbieter.
LoadInBackground
führt den tatsächlichen Ladevorgang aus und gibt eine Cursor
mit den Ergebnissen der Abfrage zurück.
Dies CalendarContract
hilft uns dabei, sowohl den Inhalt Uri
als auch die Projektion anzugeben. Um den Inhalt Uri
für die Abfrage von Kalendern abzurufen, können wir einfach die CalendarContract.Calendars.ContentUri
Eigenschaft wie folgt verwenden:
var calendarsUri = CalendarContract.Calendars.ContentUri;
Die Verwendung der CalendarContract
gewünschten Kalenderspalten ist ebenso einfach. Wir fügen nur Felder in der CalendarContract.Calendars.InterfaceConsts
Klasse zu einem Array hinzu. Der folgende Code enthält beispielsweise die ID des Kalenders, den Anzeigenamen und den Kontonamen:
string[] calendarsProjection = {
CalendarContract.Calendars.InterfaceConsts.Id,
CalendarContract.Calendars.InterfaceConsts.CalendarDisplayName,
CalendarContract.Calendars.InterfaceConsts.AccountName
};
Dies Id
ist wichtig, wenn Sie eine SimpleCursorAdapter
Bindung der Daten an die Benutzeroberfläche verwenden, da wir in Kürze sehen werden. Wenn der Inhalts-URI und die Projektion vorhanden sind, instanziieren CursorLoader
und rufen wir die CursorLoader.LoadInBackground
Methode auf, um einen Cursor mit den Kalenderdaten wie unten dargestellt zurückzugeben:
var loader = new CursorLoader(this, calendarsUri, calendarsProjection, null, null, null);
var cursor = (ICursor)loader.LoadInBackground();
Die Benutzeroberfläche für dieses Beispiel enthält ein ListView
, mit jedem Element in der Liste, das einen einzelnen Kalender darstellt. Der folgende XML-Code zeigt das Markup, das folgendes ListView
enthält:
<?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>
Außerdem müssen wir die Benutzeroberfläche für jedes Listenelement angeben, das in einer separaten XML-Datei wie folgt platziert wird:
<?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>
Ab diesem Zeitpunkt ist es einfach normaler Android-Code, die Daten vom Cursor an die Benutzeroberfläche zu binden. Wir verwenden folgendes 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;
Im obigen Code übernimmt der Adapter die im sourceColumns
Array angegebenen Spalten und schreibt sie in die Benutzeroberflächenelemente im targetResources
Array für jeden Kalendereintrag im Cursor. Die hier verwendete Aktivität ist eine Unterklasse von ListActivity
; sie enthält die ListAdapter
Eigenschaft, auf die wir den Adapter festlegen.
Hier ist ein Screenshot mit dem Endergebnis, in dem die Kalenderinformationen im ListView
Folgenden angezeigt werden:
Auflisten von Kalenderereignissen
Als Nächstes sehen wir uns an, wie sie die Ereignisse für einen bestimmten Kalender aufzählen. Auf dem obigen Beispiel wird eine Liste von Ereignissen angezeigt, wenn der Benutzer einen der Kalender auswählt. Daher müssen wir die Elementauswahl im vorherigen Code behandeln:
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);
};
In diesem Code erstellen wir eine Absicht, um eine Aktivität vom Typ EventListActivity
"Aktivität" zu öffnen, wobei die KALENDER-ID in der Absicht übergeben wird. Wir benötigen die ID, um zu wissen, welcher Kalender nach Ereignissen gesucht werden soll. In der EventListActivity
Methode "s OnCreate
" können wir die ID wie unten gezeigt abrufen Intent
:
_calId = Intent.GetIntExtra ("calId", -1);
Jetzt fragen wir Ereignisse für diese Kalender-ID ab. Der Vorgang zum Abfragen von Ereignissen ähnelt der Art, wie wir zuvor für eine Liste von Kalendern abgefragt haben, nur diesmal arbeiten wir mit der CalendarContract.Events
Klasse. Der folgende Code erstellt eine Abfrage zum Abrufen von Ereignissen:
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();
In diesem Code rufen wir zuerst den Inhalt Uri
für Ereignisse aus der CalendarContract.Events.ContentUri
Eigenschaft ab. Anschließend geben wir die Ereignisspalten an, die wir im eventsProjection-Array abrufen möchten.
Schließlich instanziieren wir eine CursorLoader
mit diesen Informationen und rufen die Methode des Ladeprogramms LoadInBackground
auf, um eine Cursor
mit den Ereignisdaten zurückzugeben.
Um die Ereignisdaten auf der Benutzeroberfläche anzuzeigen, können wir Markup und Code wie zuvor verwenden, um die Liste der Kalender anzuzeigen. Auch hier werden SimpleCursorAdapter
die Daten wie im folgenden Code dargestellt an eine ListView
Bindung gebunden:
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;
Der Standard Unterschied zwischen diesem Code und dem Code, den wir zuvor zum Anzeigen der Kalenderliste verwendet haben, ist die Verwendung einer ViewBinder
, die in der Zeile festgelegt ist:
adapter.ViewBinder = new ViewBinder ();
Die ViewBinder
Klasse ermöglicht es uns, die Bindung von Werten an Ansichten weiter zu steuern. In diesem Fall verwenden wir es, um die Startzeit des Ereignisses von Millisekunden in eine Datumszeichenfolge zu konvertieren, wie in der folgenden Implementierung gezeigt:
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;
}
}
Dadurch wird eine Liste der Ereignisse angezeigt, wie unten dargestellt:
Hinzufügen eines Kalenderereignisses
Wir haben gesehen, wie Kalenderdaten gelesen werden. Sehen wir uns nun an, wie Sie einem Kalender ein Ereignis hinzufügen. Damit dies funktioniert, müssen Sie unbedingt die Berechtigung einschließen, die android.permission.WRITE_CALENDAR
wir zuvor Erwähnung. Um einem Kalender ein Ereignis hinzuzufügen, gehen wir wie folgt vor:
- Erstellen Sie eine
ContentValues
-Instanz. - Verwenden Sie Schlüssel aus der
CalendarContract.Events.InterfaceConsts
Klasse, um dieContentValues
Instanz aufzufüllen. - Legen Sie die Zeitzonen für die Start- und Endzeiten des Ereignisses fest.
- Verwenden Sie eine
ContentResolver
, um die Ereignisdaten in den Kalender einzufügen.
Der folgende Code veranschaulicht die folgenden Schritte:
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);
Beachten Sie, dass eine Ausnahme Java.Lang.IllegalArgumentException
ausgelöst wird, wenn die Zeitzone nicht festgelegt wird. Da Ereigniszeitwerte seit der Epoche in Millisekunden ausgedrückt werden müssen, erstellen wir eine GetDateTimeMS
Methode (in EventListActivity
) zum Konvertieren unserer Datumsspezifikationen in Millisekundenformat:
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;
}
Wenn wir der Benutzeroberfläche der Ereignisliste eine Schaltfläche hinzufügen und den obigen Code im Klickereignishandler der Schaltfläche ausführen, wird das Ereignis dem Kalender hinzugefügt und in unserer Liste aktualisiert, wie unten dargestellt:
Wenn wir die Kalender-App öffnen, sehen wir, dass das Ereignis auch dort geschrieben wird:
Wie Sie sehen können, ermöglicht Android leistungsstarken und einfachen Zugriff auf das Abrufen und Speichern von Kalenderdaten, sodass Anwendungen Kalenderfunktionen nahtlos integrieren können.