Sdílet prostřednictvím


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_CALENDARv 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:

CalendarDemo spuštěný v emulátoru zobrazující dvě položky kalendáře

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 EventListActivitya 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. EventListActivityV 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:

Snímek obrazovky ukázkové aplikace zobrazující tři události kalendář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:

  1. Vytvořte ContentValues instanci.
  2. K naplnění ContentValues instance použijte klíče z CalendarContract.Events.InterfaceConsts třídy.
  3. Nastavte časová pásma pro čas zahájení a ukončení události.
  4. 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:

Snímek obrazovky ukázkové aplikace s událostmi kalendáře a následným tlačítkem Přidat ukázkovou událost

Pokud otevřete aplikaci kalendář, uvidíme, že událost je tam napsaná také:

Snímek obrazovky s aplikací kalendáře zobrazující vybranou událost kalendáře

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.