Introduction
The article describes a simple implementation of an application for Windows Mobile, that can synchronize the calendar with an external provider (in this case, Google) able to provide the events in iCalendar format.
Background
iCalendar is a file format which allows to exchange event/meeting requests and tasks. The standard shares files with an extension of .ics. Recipients of the iCalendar data file can respond to the sender easily or counter propose another meeting date/time. A very simple event on iCalendar should be:
BEGIN:VCALENDAR
VERSION:2.0
BEGIN:VEVENT
DTSTART:200714T170000Z
DTEND:20070715T035959Z
SUMMARY: Dinner with my father
END:VEVENT
END:VCALENDAR
The standard is based on RFC 2445.
Using the Code
The code is based on the iCalendar parser developed by J. Tim Spurway and adapted to the Windows Mobile and Microsoft Compact Framework .NET 3.5. The application has been developed in C#.
The main steps to develop the system are:
- implementing the Emitter to receive events
- synchronizing events with Outlook calendar and
- implementing the User Interface
The following sequence diagram shows the entire application. When the user calls the "Sync" method implemented by "Form
", the system makes an HTTP Request and then parses the iCalendar stream flushed by the server. The "Parser" (implemented by J. Tim Spurway and Robert Prouse) passes a token found to the implemented "IEmitter
" interface. In our case, we implemented the IEmitter
by OutlookCalendarEmitter
which accesses the Outlook Calendar and pushes Appointment into the database.
Implementing the Emitter to Receive Events
"IEmitter
" is a simple interface
able to receive from the "Parser
" class events and attributes from an iCalendar
stream source :
class OutlookCalendarEmitter : IEmitter
{
DateTime start = DateTime.Now;
DateTime end = DateTime.Now;
string summary = "";
string currentTag = "";
string currentValue = "";
string currentComponent = "";
...
public void doEndComponent()
{
Debug.WriteLine("doEndComponent: currentTag=" + currentTag);
if (currentComponent.Equals("Vevent"))
{
AddAppointment(summary, summary, start, end);
}
}
public void doID(Token t)
{
Debug.WriteLine("doID: \t" + t.TokenText);
currentTag = t.TokenText;
}
public void doValueProperty(Token t, Token iprop)
{
if (iprop != null)
{
Debug.WriteLine(t.TokenText + " " + iprop.TokenText);
currentTag = t.TokenText;
currentValue = iprop.TokenText;
}
else
{
currentValue = t.TokenText;
}
}
public void doRest(Token t, Token id)
{
doPrepare(id.TokenText, t.TokenText);
}
}
When the "doEndComponent()
" is called for a "VEvent
", you can add an appointment on the pocket PC Calendar calling:
AddAppointment(summary, summary, start, end);
Interfacing Microsoft Outlook Pocket Calendar
Now it's time to implement the "AddAppointment(summary, summary, start, end);
" method. We need to access the "OutlookSession
" and put on the "Appointments
" the new event.
class OutlookCalendarEmitter : IEmitter
{
string formatDate = "yyyyMMdd'T'HHmmss'Z'";
CultureInfo culture = CultureInfo.InvariantCulture;
OutlookSession session = new OutlookSession();
...
private void AddAppointment
(String subject, String text, DateTime start, DateTime end)
{
Debug.WriteLine("Appointment");
Appointment a = null;
for (int i = 0; i < session.Appointments.Items.Count; i++)
{
Appointment app = session.Appointments.Items[i];
if (app.Subject.Equals(subject))
{
a = app;
break;
}
}
if (a==null) a=session.Appointments.Items.AddNew();
a.Subject = subject;
a.Body = text;
a.Start = start;
a.End = end;
a.Subject = subject;
a.Update();
}
}
Developing the User Interface
In Visual Studio, create a new form such as figure 1:
On the "Sync Now" button, call (double click) the "Sync
" method.
private WebRequest req = null;
private OutlookCalendarEmitter emitter = new OutlookCalendarEmitter();
private void DoSync()
{
string urlText = this.textBoxUrl.Text;
try
{
req = WebRequest.Create(urlText);
req.Method = "GET";
TextReader reader = new StreamReader(req.GetResponse().GetResponseStream());
Parser parser = new Parser(reader, emitter);
parser.Parse();
}
catch (Exception e)
{
this.listBox1.Items.Add("Error: " + e.Message);
}
req = null;
}
Project
In the attached code, you can find iparser developed by J. Tim Spurway, the user interface and the cabinet project to distribute it. The application was tested on Treo 750.