Exemplo n.º 1
0
        /// <summary>
        /// Returns the value of the requested column as a DateTime
        /// </summary>
        /// <returns>The DateTime.</returns>
        /// <param name="cursor">Cursor.</param>
        /// <param name="column">Column name.</param>
        /// <param name="allDay">Whether the event is all-day</param>
        public static DateTime GetDateTime(this ICursor cursor, string column, bool allDay)
        {
            var ms = cursor.GetLong(cursor.GetColumnIndex(column));

            var dt = DateConversions.GetDateFromAndroidMS(ms);

            // All day events should not be affected by time zones, so we simply take the
            // UTC time and treat it as local (e.g., Christmas doesn't start on the 24th in California...)
            //
            return(allDay ? DateTime.SpecifyKind(dt.ToUniversalTime(), DateTimeKind.Local) : dt.ToLocalTime());
        }
        /// <summary>
        /// Add new event to a calendar or update an existing event.
        /// If a new event was added, the ExternalID property will be set on the CalendarEvent object,
        /// to support future queries/updates.
        /// </summary>
        /// <param name="calendar">Destination calendar</param>
        /// <param name="calendarEvent">Event to add or update</param>
        /// <exception cref="ArgumentException">Calendar is not specified, does not exist on device, or is read-only</exception>
        /// <exception cref="UnauthorizedAccessException">Calendar access denied</exception>
        /// <exception cref="InvalidOperationException">Editing recurring events is not supported</exception>
        /// <exception cref="Plugin.Calendars.Abstractions.PlatformException">Unexpected platform-specific error</exception>
        public static async Task AddOrUpdateEventAsync(Calendar calendar, CalendarEvent calendarEvent)
        {
            if (string.IsNullOrEmpty(calendar.ExternalID))
            {
                throw new ArgumentException("Missing calendar identifier", nameof(calendar));
            }
            else
            {
                // Verify calendar exists (Android actually allows using a nonexistent calendar ID...)
                //
                var deviceCalendar = await GetCalendarByIdAsync(calendar.ExternalID).ConfigureAwait(false);

                if (deviceCalendar == null)
                {
                    throw new ArgumentException("Specified calendar not found on device");
                }
            }

            // Validate times
            if (calendarEvent.End < calendarEvent.Start)
            {
                throw new ArgumentException("End time may not precede start time", nameof(calendarEvent));
            }

            bool          updateExisting = false;
            long          existingId     = -1;
            CalendarEvent existingEvent  = null;

            await Task.Run(() =>
            {
                if (long.TryParse(calendarEvent.ExternalID, out existingId))
                {
                    if (IsEventRecurring(calendarEvent.ExternalID))
                    {
                        throw new InvalidOperationException("Editing recurring events is not supported");
                    }

                    var calendarId = GetCalendarIdForEventId(calendarEvent.ExternalID);

                    if (calendarId.HasValue && calendarId.Value.ToString() == calendar.ExternalID)
                    {
                        updateExisting = true;
                        existingEvent  = GetEventById(calendarEvent.ExternalID);
                    }
                }

                bool allDay = calendarEvent.AllDay;
                var start   = allDay
                    ? DateTime.SpecifyKind(calendarEvent.Start.Date, DateTimeKind.Utc)
                    : calendarEvent.Start;
                var end = allDay
                    ? DateTime.SpecifyKind(calendarEvent.End.Date, DateTimeKind.Utc)
                    : calendarEvent.End;

                var eventValues = new ContentValues();
                eventValues.Put(CalendarContract.Events.InterfaceConsts.CalendarId,
                                calendar.ExternalID);
                eventValues.Put(CalendarContract.Events.InterfaceConsts.Title,
                                calendarEvent.Title);
                eventValues.Put(CalendarContract.Events.InterfaceConsts.Description,
                                calendarEvent.Description);
                eventValues.Put(CalendarContract.Events.InterfaceConsts.Dtstart,
                                DateConversions.GetDateAsAndroidMS(start));
                eventValues.Put(CalendarContract.Events.InterfaceConsts.Dtend,
                                DateConversions.GetDateAsAndroidMS(end));
                eventValues.Put(CalendarContract.Events.InterfaceConsts.AllDay,
                                allDay ? 1 : 0);
                eventValues.Put(CalendarContract.Events.InterfaceConsts.EventLocation,
                                calendarEvent.Location ?? string.Empty);

                try
                {
                    if (!string.IsNullOrEmpty(calendarEvent.EventColorString) && calendarEvent.EventColor.A > 0)
                    {
                        eventValues.Put(CalendarContract.Events.InterfaceConsts.EventColor,
                                        calendarEvent.EventColor.ToAndroid());
                    }
                }
                catch { }

                // If we're updating an existing event, don't mess with the existing
                // time zone (since we don't support explicitly setting it yet).
                // *Unless* we're toggling the "all day" setting
                // (because that would mean the time zone is UTC rather than local...).
                //
                if (!updateExisting || allDay != existingEvent?.AllDay)
                {
                    eventValues.Put(CalendarContract.Events.InterfaceConsts.EventTimezone,
                                    allDay
                        ? Java.Util.TimeZone.GetTimeZone("UTC")?.ID ?? string.Empty
                        : Java.Util.TimeZone.Default.ID);
                }

                var operations = new List <ContentProviderOperation>();

                var eventOperation = updateExisting
                    ? ContentProviderOperation.NewUpdate(ContentUris.WithAppendedId(_eventsUri, existingId))
                    : ContentProviderOperation.NewInsert(_eventsUri);

                eventOperation = eventOperation.WithValues(eventValues);
                operations.Add(eventOperation.Build());

                operations.AddRange(BuildReminderUpdateOperations(calendarEvent.Reminders, existingEvent));

                try
                {
                    var results = ApplyBatch(operations);

                    if (!updateExisting)
                    {
                        calendarEvent.ExternalID = results[0].Uri.LastPathSegment;
                    }
                }
                catch (Exception ex)
                {
                    ex.ToString();
                }
            }).ConfigureAwait(false);
        }
        /// <summary>
        /// Gets all events for a calendar within the specified time range.
        /// </summary>
        /// <param name="calendar">Calendar containing events</param>
        /// <param name="start">Start of event range</param>
        /// <param name="end">End of event range</param>
        /// <returns>Calendar events</returns>
        /// <exception cref="ArgumentException">Calendar does not exist on device</exception>
        /// <exception cref="UnauthorizedAccessException">Calendar access denied</exception>
        /// <exception cref="Plugin.Calendars.Abstractions.PlatformException">Unexpected platform-specific error</exception>
        public static async Task <IList <CalendarEvent> > GetEventsAsync(Calendar calendar, DateTime start, DateTime end)
        {
            try
            {
                var deviceCalendar = await GetCalendarByIdAsync(calendar.ExternalID).ConfigureAwait(false);

                if (deviceCalendar == null)
                {
                    throw new ArgumentException("Specified calendar not found on device");
                }

                var eventsUriBuilder = CalendarContract.Instances.ContentUri.BuildUpon();

                // Note that this is slightly different from the GetEventById projection
                // due to the Instances API vs. Event API (specifically, IDs and start/end times)
                //
                string[] eventsProjection =
                {
                    CalendarContract.Instances.EventId,
                    CalendarContract.Events.InterfaceConsts.Title,
                    CalendarContract.Events.InterfaceConsts.DisplayColor,
                    CalendarContract.Events.InterfaceConsts.EventColor,
                    CalendarContract.Events.InterfaceConsts.Description,
                    CalendarContract.Instances.Begin,
                    CalendarContract.Instances.End,
                    CalendarContract.Events.InterfaceConsts.AllDay,
                    CalendarContract.Events.InterfaceConsts.EventLocation
                };

                ContentUris.AppendId(eventsUriBuilder, DateConversions.GetDateAsAndroidMS(start));
                ContentUris.AppendId(eventsUriBuilder, DateConversions.GetDateAsAndroidMS(end));
                var eventsUri = eventsUriBuilder.Build();

                return(await Task.Run(() =>
                {
                    try
                    {
                        var cursor = Query(eventsUri, eventsProjection,
                                           string.Format("{0} = {1}", CalendarContract.Events.InterfaceConsts.CalendarId, calendar.ExternalID),
                                           null, CalendarContract.Events.InterfaceConsts.Dtstart + " ASC");

                        var events = IterateCursor(cursor, () =>
                        {
                            try
                            {
                                bool allDay = cursor.GetBoolean(CalendarContract.Events.InterfaceConsts.AllDay);

                                var calendarEvent = new CalendarEvent
                                {
                                    ExternalID = cursor.GetString(CalendarContract.Instances.EventId),
                                    CalendarId = calendar.ExternalID,
                                    Title = cursor.GetString(CalendarContract.Events.InterfaceConsts.Title),
                                    DisplayColorString = string.Format("#{0:x8}", cursor.GetInt(CalendarContract.Events.InterfaceConsts.DisplayColor)),
                                    EventColorString = string.Format("#{0:x8}", cursor.GetInt(CalendarContract.Events.InterfaceConsts.EventColor)),
                                    Description = cursor.GetString(CalendarContract.Events.InterfaceConsts.Description),
                                    Start = cursor.GetDateTime(CalendarContract.Instances.Begin, allDay),
                                    End = cursor.GetDateTime(CalendarContract.Instances.End, allDay),
                                    Location = cursor.GetString(CalendarContract.Events.InterfaceConsts.EventLocation),
                                    //AccessLevel = cursor.GetInt(CalendarContract.Events.InterfaceConsts.AccessLevel),
                                    //tmp = cursor.GetString(CalendarContract.Events.InterfaceConsts.HasExtendedProperties), int mit Count?
                                    //tmp = "1" + cursor.GetString(CalendarContract.Events.InterfaceConsts.IsPrimary),

                                    AllDay = allDay
                                };
                                //calendarEvent.Reminders = GetEventReminders(calendarEvent.ExternalID); => Dauert zu lange!

                                return calendarEvent;
                            }
                            catch (Exception ex)
                            {
                                sys.LogException(ex);
                                int rnd = new Random().Next(8);
                                return new CalendarEvent()
                                {
                                    Start = DateTime.Today.AddHours(10 + rnd),
                                    End = DateTime.Today.AddHours(11 + rnd),
                                    Title = ex.Message
                                };
                            }
                        });

                        return events;
                    }
                    catch (Exception ex)
                    {
                        sys.LogException(ex);
                        return null;
                    }
                }).ConfigureAwait(false));
            }
            catch (Exception ex)
            {
                sys.LogException(ex);
                return(null);
            }
        }