B4A Library Calendar Library

:)Hi,
Having had a need to be able to create and delete calendar events I produced my first calendar library (most of the code I got from the net).
The functions are;
GetListOfAllCalendars(boolean)
- this will return a 'Map' with the calendar Id and name. With this ID we can then create or delete events in this calendar.

CreateEvent(int CalID, String Title, String Desc, String Location, long StartTime, long EndTime, String RRule, boolean AllDay)
- used to create a calendar event using the calendar ID found above. At the moment the fields allowed are Calendar ID, TITLE, DESCRIPTION, LOCATION, STARTTIME, ENDTIME, Recurring Rule and ALLDAY.

Added with V1.1
CreateEventWithReminder(int CalID, String Title, String Desc, String Location, long StartTime, long EndTime, int ReminderTime, String RRule, boolean AllDay)
- used to create a calendar event using the calendar ID found above. At the moment the fields allowed are Calendar ID, TITLE, DESCRIPTION, LOCATION, STARTTIME, ENDTIME, Reminder Time, Recurring Rule and ALLDAY.

GetListofAllEventsforCalendar(int)
- using the calendar ID we can get a 'List' of all events for that calendar, items returned are the same as in the CreateEvent as well as the Event ID. the data is in the form of a List you just need to iterate thru it.

GetListofEventsforCalendarBetweenDates(int, long, long)
- As above but you can specify start and finish dates/time in milliseconds from epoch.

ListofEventsWithDescKeywordBetweenDates(int, String, long, long)
- similar to above but filter on 'string' in the Description field.

ListofEventsWithTitleKeywordBetweenDates(int, String, long, long)
- this time filter on Title field

DeleteCalendarEntry(int)
- once you have the event ID you can delete it with this routine.

This library works on the "unofficial" google model which works directly on the calendars on the phone its self this then syncs up to your google account online. The advantage is no problems with authorization but it probably will not work with all phones. I do hope to create a similar one using the new API which will work on everything and will not stop working. I have tried it on a HTC Desire 2.2 and an Asus tablet 3.1? and it worked on both.

To use it in your program,
B4X:
Dim Mycal As MyCalendar
Mycal.Initialize
myMap = Mycal.GetListOfAllCalendars(False)
Mycal.CreateEvent(1,"Test title 7","This is a test of the create event","At Work",(DateTime.Now ),(DateTime.Now + 3600000),False)
The code is well commented so should not be a problem.
Hope it is of use to someone, it has lots of expansion capability, update calendar event, add more fields to the create event routine, search on different fields etc.
Edward

Edit; Version 1.1 added,
  1. New module added to create events with reminder
  2. Added a recurring Rule field to the Create Event modules, see RFC 5545 - Internet Calendaring and Scheduling Core Object Specification (iCalendar) for all the many options available, it is then passed as a string e.g. "FREQ=MONTHLY;WKST=SU;BYDAY=2WE"
  3. Calendar Example attached, this demonstrates
    • Locating Calendar ID
    • Getting list of events for the selected calendar for the previous month.
    • Creating an event with a reminder
    • Creating an all day event
    • Creating a recurring event
The list of Calendars is loaded into a listview with the Calendar Name and ID.
A Preference Screen (AHPreferenceActivity) is also created to show how the calendar selection can be achieved thru a settings page on menu press.

Edit; Version 1.2 added.
  1. Updated to include the new Calendar API for Android 4 aka ICS
  2. Example program now shows events in a listview, a long_click gives the option to delete the event.
  3. To use the example program select the radio button for the required action then select the calendar you want this action on. The event list is not dynamic so after adding or deleting an event you will have to select read events for that calendar to update the listview.

Edit; Version 1.3 added see post #39 for details
  • New function 'ListExtendedCalendarEntryDetails(Value)' this returns a Map containing
    * hasAlarm
    * recurRule
    * duration
    * minutes
    * method
    * AttendeeName
    * AttendeeEmail
    * AttendeeStatus
  • Sorted bug where ICS did not get the recurring events.

Edit; Version 1.4 added
The bug that I thought I had fixed in v1.3 was not fixed this sorts it out (I hope)

Edit; Version 1.5 added
Details for recurring event now show the start and end time for the recurring event not the original event.

Edit; Version 1.6 added
Changed library to a process object. (no longer an activity object)

Edit; Version 1.7 added
Bug fixed where event timezone was not entered on pre 4.0 android non "all day" event.

Edit; Version 1.8 added
No change in functionality but now the events are returned sorted based on the date/time of the start of the event.

Edit; Version 1.9 added
The 2 create event methods now return the created event ID as a string

Edit; Version 1.11 added
Attached is an updated version of the library with 2 new functions;
GetEventDetails & UpdateEvent.
At the moment UpdateEvent allows you to change the
1) Title
2) Description
3) Location
4) StartTime
5) EndTime
If you do not want to change any of the first 3 pass "" for the relevant one.
To change the time set the ChangeTime Boolean to 'true' and pass both the start & end times. Both must be passed as the system can update both or neither not just one. If ChangeTime is set to 'false' a value must be still be entered in the StartTime & EndTime fields as the function still expects values even if they are not used. Normally I would not use the Boolean and just pass -1 for the time to indicate that it is not to be used but -1 is a valid time (1 millisecond before the epoch Jan 01 1970).

Fixed a bug where 'GetListOfAllCalendars(False)' only returned your "owned" calendars instead of all calendars.

Edit; Version 1.12 added See this post for some more detail
Added function 'GetExtendedListOfAllCalendars(int)'
This returns a LIST with the following calendar values
  • calID (long)
  • name (string)
  • displayName (string)
  • colourName (string)
  • location (string)
  • timezone (string)
  • accesslevel (string)
  • owner account (string)
The value passed in the function is the Access Level, details of the different values are contained in the info popup in B4A.
The Returned LIST can contain no calendars to many calendars depending on the Access Level used. If there is more then 1 calendar the group of 8 values for the additional calendars is repeated.
 

Attachments

  • CalendarExample v1.2.zip
    9.5 KB · Views: 3,817
  • calendar2 V1.12.zip
    18.7 KB · Views: 2,278
  • calendar2_v1.13.zip
    20.4 KB · Views: 1,264
Last edited:

Eumel

Active Member
Licensed User
Longtime User
Hi Edward,

is there a way to update an event, without deleting one and create a new ?


Best regards

Wolfgang
 

lagore

Active Member
Licensed User
Longtime User
The facility does exist to edit an event I just never included it in the library, let me have a look at what is involved. The only complication may be in keeping pre android 4.0 functionality.
 

lagore

Active Member
Licensed User
Longtime User
Hi Wolfgang,
Attached is an updated version of the library with 2 new functions;
GetEventDetails & UpdateEvent.
At the moment UpdateEvent allows you to change the
1) Title
2) Description
3) Location
4) StartTime
5) EndTime
If you do not want to change any of the first 3 pass "" for the relevant one.
To change the time set the ChangeTime Boolean to 'true' and pass both the start & end times. Both must be passed as the system can update both or neither not just one. If ChangeTime is set to 'false' a value must be still be entered in the StartTime & EndTime fields as the function still expects values even if they are not used. Normally I would not use the Boolean and just pass -1 for the time to indicate that it is not to be used but -1 is a valid time (1 millisecond before the epoch Jan 01 1970).
I also should be able to change its allday status and recurring rule if required.
Let me know what you think.
Once we have it finalized I will place the update on the first post.
 

Attachments

  • calendar2 V1.10.zip
    17.1 KB · Views: 344

Eumel

Active Member
Licensed User
Longtime User
Hi Edward,

this was fast :)
I´ll change my code and try to update the event.

After finish, i reply. Many thanks for that.

Wolfgang
 

hmotiwala

Member
Licensed User
Longtime User
Very useful library, thanks a lot.
It seems the function call GetListOfAllCalendars(False) does not return calendars that are subscribed to but not owned. Am I doing something wrong or missing some other setting?
 

lagore

Active Member
Licensed User
Longtime User
Very useful library, thanks a lot.
It seems the function call GetListOfAllCalendars(False) does not return calendars that are subscribed to but not owned. Am I doing something wrong or missing some other setting?
You were right there was a bug in the ICS version where it did not pick up all of the subscribed calendars. I have uploaded a new version to post #1
 

tipallandgo

Member
Licensed User
Longtime User
Hi, I tried to download v1.11 in the first post but the ZIP file doesn't have an XML file so it doesn't show up in my library list.
 

tipallandgo

Member
Licensed User
Longtime User
Thanks for the quick update! :D I'm just wondering though, what's MyICSCalendar that's commented in the example?
 

lagore

Active Member
Licensed User
Longtime User
Thanks for the quick update! :D I'm just wondering though, what's MyICSCalendar that's commented in the example?
When I created the library initially Android had not created the official calendar API for ICS (4.0 and on), when the API came out I was testing it using a separate library but was able to create a single library for both pre and post ICS just never took out the testing lines.
 

RiverRaid

Active Member
Licensed User
Longtime User
Hi!

Is there also the possiblity to get the calendar color with the "GetListOfAllCalendars" - Function? Thank you very much :)

Best regards, Andi
 

lagore

Active Member
Licensed User
Longtime User
New version uploaded to post #1. This creates a new function 'GetExtendedListOfAllCalendars(int)' which returns some more detail for the calendars (see post #1 for more detail).
The value for the colour in Android 4+ is a signed 3 byte int of the RGB colour (eg. 1484645 = 0x16A765)
For pre Android 4 the value appears to be a signed 4 byte integer of the ARGB value (eg. -14069085 = 0xFF2952A3). These pre Android 4 colours do not appear to be an exact match for the newer 4+ colours (which are correct). The colour pallet for the pre 4 was limited so this may explain the difference. If anybody can shed more light on this it would be great.
Some of the returned calendars are not the normal calendars, these could be ones associated with 'Exchange', Outlook', 'Tasks' etc they will normally have a Name = null.
To display all of the values use;
B4X:
Dim mylist As List
    mylist.Initialize
    Dim cal As MyCalendar
    cal.Initialize
   
    mylist = cal.GetExtendedListOfAllCalendars(-1)
   
    For x = 0 To mylist.Size-1 Step 8
            Log("ID = " & mylist.Get(x + 0))
            Log("Name = " & mylist.Get(x + 1))
            Log("Display Name = " & mylist.Get(x + 2))
            Log("colour = " & mylist.Get(x + 3))
            Log("Location = " & mylist.Get(x + 4))
            Log("Time Zone = " & mylist.Get(x + 5))
            Log("Access Level = " & mylist.Get(x + 6))
            Log("Owner Acc = " & mylist.Get(x + 7))
    Next
 

hmotiwala

Member
Licensed User
Longtime User
Problem of events spanning multiple days:
I am working on an app where I want to be able to show what events are schduled for a particular day. I am having a problem when dealing with events that span multiple days. I don't know how to determine if a particular day falls within the range of any multiple day event. I think one way to do it would be to get all events for a calendar and then iterate through each event and determine if the chosen day falls within it's event time range (using event starttime,endtime). This should work but seems like there must be a better way to determine if there are any events with a time range that spans a particular day or time. Any ideas would be appreciated.
Idea for a possible new function to add to library:
A function with a query returning list of events where starttime < 'user supplied StartTime' AND endtime > 'user supplied End Time' would I think do the job.
May be call it "GetListof EventsforCalendarSpanningTimes(calID as Int, StartTime as long, EndTime as long).
 

NeoTechni

Well-Known Member
Licensed User
Longtime User
How is GetListofEventsforCalendarBetweenDates checking? Cause it's returning 0 events for days I have events for. Is it ignoring events that start on one day and end on the next day? It's also ignoring all-day events

I've made code to get events for all calendars into a single list. But I need multi-day spanning events.

B4X:
Type CalendarEvent(CalID As Int, EventName As String, Description As String, StartTime As Long, EndTime As Long, Loc As String, AllDay As Boolean, EventID As Int)

Sub EnumAllEvents(StartDate As Long, EndDate As Long)As List
    Dim CAL As MyCalendar, Calendars As Map, temp As Int,Events As List ,temp2 As Int
    CAL.Initialize
    Events.Initialize
    Calendars = CAL.GetListOfAllCalendars(False)'key=id, value=name of calendar
    'If StartDate=EndDate Then Log("All events") Else Log("Between: " & DateTime.Date(StartDate) & " - " & DateTime.Time(StartDate) & " and " & DateTime.Date(EndDate) & " - " & DateTime.Time(EndDate))
    For temp = 0 To Calendars.Size-1
        Dim calEvents As List, calID As Int = Calendars.GetKeyAt(temp)
        If StartDate=EndDate Then
            calEvents = CAL.GetListofAllEventsforCalendar(calID)
        Else
            calEvents = CAL.GetListofEventsforCalendarBetweenDates(calID,StartDate,EndDate)
        End If
        'Log("Checking calendar " & calID & " " & Calendars.GetValueAt(temp) & " = " & (calEvents.Size/7) & " events")
        For temp2 = 0 To calEvents.Size-1 Step 7
            Dim Event As  CalendarEvent
            Event.Initialize
            Event.calID = calID
            Event.EventName =    calEvents.Get(temp2)            '(0) Event Name
            Event.Description = calEvents.Get(temp2+1)            '(1) Description
            Event.StartTime  =    calEvents.Get(temp2+2)            '(2) Start Time
            Event.EndTime =    calEvents.Get(temp2+3)            '(3) End Time
            Event.Loc =        calEvents.Get(temp2+4)            '(4) Location
            Event.AllDay =        calEvents.Get(temp2+5) = "1"    '(5) All day indicator, 1= all day, 0= not
            Event.EventID =    calEvents.Get(temp2+6)            '(6) Event_ID
            Events.Add(Event)
            Log(Events.Size & ": " & Event)
        Next
    Next
    Return Events
End Sub
 
Last edited:

gmars

Member
Licensed User
Longtime User
One additional request. Can you add the availability field (Free, Busy, Tentative)?

Thank you
 

lagore

Active Member
Licensed User
Longtime User
Attached is a beta version of the calendar library. It adds 3 new functions

"GetListofEventsforCalendarSpanningTimes(int calID, long StartTime, long FinishTime)"
This will return any events that have a start time <= "StartTime" and an end time >= "FinishTime", in other words the event spans the given times.
This works for android 4.0 and higher not for pre 4.0 I am still working on that (hence beta)

"AddEventAttendee(int eventID, String Name, String Email, String Relationship, String Type, String Status)"
With an event ID attendees can be added to the event, the required values are explained in the info popup when you use the function.

"GetAllTimeZones()"
This just returns an array containing all of the timezone ID names used in java. This may be handy when I do the next update as you will be able to specify the event timezone instead of current timezone being used.

The new update will be released as 2.0 as it will break its previous usage. If you would like any additional functions or fields to be added let me know.

@NeoTechni the function "GetListofEventsforCalendarBetweenDates " gets events that have a start time >= the supplied 'StartTime' and and an end time <= the supplied 'FinishTime' or is NULL. The null is required when the event is a recurring event. If the event time is even 1ms outside of the supplied parameters it will not show. An all day event is based on UTC (by design) so you may be out with your supplied times. To get a handle on the way the times of events work create a couple of test events an hour or two long and an all day one then then search for all events for a day or two on each side of these events then have a look at the events start and end times, these are in ms and compare them to your supplied times.
 

Attachments

  • calendar2 v1.13 beta.zip
    20.4 KB · Views: 342

NeoTechni

Well-Known Member
Licensed User
Longtime User
Ive already fixed it on my side with a workaround, but it should also be fixed on yours cause workarounds are slower

the function "GetListofEventsforCalendarBetweenDates " gets events that have a start time >= the supplied 'StartTime' and and an end time <= the supplied 'FinishTime'

that formula is wrong.
it should be (event.starttime >= starttime AND event.starttime <= endtime) OR (event.endtime >= starttime AND event.endtime <= endtime)
 
Top