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,853
  • calendar2 V1.12.zip
    18.7 KB · Views: 2,319
  • calendar2_v1.13.zip
    20.4 KB · Views: 1,307
Last edited:

JohnC

Expert
Licensed User
Longtime User
Hi Lagore,

Were you able to reproduce the crashing I am having when trying to "edit" a new calendar "alarm" entry like I posted a few messages ago in this thread?

It seems that the crash is occuring when the samsung built in app is trying to access the "TimeZone" data of the ALARM appointment that was created using your library:

Caused by: java.lang.NullPointerException
at com.android.calendar.EditEvent.setVariableTimezone (EditEvent.java:4344)
at com.android.calendar.EditEvent.setTimezone(EditEve nt.java:4357)


If I create an "Alarm" entry using your library, does your library set the timezone param of the calendar entry?
 

lagore

Active Member
Licensed User
Longtime User
Hi JohnCody,
I think you have found the problem (i hope), I left out an entry on the non ICS version for an entry that is not an 'all day' event. so no data was stored for timezone in this case. If you create an all day event does this crash your program as the time zone "UTC" is in the field (this is required for an all day event. I will update the library and post it later.
 

lagore

Active Member
Licensed User
Longtime User
Version 1.7 added to the first post. This hopefully fixes a bug where the event timezone was not entered when a non 'all day' event was created on pre 4.0 android devices.
 

JohnC

Expert
Licensed User
Longtime User
Version 1.7 added to the first post. This hopefully fixes a bug where the event timezone was not entered when a non 'all day' event was created on pre 4.0 android devices.

Just tested it with 1.7 and I can now edit alarm entries without a crash!

Thank you.
 

Bardill

Member
Licensed User
Longtime User
CreateEvent

Hi
I will make a CreateEvent
when i make this

DateTime.DateFormat="dd.MM.yyyy"
DateTime.TimeFormat="HH:mm"
DTSTART=DateTime.DateParse("24.10.2012")
DTSTART = DTSTART + DateTime.TimeParse("15:00")
RRULE="FREQ=WEEKLY;COUNT=1;INTERVAL=2;BYDAY=WE"
cal.CreateEvent (1 ,"Titel" ,"description","Location", DTSTART ,DTSTART + 900000 ,RRULE,False)

i have an appoinment at 11 july 1919 5:31-5:46


what make i wrong??
 

lagore

Active Member
Licensed User
Longtime User
The problem is with your code,
B4X:
DateTime.TimeParse("15:00")
returns the number of ticks from the epoch (1 Jan 1970) to 1500 today (or to whatever day it is executed), not from midnight. You have a couple of options;
B4X:
DTSTART = DTSTART + DateTime.TimeParse("15:00") - DateTime.TimeParse("00:00")
or
B4X:
DTSTART = DTSTART + DateTime.TicksPerHour * 15 + DateTime.TicksPerMinute * 0
There is a potential problem with the first option, if the time rolls past midnight after the first TimeParse but before the second TimeParse then it will give an incorrect answer (very remote but still possible). With any of these types of number problems it is a good idea to step thru the code in debug you would have noticed DTSTART go from 1351033200000 to 2702030400000 instead of 1351087200000.
 

Bardill

Member
Licensed User
Longtime User
Oh thanks for the answer
An other question how i musst handle the TimeZone and The ALARM?

or is there a way to edit and add the ALARM
 
Last edited:

lagore

Active Member
Licensed User
Longtime User
The way I handle the TimeZone for all day events which must be set to a midnight boundary UTC is with the following code.
B4X:
Dim calstart, offset, calfinish As Long
   offset = DateTime.GetTimeZoneOffsetAt(Start_Date) * DateTime.TicksPerHour
   calstart = Start_Date + offset
using this code will compensate for the difference in your local time and UTC and set the time to the midnight boundary.
At the moment there is no way to edit an event (might have a look at that some) I normally delete the event then recreate it with the new info.
 

Paulsche

Well-Known Member
Licensed User
Longtime User
APP no starts in Android 2.2 ?

Hello, this library since I use in my app, starts the app in some users not more. In the emulator with platform 2.2 API 8 launches the app also not more, only if i Platform Version 4.0.3 API 15 clearances, then does the app easily. It may be that the library with Android 2.2 is not compatible?
 

lagore

Active Member
Licensed User
Longtime User
Hi unfortunately the calendar API only exists for 4.0 and on, so there is no guarantee that it will work on any version < 4.0 although to date I have not found a phone that it has not worked on. If you have an example of your app that you could upload I will certainly have a look at it and test it on my 2.2 HTC desire.
 

lagore

Active Member
Licensed User
Longtime User
I downloaded the lite version and it does indeed crash on my 2.2 android, what I need is a bit of the code that is causing the crash if that is possible?
 

lagore

Active Member
Licensed User
Longtime User
Having had a look at the unfiltered logs it appears to be
java.lang.NoClassDefFoundError: android.os.StrictMode$ThreadPolicy$Builder
is causing this problem, apparently StrictMode$ThreadPolicy does not exist for android <2.3 which seems to bear out your problem. I am not sure how the calendar library is causing this as I have never seen this type of crash before. Have you recently used any other libraries in your app particularly HTTP.
 

Paulsche

Well-Known Member
Licensed User
Longtime User
i send you the projekt as zipfile.

the last version without the calendar2 Library i send to the user
run without problems.

i have no other library installed between the two versions.
 

Paulsche

Well-Known Member
Licensed User
Longtime User
In Emulator with Android 2.3.3 the APP run,
the problem is only by Android 2.2 .
 

lagore

Active Member
Licensed User
Longtime User
I think it might be something to do with running on different threads and StrictMode as strictmode does not exist on android 2.2. I have not been able to compile your app so cannot debug as I get the following failure during the compile,
Copying libraries resources Error
Cannot find central directory
but looking at the unfiltered logs when running the lite version I get
Could not find class 'android.os.StrictMode$ThreadPolicy$Builder', referenced from method com.giuseppe.salvi.icos.library.weather.ICOSWorldForecastWrapper.Initialize


VFY: unable to resolve new-instance 150 (Landroid/os/StrictMode$ThreadPolicy$Builder;) in Lcom/giuseppe/salvi/icos/library/weather/ICOSWorldForecastWrapper;
VFY: replacing opcode 0x22 at 0x0000
VFY: dead code 0x0002-0014 in Lcom/giuseppe/salvi/icos/library/weather/ICOSWorldForecastWrapper;.Initialize (Lanywheresoftware/b4a/BA;Ljava/lang/String;)V
Could not find method android.hardware.Camera.open, referenced from method xvs.ACL.ACL.CameraBack2


VFY: unable to resolve static method 707: Landroid/hardware/Camera;.open (I)Landroid/hardware/Camera;
VFY: replacing opcode 0x71 at 0x0007
VFY: dead code 0x000a-000f in Lxvs/ACL/ACL;.CameraBack2 ()V
Could not find method android.hardware.Camera.open, referenced from method xvs.ACL.ACL.CameraFront2
VFY: unable to resolve static method 707: Landroid/hardware/Camera;.open (I)Landroid/hardware/Camera;
VFY: replacing opcode 0x71 at 0x0007
VFY: dead code 0x000a-000f in Lxvs/ACL/ACL;.CameraFront2 ()V
Could not find method android.hardware.Camera$Parameters.getSupportedPreviewFpsRange, referenced from method xvs.ACL.ACL.getSupportedPreviewFpsRange
VFY: unable to resolve virtual method 675: Landroid/hardware/Camera$Parameters;.getSupportedPreviewFpsRange ()Ljava/util/List;
VFY: replacing opcode 0x6e at 0x0006
VFY: dead code 0x0009-000a in Lxvs/ACL/ACL;.getSupportedPreviewFpsRange ()Ljava/util/List;
Could not find class 'android.hardware.Camera$CameraInfo', referenced from method xvs.ACL.ACL.openFrontFacingCameraGingerbread
VFY: unable to resolve new-instance 115 (Landroid/hardware/Camera$CameraInfo;) in Lxvs/ACL/ACL;
VFY: replacing opcode 0x22 at 0x0002
VFY: dead code 0x0004-0037 in Lxvs/ACL/ACL;.openFrontFacingCameraGingerbread ()V
Could not find method android.hardware.Camera$Parameters.setPreviewFpsRange, referenced from method xvs.ACL.ACL.setPreviewFpsRange
VFY: unable to resolve virtual method 695: Landroid/hardware/Camera$Parameters;.setPreviewFpsRange (II)V
VFY: replacing opcode 0x6e at 0x0006
VFY: dead code 0x0009-000e in Lxvs/ACL/ACL;.setPreviewFpsRange (II)V
VFY: unable to resolve static field 954 (CONTENT_URI) in Landroid/provider/CalendarContract$Events;
VFY: replacing opcode 0x62 at 0x02c9
VFY: dead code 0x02cb-02ef in Ledsmith/calendar/Calendar;.CreateEvent (ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;JJLjava/lang/String;Z)V


VFY: unable to resolve static field 954 (CONTENT_URI) in Landroid/provider/CalendarContract$Events;
VFY: replacing opcode 0x62 at 0x0343
VFY: dead code 0x0345-03b8 in Ledsmith/calendar/Calendar;.CreateEventWithReminder (ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;JJJLjava/lang/String;Z)V
VFY: unable to resolve static field 954 (CONTENT_URI) in Landroid/provider/CalendarContract$Events;
VFY: replacing opcode 0x62 at 0x0075
VFY: dead code 0x0077-00af in Ledsmith/calendar/Calendar;.DeleteCalendarEntry (I)I
VFY: unable to resolve static field 953 (CONTENT_URI) in Landroid/provider/CalendarContract$Calendars;
VFY: replacing opcode 0x62 at 0x00c6
VFY: dead code 0x00c8-018e in Ledsmith/calendar/Calendar;.GetListOfAllCalendars (Z)Lanywheresoftware/b4a/objects/collections/Map;
VFY: unable to resolve static field 954 (CONTENT_URI) in Landroid/provider/CalendarContract$Events;
VFY: replacing opcode 0x62 at 0x01d4
VFY: dead code 0x01d6-033f in Ledsmith/calendar/Calendar;.GetListofAllEventsforCalendar (I)Lanywheresoftware/b4a/objects/collections/List;
VFY: unable to resolve static field 955 (CONTENT_URI) in Landroid/provider/CalendarContract$Instances;
VFY: replacing opcode 0x62 at 0x01ed
VFY: dead code 0x01ef-0370 in Ledsmith/calendar/Calendar;.GetListofEventsforCalendarBetweenDates (IJJ)Lanywheresoftware/b4a/objects/collections/List;
VFY: unable to resolve static field 954 (CONTENT_URI) in Landroid/provider/CalendarContract$Events;
VFY: replacing opcode 0x62 at 0x03bc
VFY: dead code 0x03be-06f0 in Ledsmith/calendar/Calendar;.ListExtendedCalendarEntryDetails (I)Lanywheresoftware/b4a/objects/collections/Map;
VFY: unable to resolve static field 955 (CONTENT_URI) in Landroid/provider/CalendarContract$Instances;
VFY: replacing opcode 0x62 at 0x021d
VFY: dead code 0x021f-0394 in Ledsmith/calendar/Calendar;.ListofEventsWithDescKeywordBetweenDates (ILjava/lang/String;JJ)Lanywheresoftware/b4a/objects/collections/List;
VFY: unable to resolve static field 955 (CONTENT_URI) in Landroid/provider/CalendarContract$Instances;
VFY: replacing opcode 0x62 at 0x021e
VFY: dead code 0x0220-0395 in Ledsmith/calendar/Calendar;.ListofEventsWithTitleKeywordBetweenDates (ILjava/lang/String;JJ)Lanywheresoftware/b4a/objects/collections/List;
** Activity (main) Create, isFirst = true **


Shutting down VM
threadid=1: thread exiting with uncaught exception (group=0x400259f8)
main_activity_create (java line: 1031)
java.lang.NoClassDefFoundError: android.os.StrictMode$ThreadPolicy$Builder
at com.giuseppe.salvi.icos.library.weather.ICOSWorldForecastWrapper.Initialize(ICOSWorldForecastWrapper.java:71)
at HBVerbrauchszaehler.lite.main._activity_create(main.java:1031)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:521)
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:165)
at HBVerbrauchszaehler.lite.main.afterFirstLayout(main.java:84)
at HBVerbrauchszaehler.lite.main.access$100(main.java:16)
at HBVerbrauchszaehler.lite.main$WaitForLayout.run(main.java:72)
at android.os.Handler.handleCallback(Handler.java:587)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:144)
at android.app.ActivityThread.main(ActivityThread.java:4937)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:521)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:858)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
at dalvik.system.NativeStart.main(Native Method)
FATAL EXCEPTION: main
java.lang.NoClassDefFoundError: android.os.StrictMode$ThreadPolicy$Builder
at com.giuseppe.salvi.icos.library.weather.ICOSWorldForecastWrapper.Initialize(ICOSWorldForecastWrapper.java:71)
at HBVerbrauchszaehler.lite.main._activity_create(main.java:1031)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:521)
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:165)
at HBVerbrauchszaehler.lite.main.afterFirstLayout(main.java:84)
at HBVerbrauchszaehler.lite.main.access$100(main.java:16)
at HBVerbrauchszaehler.lite.main$WaitForLayout.run(main.java:72)
at android.os.Handler.handleCallback(Handler.java:587)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:144)
at android.app.ActivityThread.main(ActivityThread.java:4937)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:521)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:858)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
at dalvik.system.NativeStart.main(Native Method)
Force finishing activity HBVerbrauchszaehler.lite/.main
as you can see it throws up the StrictMode and ICOSWorldForecastWrapper quite a few times.
 

Paulsche

Well-Known Member
Licensed User
Longtime User
ok, thanks Edward,

Have you tried without the Calendar2 library to compile ? Would be interesting if there is running with you also. Otherwise, it will probably just under Andoroid 2.2 does not run.
 

lagore

Active Member
Licensed User
Longtime User
I tried removing some libraries but still cannot get it to compile, so cannot debug?
 

Paulsche

Well-Known Member
Licensed User
Longtime User
So, once a user has written that the app will not start,
He has 2.2 Android.
I have emailed him the app without the calendar library that will run without problems.
Currently, about 3% of the users do not have my app have installed the version 2.2, I think this is very limited, and it just has to be accepted that Android is too old 2.2.
 

lagore

Active Member
Licensed User
Longtime User
The calendar library will work with android 2.2 and smaller so it is some sort of interaction with your app that is causing the problem, I still think that StrictMode.ThreadPolicy is the culprit as it is only valid from API 9 and above that is android 2.3 and above.
 
Top