Partager via


Calendrier Xamarin.Android

API Calendrier

Un nouvel ensemble d’API de calendrier introduites dans Android 4 prend en charge les applications conçues pour lire ou écrire des données dans le fournisseur de calendrier. Ces API prennent en charge une multitude d’options d’interaction avec les données de calendrier, notamment la possibilité de lire et d’écrire des événements, des participants et des rappels. En utilisant le fournisseur de calendrier dans votre application, les données que vous ajoutez via l’API s’affichent dans l’application de calendrier intégrée fournie avec Android 4.

Ajout d’autorisations

Lorsque vous utilisez les nouvelles API de calendrier dans votre application, la première chose à faire est d’ajouter les autorisations appropriées au manifeste Android. Les autorisations que vous devez ajouter sont android.permisson.READ_CALENDAR et android.permission.WRITE_CALENDAR, selon que vous lisez et/ou écrivez des données de calendrier.

Utilisation du contrat de calendrier

Une fois que vous avez défini les autorisations, vous pouvez interagir avec les données de calendrier à l’aide de la CalendarContract classe. Cette classe fournit un modèle de données que les applications peuvent utiliser lorsqu’elles interagissent avec le fournisseur de calendrier. Les CalendarContract applications permettent de résoudre les URI en entités de calendrier, telles que les calendriers et les événements. Il permet également d’interagir avec différents champs de chaque entité, tels que le nom et l’ID d’un calendrier, ou la date de début et de fin d’un événement.

Examinons un exemple qui utilise l’API Calendar. Dans cet exemple, nous allons examiner comment énumérer les calendriers et leurs événements, ainsi que comment ajouter un nouvel événement à un calendrier.

Liste des calendriers

Tout d’abord, examinons comment énumérer les calendriers inscrits dans l’application de calendrier. Pour ce faire, nous pouvons instancier un CursorLoader. Introduit dans Android 3.0 (API 11), CursorLoader est le moyen préféré de consommer un ContentProvider. Au minimum, nous devons spécifier l’URI de contenu pour les calendriers et les colonnes à retourner ; cette spécification de colonne est appelée projection.

L’appel de la CursorLoader.LoadInBackground méthode nous permet d’interroger un fournisseur de contenu pour les données, telles que le fournisseur de calendrier. LoadInBackground effectue l’opération de chargement réelle et retourne une Cursor valeur avec les résultats de la requête.

Il CalendarContract nous aide à spécifier à la fois le contenu Uri et la projection. Pour obtenir le contenu Uri de l’interrogation des calendriers, nous pouvons simplement utiliser la CalendarContract.Calendars.ContentUri propriété comme suit :

var calendarsUri = CalendarContract.Calendars.ContentUri;

L’utilisation de la CalendarContract méthode pour spécifier les colonnes de calendrier souhaitées est tout aussi simple. Nous ajoutons simplement des champs dans la CalendarContract.Calendars.InterfaceConsts classe à un tableau. Par exemple, le code suivant inclut l’ID, le nom complet et le nom du compte du calendrier :

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

Il Id est important d’inclure si vous utilisez un SimpleCursorAdapter pour lier les données à l’interface utilisateur, comme nous le verrons bientôt. Avec l’URI de contenu et la projection en place, nous instancions la CursorLoader méthode et appelons la CursorLoader.LoadInBackground méthode pour retourner un curseur avec les données de calendrier, comme indiqué ci-dessous :

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

L’interface utilisateur de cet exemple contient un ListViewélément , avec chaque élément de la liste représentant un seul calendrier. Le code XML suivant montre le balisage qui inclut les ListViewéléments suivants :

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

En outre, nous devons spécifier l’interface utilisateur de chaque élément de liste, que nous placeons dans un fichier XML distinct comme suit :

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

À partir de ce stade, il s’agit simplement du code Android normal pour lier les données du curseur à l’interface utilisateur. Nous allons utiliser les SimpleCursorAdapter éléments suivants :

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;

Dans le code ci-dessus, l’adaptateur prend les colonnes spécifiées dans le sourceColumns tableau et les écrit dans les éléments de l’interface utilisateur du targetResources tableau pour chaque entrée de calendrier dans le curseur. L’activité utilisée ici est une sous-classe de ListActivity; elle inclut la ListAdapter propriété sur laquelle nous définissons l’adaptateur.

Voici une capture d’écran montrant le résultat final, avec les informations de calendrier affichées dans les ListViewéléments suivants :

CalendarDemo s’exécutant dans l’émulateur, affichant deux entrées de calendrier

Liste des événements de calendrier

Examinons ensuite comment énumérer les événements d’un calendrier donné. À l’instar de l’exemple ci-dessus, nous présenterons une liste d’événements lorsque l’utilisateur sélectionne l’un des calendriers. Par conséquent, nous devons gérer la sélection d’éléments dans le code précédent :

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

Dans ce code, nous créons une intention pour ouvrir une activité de type EventListActivity, en passant l’ID du calendrier dans l’intention. Nous aurons besoin de l’ID pour savoir quel calendrier interroger pour les événements. Dans la EventListActivityméthode ' OnCreate s, nous pouvons récupérer l’ID à partir de l’exemple Intent ci-dessous :

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

Nous allons maintenant interroger les événements pour cet ID de calendrier. Le processus d’interrogation des événements est similaire à la façon dont nous avons interrogé une liste de calendriers précédemment, seulement cette fois nous allons travailler avec la CalendarContract.Events classe. Le code suivant crée une requête pour récupérer des événements :

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

Dans ce code, nous obtenons d’abord le contenu Uri des événements à partir de la CalendarContract.Events.ContentUri propriété. Ensuite, nous spécifions les colonnes d’événements que nous voulons récupérer dans le tableau eventsProjection. Enfin, nous instancions une CursorLoader information avec ces informations et appelons la méthode du LoadInBackground chargeur pour retourner une Cursor avec les données d’événement.

Pour afficher les données d’événement dans l’interface utilisateur, nous pouvons utiliser le balisage et le code comme nous l’avons fait avant d’afficher la liste des calendriers. Là encore, nous utilisons SimpleCursorAdapter pour lier les données à un ListView comme indiqué dans le code suivant :

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;

La principale différence entre ce code et le code que nous avons utilisé précédemment pour afficher la liste de calendriers est l’utilisation d’un ViewBinder, qui est défini sur la ligne :

adapter.ViewBinder = new ViewBinder ();

La ViewBinder classe nous permet de contrôler davantage la façon dont nous liez des valeurs aux vues. Dans ce cas, nous l’utilisons pour convertir l’heure de début de l’événement de millisecondes en chaîne de date, comme indiqué dans l’implémentation suivante :

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

Cette opération affiche une liste d’événements, comme indiqué ci-dessous :

Capture d’écran de l’exemple d’application affichant trois événements de calendrier

Ajout d’un événement de calendrier

Nous avons vu comment lire les données de calendrier. Voyons maintenant comment ajouter un événement à un calendrier. Pour que cela fonctionne, veillez à inclure l’autorisation android.permission.WRITE_CALENDAR que nous avons mentionnée précédemment. Pour ajouter un événement à un calendrier, nous allons :

  1. Créez une instance ContentValues.
  2. Utilisez des clés de la CalendarContract.Events.InterfaceConsts classe pour remplir l’instance ContentValues .
  3. Définissez les fuseaux horaires des heures de début et de fin de l’événement.
  4. Utilisez un ContentResolver pour insérer les données d’événement dans le calendrier.

Le code ci-dessous illustre les étapes suivantes :

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

Notez que si nous ne définissons pas le fuseau horaire, une exception de type Java.Lang.IllegalArgumentException est levée. Étant donné que les valeurs d’heure d’événement doivent être exprimées en millisecondes depuis l’époque, nous créons une GetDateTimeMS méthode (en EventListActivity) pour convertir nos spécifications de date en format millisecondes :

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

Si nous ajoutons un bouton à l’interface utilisateur de la liste d’événements et exécutez le code ci-dessus dans le gestionnaire d’événements click du bouton, l’événement est ajouté au calendrier et mis à jour dans notre liste, comme indiqué ci-dessous :

Capture d’écran de l’exemple d’application avec des événements de calendrier suivis du bouton Ajouter un exemple d’événement

Si nous ouvrez l’application de calendrier, nous verrons que l’événement est également écrit ici :

Capture d’écran de l’application calendrier affichant l’événement de calendrier sélectionné

Comme vous pouvez le voir, Android permet un accès puissant et facile à récupérer et conserver les données de calendrier, ce qui permet aux applications d’intégrer en toute transparence les fonctionnalités de calendrier.