Search code examples
c#xamarincalendarxamarin.forms

Xamarin: Check if an event exists before adding it to the calendar in android


I am using xamarin forms to add an event to the native calendar of android platform. I have made dependency service to add an event across platforms. I am able to add an event, but before adding any event, I want to apply a check to restrict if any event of same unique identifier exists then it should not allow to add that event.

I tried this but didn't worked, as I could not found any Cursor class in xamarin on android platform.


Solution

  • On Android, you need to do the following to fetch data from calendar using the new APIs.

    You need the permission android.permisson.READ_CALENDAR

    Interact with calendar data by using the CalendarContract class. This class provides a data model that applications can use when they interact with the calendar provider.

    To enumerate the calendars that have been registered in the calendar app. To do this, we can call the ManagedQuery method. At a minimum, we’ll need to specify the content Uri for calendars and the columns we want to return; this column specification is known as a projection. Calling ManagedQuery allows us to query a content provider for data, such as the calendar provider, and returns a Cursor with the results of the query.

    var calendarsUri = CalendarContract.Calendars.ContentUri;
    

    Specifying the projection :

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

    You can pass in more parameters instead of null. Look at other parameters available here.

    var cursor = ManagedQuery (calendarsUri, calendarsProjection, null, null, null);
    

    Managed query is deprecated, and it's better you use ContentResolver.

    var cursor = context.ContentResolver.Query(calendarsUri, calendarsProjection, null, null, null);
    

    with date filter :

    var selection = "((dtstart <= ?) AND (dtend >= ?))";
    var selectionArgs = new string[] { startString, endString };
    Forms.Context.ApplicationContext.ContentResolver.Query(calendarsUri, calendarsProjection, selection, selectionArgs, null);
    

    or

    var ctx = Forms.Context;
    var cursor = ctx.ApplicationContext.ContentResolver.Query(calendarsUri, calendarsProjection, null, null, null);
    

    The parameters to Query are :

    • cr - The ContentResolver to use for the query
    • projection - The columns to return
    • begin -The start of the time range to query in UTC millis since epoch
    • end - The end of the time range to query in UTC millis since epoch

    The whole tutorial and step by step explanation is provided here. Read about ContentResolver here.

    For iOS, you have to use EventKit.

    To retrieve an event by it’s ID, use the EventFromIdentifier method on the EventStore and pass it the EventIdentifier that was pulled from the event:

    var mySavedEvent = App.Current.EventStore.EventFromIdentifier (newEvent.EventIdentifier);
    

    To search for calendar events, you must create an NSPredicate object via the PredicateForEvents method on the EventStore. An NSPredicate is a query data object that iOS uses to locate matches:

    NSPredicate query = App.Current.EventStore.PredicateForEvents (startDate, endDate, null);
    

    The third parameter is calendars to query, to use all calendars, pass null.

    Once the NSPredicate is created, use the EventsMatching method on the EventStore, execute the query :

    EKCalendarItem[] events = App.Current.EventStore.EventsMatching (query);
    

    The full tutorials is available here and for sample look here.