Why my calendar app has no internet permission
Open Calendula’s manifest and you’ll notice something missing: there is no
android.permission.INTERNET. The app physically cannot reach the network.
For a calendar — a category of app practically synonymous with cloud accounts —
that sounds like a missing feature. It’s the opposite. It’s the design.
The usual shape of a calendar app
Most calendar apps own their data. They sign you into an account, pull events down over the provider’s API, cache them in a private database, and reconcile changes with their own sync engine. That sync stack is the hard part: conflict resolution, recurring-event expansion, time zones, retries, token refresh. It’s also the part that locks you in — your events live in their schema, reachable only through their app.
The other option Android already gives you
Android ships a system calendar database, exposed through
CalendarContract.
Anything synced to your device lands there: a CalDAV account via
DAVx5, your Google calendar, a local on-device
calendar, a read-only WebCal subscription. They all show up through the same
content provider, with the same columns.
Calendula is a pure front-end over that provider. It reads events through
CalendarContract, and when you create or edit something, it writes straight
back. Whatever sync adapter put the calendar on your device picks the change up
and pushes it out. There is no own database and no reinvented sync stack —
so there is nothing for the app to phone home about.
What you get for free
Dropping the network permission isn’t a sacrifice; it’s what falls out of the architecture:
- Your data stays yours, and stays portable. Events live in the platform’s store and in your CalDAV account — not in a schema only Calendula understands.
- Privacy is structural, not a promise. Zero telemetry and zero analytics are easy to claim. No internet permission is enforced by the OS: even if I wanted to exfiltrate your schedule, the app couldn’t.
- Reminders still work — Calendula delivers them itself as notifications, because Android delegates reminder delivery to the installed calendar app.
- Any account “just appears.” Add a new CalDAV account in DAVx5 and it surfaces in Calendula with no integration work, because the integration point is the OS, not a vendor API.
The trade-off, stated honestly
A front-end can only be as good as the provider beneath it. Calendula doesn’t add its own server-side features, and it relies on a sync adapter like DAVx5 being installed to actually move bytes. That’s a deliberate line: I’d rather put a thoughtful Material 3 Expressive interface on an open protocol than own a sync stack I’d inevitably get subtly wrong.
The same idea drives the rest of the Floret family — Agendula is the exact same bet, made on the OpenTasks provider instead of the calendar one. Different content, identical philosophy: build the part that’s worth building, and let open standards carry the rest.