Articles tagged with "CalDAV"

PIMp my calendar: Aftermath

I spent some of my free time over the past few weeks trying to get the Calendar app on my Android phone to run with a non-Google and non-MS-Exchange account (see part 1, part 2, part 3, part 4 and part 5). As with my printer woes, it turned out to be an enlightening excercise. I ended up running the Radicale CALDav server on my home server and Marten Gajda's CalDAV adapter on the little machine. I discovered fun facts about Android and its development tools along the way (the highlight was discovering that changing the minimum API level in Eclipse ADT fails to trigger a re-build).

As for the lessons learned, I guess there is a balance to be struck when troubleshooting a technical issue. One approach involves poking and prodding the system, observing responses and formulating hypotheses. Another option is to study information about the system - source code, documentation, online forums and other resources. Combining these modes optimally is rather delicate and I do tend to err on the side of experimentation. The knowledge it yields may be overly specific and not very reusable but the process fosters a problem-solving mind-set that comes in handy in other situations as well. Besides, documentation may be out of date and, as we've seen, even source code may not be quite what it seems. In fact, what hindered me in resolving the calendaring problem was that I failed to recognize the extent of the system I was working with - namely that it included the development environment.


PIMp my calendar, part 5

The self-hosted calendaring solution I had been trying to set up turned out not to work due to an incompatibility between my Android phone and the CalDAV client I tried to run on it. My options at this point consisted of

  1. upgrading the firmware in my phone to Ice Cream Sandwich or higher
  2. buying a new phone
  3. porting the CalDAV Adapter to the unofficial and unsupported APIs
  4. choosing a different calendaring solution

My handset is a Geeksphone One - a sturdy little machine well supported by Cyanogen Mod yet simply too weak to handle anything beyond 2.3.x. It's condemned to stay in the Gingerbread zombie army until I retire it. Buying a new phone is plausible in the mid- to long-term but I do want a slide-out QWERTY keyboard. Looks like I'll have to overcome my allergy to Sony.

I looked into back-porting the CalDAV adapter to the unofficial APIs available in Gingerbread. It seemed like a ton of work with dubious benefits - especially when I found out the work had already been done. You see, the adapter I'd been working with (written by Gérald Garcia) was not the only one I'd found - there is also another adapter written by Marten Gajda which I hadn't considered since it isn't distributed as open-source. It does work under Gingerbread, however, which made a proper impression on me given everything I knew at this stage.

I ended up doing something I hadn't done in years - I purchased and installed a piece of closed-source software. One thing that convinced me was Marten's website which is simple and sticks to the point; the same can be said of the software. Unfortunately, even with a bona-fide polished product on the Android side it wasn't smooth sailing. I had a Radicale instance installed on my notebook for debugging and it talked to the adapter just fine - unlike the home server. Both were running Radicale 0.7 by this point so I compared their OS-specific patches (using apt-get src on my Debian notebook and the ports tree on the OpenBSD home server). One of the Debian patches added automatic creation of calendars which was lacking in the OpenBSD version (this functionality is mentioned in current Radicale documentation but that supposedly refers to 0.7.1; the experiment with Mozilla Lightning in part 3 had worked because the Debian version was involved). Porting the patch and installing from ports was a matter of minutes. After that, everything worked like a charm.


PIMp my calendar, part 4

Previous parts of the saga brought me to a point where I had an upgraded instance of the Radicale CalDAV server talking to my Android phone's CalDAV adapter and still getting nowhere. I decided to debug the Android-side code.

Attaching the debugger was a bit of a trick since the adapter has no Activity. Once I got past that, I discovered the response from Radicale was getting parsed just fine but it was only happening in an authentication context (i.e. while adding the new "CalDAV account"). I generally found that the adapter was basically a bunch of callbacks and I seemed unable to properly trigger them.

I then noticed something funny in the log (i.e. the LogCat view in the DDMS perspective in Eclipse):

VFY: unable to resolve static field 27 (CONTENT_URI) in Landroid/provider/CalendarContract$Events;

According to the documentation, Events.CONTENT_URI is one of the basic constants used when working with calendars - how could it be missing? The question led to a quick series of discoveries:

  • My phone runs Android 2.3.7 a.k.a. Gingerbread (well, not really a discovery for me but a key piece of the puzzle).
  • Proper support for non-Google calendars was only added in version 4.0 a.k.a. Ice Cream Sandwich; what there was before was unofficial and unsupported.
  • The CalDAV Adapter project lists API level 14 (Ice Cream Sandwich) as the minimum required API level in its Android manifest.
  • Back when I first tried to run the CalDAV adapter, Eclipse ADT had told me I had no compatible device; I tried modifying the manifest, changing the minimum API level to 10 (Gingerbread).
  • Changing the minimum API level of an Android project doesn't trigger a re-build in Eclipse ADT; changing the target API level does trigger a re-build.
  • Once prompted to re-build the project, ADT flags usage of higher-than-minimum-level APIs as an error, breaking the build.
  • When Dalvik encounters unknown API usage while executing the code, it marks the block where the API was used as dead code and moves on.

So I was trying to use an application that was incompatible with my handset and both the development environment and the runtime responded with silent failures. I think ADT in particular behaved quite impolitely. If using APIs beyond the minimum level is off-limits then changing the minimum level should trigger a re-build, right? As for the Android runtime, the documentation says

...the application will crash during runtime when attempting to access the unavailable APIs.

which seems to be false (or at least no indication of a crash reaches the user). In any case, the approach I'd been taking turned out to be a dead end. Continued in part 5.


PIMp my calendar, part 3

My efforts to put a server-backed calendar on my Android phone entered a new phase. I had Radicale on the server and the CalDAV adapater on the phone but they seemed to talk past each other. My phone would set up a CalDAV account successfully but then tell me "You have no calendar" when I tried to create events.

Radicale documentation says calendars are created automagically based on a URL convention, i.e. simply accessing a non-existent calendar should bring it into existence. I tried it with the Mozilla Lightning client and it worked as advertised. The Android adapter, however, still wouldn't see the new calendar nor its events.

WireShark revealed that a CalDAV client apparently enjoys a lot of freedom when formulating requests. A PROPFIND request from Lightning looked like this:

<D:propfind xmlns:D="DAV:"
    xmlns:CS="http://calendarserver.org/ns/"
    xmlns:C="urn:ietf:params:xml:ns:caldav">
  <D:prop>
    <D:resourcetype/>
    <D:owner/>
    <D:supported-report-set/>
    <C:supported-calendar-component-set/>
    <CS:getctag/>
  </D:prop>
</D:propfind>

whereas the Android adapter was sending

<d:propfind xmlns:d="DAV:"
    xmlns:c="urn:ietf:params:xml:ns:caldav"
    xmlns:cs="http://calendarserver.org/ns/"
    xmlns:ic="http://apple.com/ns/ical/">
  <d:prop>
    <d:displayname />
    <d:resourcetype />
    <cs:getctag />
  </d:prop>
</d:propfind>

and it seemed Radicale was not happy with the displayname bit:

...
<propstat>
  <prop>
    <displayname />
  </prop>
  <status>HTTP/1.1 404 Not Found</status>
</propstat>
...

Server-side source code revealed that Radicale returns 404 for properties which it does not recognize (see the final else in the long if-elif chain in _propfind_response() in xmlutils.py). My installed version of Radicale was 0.7. I downloaded the most recent stable release (0.7.1) from the project site and tried that instead. Lo and behold, it finally said

<multistatus xmlns="DAV:"
    xmlns:C="urn:ietf:params:xml:ns:caldav"
    xmlns:CS="http://calendarserver.org/ns/">
  <response>
    <href>/jh/calendar/</href>
    <propstat>
      <prop>
        <displayname>calendar</displayname>
        <resourcetype>
          <C:calendar />
          <collection />
        </resourcetype>
        <CS:getctag>"0"</CS:getctag>
      </prop>
      <status>HTTP/1.1 200 OK</status>
    </propstat>
  </response>
</multistatus>

The Calendar app on my phone, however, still insisted I had no calendar. Continued in part 4.


PIMp my calendar, part 2

My effort to set up a self-hosted calendaring solution is taking on epic proportions, turning into another CUPS saga:

  • I quickly discarded the local iCal option because I can't trust a piece of closed-source freeware from someone calling themselves "Khaos".
  • The Kolab connector dropped out of the race because Kolab itself has complex dependencies and no OpenBSD package.
  • Zafara just felt too heavy-weight and, well, corporate for my needs.

I decided to concentrate on CalDAV servers with existing OpenBSD packages: DAVical, ownCloud, Radicale and SabreDAV. All except Radicale were PHP-based which made my decision easy as I'm allergic to PHP. I have to admit, though, ownCloud looks mighty fine and seems to have a lot of momentum.

Radicale has a no-nonsense, focused feel. It is written in Python which is very nice indeed. Installing it was a breeze. I then tried to set up a calendar in Kontact and failed miserably. CalDAV support in Akonadi is apparently confined to a legacy KResource implementation and blah blah blah. I had no stamina to go there. What was important was my phone.

Installing Gérald Garcia's open-source AndroidCaldavSyncAdapater via Google Play would have been a snap. The thing is, just as I don't want Google knowing about my appointments I don't want it knowing what I run on my phone. Don't get me wrong - I'm quite fond of Google. I'm simply more fond of my privacy.

Installing the adapter from GitHub turned out to be quite smooth. Once I cloned the repository I found out the project relied on the ADT Eclipse plugin for building and signing the installation package - no trouble there. I had a bit of fun getting ADT to see my phone because I made a typo in the udev rule file. I figured it out eventually and got the package onto the phone.

Adding a Radicale account on Android involved going to Settings > Accounts & sync > Add account > CalDAV Sync Adapter and filling out my user name, password and the URL. Excited, I opened the calendar application. No nagging about MS Exchange - great. Alas, when I tried to create an event I was told "You have no calendars." Continued in part 3.


PIMp my calendar, part 1

I have a confession to make: I'm a PIM dinosaur. My appointment list resides in an ultra-minimalist GTD app I wrote as an exercise in HTML5 local storage. Even though it runs on my Android phone, it has no alarm function (did I say it was HTML5?). It's just a list of appointments I have to actively look into.

Of course, the phone has a native calendar app. Back when I had stock firmware it demanded my Google account details before it would talk to me. My appointments are none of Google's business (despite what Google may think) so I stayed away from the app. Now that I run CyanogenMod it asks about my MS Exchange account. Let's just say I don't do MS Exchange.

An alarm would be nice, though. Syncing with Kontact on my notebook wouldn't hurt either. Since I'm in the process of building a new home server, I considered fixing my calendar woes as well.

My research turned up several interesting facts:

  • The Android calendar can be backed by anything which says it's a "calendar service".
  • The default calendar service on my phone talks ActiveSync - the MS Exchange calendar synchronization protocol.
  • Other groupware tools besides MS Exchange talk ActiveSync.
    • Zafara with its Z-Push connector looks the most mature.
  • Other calendar services for Android exist.

It seems I first need to decide whether I would actually use the syncing capability of a server or whether it's best to choose the iCal option and forget about a server altogether. Continued in part 2.


« Page 1 / 1 »
Proudly powered by Pelican, which takes great advantage of Python.