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.
Calendar apps are almost synonymous with cloud accounts, so that sounds like a
missing feature. I left it out on purpose.
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 what locks you in, because 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. The app has no database of its own and no sync stack, so it
has nothing to phone home about.
What you get for free
Dropping the network permission costs Calendula nothing, because the architecture never needed it:
- Your data stays yours, and stays portable. Events live in the platform’s store, where every calendar app on the device can read them, and on your CalDAV server as standard iCalendar if you sync one.
- The privacy comes from the OS. Zero telemetry and zero analytics are easy to
claim, but Android enforces no internet permission: the app can’t open a
network connection, so it has no way to send your schedule anywhere on its
own. What it can do, like any app, is hand data to another app. When you
share an event, Calendula writes an
.icsfile and passes it to the app you picked, and it only does that when you ask. - Reminders still work. Android delegates reminder delivery to the installed calendar app, so Calendula delivers them itself as notifications.
- New accounts show up on their own. Add a CalDAV account in DAVx5 and it appears in Calendula with no integration work, because the integration point is the OS rather than a vendor API.
The trade-off
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 probably get subtly wrong.
The rest of the Floret family follows the same idea, though not this
exact bet. Android ships no system store for tasks, so Agendula keeps them in its
own store, shaped after the iCalendar VTODO, and can sync it with a CalDAV
server itself. That needs the network, so Agendula does ask for the internet
permission. If you already sync tasks through OpenTasks or tasks.org, it can
work on that provider instead. The aim is the same either way: build the part
that’s worth building, and let open standards carry the rest.