Opening an .ics file on Android without Google Calendar
Someone sends you an invitation. It arrives as invite.ics, you tap it, and
Android either opens something you didn’t want, offers you a choice of apps
none of which is a calendar, or does nothing at all.
The file is fine. The handling around it is awkward, and the same three problems come up again and again.
What the file is
An .ics file is an iCalendar
document: plain UTF-8 text, one or more VEVENT blocks, each with a start, an
end, a summary and whatever else the sender bothered to include. You can open
one in a text editor and read it. It’s one of the interchange formats that
actually caught on: nearly every calendar product reads and writes it, which is
why it’s what lands in your inbox.
A single file can hold one event or a whole calendar’s worth. A good import flow handles those two cases differently, and plenty of apps get one of them wrong.
Problem one: the file is labelled wrong
Android decides which apps can open a file from its MIME type. The correct type
here is text/calendar. In practice, calendar data turns up labelled as:
text/calendar: correct, and commontext/x-vcalendar: the older vCalendar 1.0 format, still emitted by some systems, usually with a.vcsextensionapplication/ics: not a registered type, but enough of the ecosystem passes it around that calendar apps match on it anywayapplication/octet-stream: “some bytes”, which is what a mail app falls back to when it doesn’t recognise the attachment it is handing over
That last one is the reason a perfectly ordinary .ics file opens nothing. The
data is right there and the system has been told it’s an anonymous blob, so no
app claims it.
An app can catch it anyway by registering a second intent filter that adds the
filename to the type: application/octet-stream plus a .*\.ics path
pattern. That’s what Calendula does, and it has to be a separate
filter: putting a path pattern on the MIME-typed filter would stop it matching
content:// URIs that expose no filename, which is the case the type-based
filter exists for. Between the two of them, most real-world attachments get
caught.
It is not perfect. When a content:// URI carries neither a useful type nor a
filename, nothing can tell it is calendar data. You may still get a chooser,
just one full of text editors. The fix then is to save the attachment to
storage first and open it from the file manager, which restores the extension
and with it the type.
Problem two: Google Calendar can’t import on Android
This surprises people, and it’s probably the main reason “open an ics file on android” is a query at all. As of September 2026 the Google Calendar Android app has no import function, and Google’s own help page tells Android users to open Google Calendar on a computer: Settings → Import & export. (Google could add an import button in any app update, so this is the paragraph most likely to date.)
The Android app handles tapping an invitation: an event mailed to you
through Gmail, in the shape Gmail expects. Hand it an .ics file some other
way and you are back to the browser on a laptop.
So a query that sounds like it should have a one-tap answer frequently doesn’t, and the tool sites that rank for it mostly recommend uploading your calendar file to a website, which for a document full of who you are meeting and where is a strange thing to do casually.
Problem three: one event and a thousand events want different flows
An app that treats these the same is annoying in one direction or the other. Import a single invitation and you want to see it before it lands: which calendar, whether the time is right, whether that’s the correct time zone. Import a year of history exported from somewhere else and you absolutely do not want to confirm nine hundred events one at a time; you want to pick a target calendar once.
Calendula splits on the count. One event opens the ordinary
create screen, prefilled, so you review and save it like anything else. Several
events open a picker: choose the calendar, import the lot, deduplicated by
UID so re-running a file doesn’t double the events that carry one. A
VEVENT with no UID gets inserted again, because there is nothing to match
it against. If every event
in the file names the same source calendar, that’s used to preselect a matching
target.
On a bulk import it also tells you what it couldn’t take:
- modified occurrences of a recurring event (
RECURRENCE-IDoverrides) are skipped, and only the series master imports ATTENDEErows are ignoredVTODOcomponents import as events, because there is no task model here- an unresolvable
TZIDfalls back to your local zone - a malformed
RRULEis repaired where it can be, dropped where it can’t
None of those are good news. They are all better than a silent partial import, where an app says “imported” and moves on.
Going the other way
The same pipe runs backwards, which is worth knowing before you commit a
calendar to any app. From an event’s detail screen you can share it as an
.ics, staged through a FileProvider, so it goes to any app that takes a
file. A whole local calendar can be written out to a file you choose, and
there’s an automatic backup that rewrites it into a folder you picked once.
Synced calendars are deliberately not in that list: they already live on a
server that owns them, and the copy on the phone is not the original.
If you can’t get your data out, it isn’t really yours, and .ics is how it
gets out. The rest of the app follows the same reasoning: events
live in Android’s own calendar store rather than in a private database, the app
has no internet permission at all, and export
is there so that even the platform isn’t a lock-in.
Practically, on a phone
- If the file opens a chooser and your calendar app is in it, you’re done.
- If nothing happens, save the attachment to storage and open it from a file manager. That usually restores a real filename and a real type.
- A
.vcsis vCalendar 1.0, the 1996 predecessor, two years older than iCalendar. Most apps that read.icswill open one and get the titles and times out, but repeats and reminders use a different syntax entirely and often don’t survive. Mine doesn’t carry them. - If you’re moving years of events between systems, export one file and import it once, rather than forwarding invitations one at a time.
If you’re choosing an app to open them with, look for one that registers all the MIME types the real world uses, lets you review a single event before saving it, bulk-imports the rest, and tells you what it dropped.