Kalendář Xamarin.Android
Rozhraní API kalendáře
Nová sada rozhraní API kalendáře zavedená v Androidu 4 podporuje aplikace, které jsou navržené pro čtení nebo zápis dat do poskytovatele kalendáře. Tato rozhraní API podporují širokou škálu možností interakce s daty kalendáře, včetně možnosti čtení a zápisu událostí, účastníků a připomenutí. Pomocí zprostředkovatele kalendáře ve vaší aplikaci se data, která přidáte přes rozhraní API, zobrazí v integrované kalendářové aplikaci, která je součástí Androidu 4.
Přidání oprávnění
Při práci s novými rozhraními API kalendáře ve vaší aplikaci je potřeba nejdřív přidat příslušná oprávnění do manifestu Androidu. Oprávnění, která potřebujete přidat, jsou android.permisson.READ_CALENDAR
a android.permission.WRITE_CALENDAR
v závislosti na tom, jestli čtete nebo zapisujete data kalendáře.
Použití kontraktu kalendáře
Po nastavení oprávnění můžete pomocí třídy pracovat s daty CalendarContract
kalendáře. Tato třída poskytuje datový model, který můžou aplikace používat při interakci s poskytovatelem kalendáře. Umožňuje CalendarContract
aplikacím přeložit Uris na entity kalendáře, jako jsou kalendáře a události. Poskytuje také způsob interakce s různými poli v každé entitě, jako je název a ID kalendáře nebo počáteční a koncové datum události.
Podívejme se na příklad, který používá rozhraní API kalendáře. V tomto příkladu prozkoumáme, jak vytvořit výčet kalendářů a jejich událostí a jak přidat novou událost do kalendáře.
Výpis kalendářů
Nejprve se podíváme, jak vytvořit výčet kalendářů zaregistrovaných v aplikaci kalendáře. Abychom to mohli udělat, můžeme vytvořit instanci CursorLoader
. Zavedení v Androidu 3.0 (API 11) CursorLoader
je upřednostňovaným způsobem, jak používat ContentProvider
. Alespoň budeme muset zadat identifikátor URI obsahu pro kalendáře a sloupce, které chceme vrátit; tato specifikace sloupce se označuje jako projekce.
CursorLoader.LoadInBackground
Volání metody nám umožňuje dotazovat poskytovatele obsahu na data, jako je poskytovatel kalendáře.
LoadInBackground
provede skutečnou operaci načítání a vrátí Cursor
výsledek dotazu.
Pomáhá CalendarContract
nám určit obsah Uri
i projekci. K získání obsahu Uri
pro dotazování kalendářů můžeme jednoduše použít CalendarContract.Calendars.ContentUri
tuto vlastnost:
var calendarsUri = CalendarContract.Calendars.ContentUri;
CalendarContract
Určení požadovaných sloupců kalendáře je stejně jednoduché. Pouze přidáme pole ve CalendarContract.Calendars.InterfaceConsts
třídě do pole. Následující kód například obsahuje ID kalendáře, zobrazovaný název a název účtu:
string[] calendarsProjection = {
CalendarContract.Calendars.InterfaceConsts.Id,
CalendarContract.Calendars.InterfaceConsts.CalendarDisplayName,
CalendarContract.Calendars.InterfaceConsts.AccountName
};
Je Id
důležité zahrnout, pokud k vytvoření vazby dat s uživatelským rozhraním používáte SimpleCursorAdapter
vazbu, jak uvidíme za chvíli. S vloženým identifikátorem URI obsahu a projekcí vytvoříme instanci CursorLoader
metody a zavoláme metodu CursorLoader.LoadInBackground
, která vrátí kurzor s daty kalendáře, jak je znázorněno níže:
var loader = new CursorLoader(this, calendarsUri, calendarsProjection, null, null, null);
var cursor = (ICursor)loader.LoadInBackground();
Uživatelské rozhraní pro tento příklad obsahuje položku ListView
, s každou položkou v seznamu představující jeden kalendář. Následující kód XML ukazuje značky ListView
, které zahrnují:
<?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>
Musíme také zadat uživatelské rozhraní pro každou položku seznamu, kterou umístíme do samostatného souboru XML následujícím způsobem:
<?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 tohoto okamžiku je to jen normální kód Androidu pro vazbu dat z kurzoru na uživatelské rozhraní. Použijeme SimpleCursorAdapter
následující postup:
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;
Ve výše uvedeném kódu adaptér vezme sloupce zadané v sourceColumns
poli a zapíše je do prvků uživatelského rozhraní v targetResources
poli pro každou položku kalendáře v kurzoru. Aktivita použitá zde je podtřídou ListActivity
; zahrnuje ListAdapter
vlastnost, na kterou jsme nastavili adaptér.
Tady je snímek obrazovky zobrazující konečný výsledek s informacemi o kalendáři zobrazenými v části ListView
:
Výpis událostí kalendáře
Teď se podíváme, jak vytvořit výčet událostí pro daný kalendář. Na základě výše uvedeného příkladu zobrazíme seznam událostí, když uživatel vybere jeden z kalendářů. Proto budeme muset zpracovat výběr položky v předchozím kódu:
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);
};
V tomto kódu vytváříme záměr pro otevření aktivity typu EventListActivity
a předání ID kalendáře v záměru. Budeme potřebovat ID, abychom věděli, který kalendář se má dotazovat na události. EventListActivity
V metodě můžeme OnCreate
ID načíst z následujícího obrázkuIntent
:
_calId = Intent.GetIntExtra ("calId", -1);
Teď se dotazujme na události pro toto ID kalendáře. Proces dotazování na události je podobný tomu, jak jsme se dříve dotazovali na seznam kalendářů, pouze tentokrát budeme pracovat s CalendarContract.Events
třídou. Následující kód vytvoří dotaz pro načtení událostí:
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();
V tomto kódu nejprve získáme obsah Uri
událostí z CalendarContract.Events.ContentUri
vlastnosti. Potom určíme sloupce událostí, které chceme načíst v poli eventsProjection.
Nakonec vytvoříme instanci CursorLoader
s touto informací a zavoláme metodu zavaděče LoadInBackground
, která vrátí Cursor
data události.
K zobrazení dat událostí v uživatelském rozhraní můžeme použít kód a kód stejně jako předtím k zobrazení seznamu kalendářů. Znovu použijeme SimpleCursorAdapter
k vytvoření vazby dat k tomuto ListView
kódu, jak je znázorněno v následujícím kódu:
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;
Hlavní rozdíl mezi tímto kódem a kódem, který jsme použili dříve k zobrazení seznamu kalendářů, je použití znaku ViewBinder
, který je nastavený na řádku:
adapter.ViewBinder = new ViewBinder ();
Třída ViewBinder
nám umožňuje dále řídit, jak hodnoty svážeme s zobrazeními. V tomto případě ji použijeme k převodu počátečního času události z milisekund na řetězec kalendářního data, jak je znázorněno v následující implementaci:
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;
}
}
Zobrazí se seznam událostí, jak je znázorněno níže:
Přidání události kalendáře
Viděli jsme, jak číst data kalendáře. Teď se podíváme, jak přidat událost do kalendáře. Aby to fungovalo, nezapomeňte zahrnout android.permission.WRITE_CALENDAR
oprávnění, která jsme zmínili dříve. Pokud chcete přidat událost do kalendáře, provedeme:
- Vytvořte
ContentValues
instanci. - K naplnění
ContentValues
instance použijte klíče zCalendarContract.Events.InterfaceConsts
třídy. - Nastavte časová pásma pro čas zahájení a ukončení události.
ContentResolver
Slouží k vložení dat události do kalendáře.
Následující kód znázorňuje následující kroky:
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);
Všimněte si, že pokud časové pásmo nenastavíme, vyvolá se výjimka typu Java.Lang.IllegalArgumentException
. Vzhledem k tomu, že hodnoty času události musí být vyjádřeny v milisekundách od epochy, vytvoříme metodu GetDateTimeMS
(in EventListActivity
) pro převod specifikace data do formátu 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;
}
Pokud přidáme tlačítko do uživatelského rozhraní seznamu událostí a spustíme výše uvedený kód v obslužné rutině události kliknutí na tlačítko, přidá se událost do kalendáře a aktualizuje se v našem seznamu, jak je znázorněno níže:
Pokud otevřete aplikaci kalendář, uvidíme, že událost je tam napsaná také:
Jak vidíte, Android umožňuje výkonný a snadný přístup k načítání a zachování dat kalendáře, což umožňuje aplikacím bezproblémovou integraci funkcí kalendáře.