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.