Your week's Google Calendar events and to-dos in a single persistent Android notification.
Pinned Calendar is an open-source Android app that keeps this week's Google Calendar events and your to-dos in one ongoing notification at the top of the shade. It reads the calendars already synced on your device, so there is no Google sign-in, no OAuth, and no internet permission β your schedule never leaves the phone.
The pin is self-healing: swipe it away by accident and it re-posts itself. When you do want it gone, switch it off in the app or turn on swipe-twice-to-remove.
| Pinned agenda (light) | Pinned agenda (dark) | To-dos tab | Settings tab |
![]() |
![]() |
![]() |
![]() |
- Persistent, self-healing notification: an ongoing pin that re-posts itself after an accidental swipe. Set its priority to Top, Normal, or Silent β Top keeps it above your everyday notifications without ever popping up or making a sound.
- Swipe twice to remove: an optional gesture to dismiss the pin for good without opening settings.
- Reads your device calendars through Android's Calendar Provider, with per-calendar colours. No sign-in, no OAuth, no network.
- Local to-dos: add quick tasks in the app and they merge into the same agenda. Tasks carry forward day to day until you complete or delete them.
- Day-grouped agenda: Today, Tomorrow, and weekday sections, color-coded per calendar, with tasks shown as their own rows.
- Tap an event row to open it directly in Google Calendar; tap anywhere else on the pin to jump into the app.
- Material 3 and Material You: wallpaper-based dynamic colour, seed colours, palette styles, AMOLED black, and selectable fonts.
- Light, dark, and system themes, plus a theme- and accent-adaptive launcher icon.
- Configurable window: the next 3 days, this week, 7 days, or 14 days. Choose which calendars appear and cap the item count.
- Background refresh with WorkManager and a ContentObserver for instant updates, plus an optional battery-optimization exemption for aggressive OEMs.
- No foreground service, so it stays light on battery; the pin restores itself after reboots and app updates.
- Offline by design: no analytics, no accounts, and minimal permissions.
Pinned Calendar is offline-first. It has no INTERNET permission and sends nothing off the device.
| Permission | Why it's needed |
|---|---|
READ_CALENDAR |
Read the events already synced on your device. |
POST_NOTIFICATIONS |
Show the pinned agenda (Android 13+). |
RECEIVE_BOOT_COMPLETED |
Re-pin the agenda after a reboot. |
REQUEST_IGNORE_BATTERY_OPTIMIZATIONS |
Optional β keep background refresh reliable on aggressive devices. |
No accounts, ads, trackers, or cloud.
| Area | Technology |
|---|---|
| Language | Kotlin 2.2 |
| UI | Jetpack Compose Β· Material 3 |
| Dynamic colour | MaterialKolor Β· Material You |
| Background work | WorkManager Β· ContentObserver |
| Storage | DataStore (Preferences) |
| Calendar | CalendarContract (Calendar Provider) |
| Notification | NotificationCompat Β· custom RemoteViews |
| Build | AGP 9.2 Β· Gradle 9.5 Β· compileSdk 36 Β· minSdk 26 |
Download the latest signed APK from the Releases page and install it on your device. You may need to allow installs from unknown sources. No Play Store account is required.
Prerequisites: Android Studio (latest), JDK 17+, and Android SDK Platform 36.
git clone https://github.com/ahnafnafee/pinned-calendar.git
cd pinned-calendar
./gradlew :app:assembleDebug # build a debug APK
./gradlew :app:installDebug # install on a connected device/emulatorOr open the project in Android Studio and run it. On first launch, grant Calendar and Notification access, then turn on "Pin to notifications". For reliable background updates on aggressive OEMs, also enable "Ignore battery optimizations" under Reliability.
Device Calendar Provider ββ
βββΊ AgendaRepository ββΊ NotificationContentBuilder ββΊ ongoing notification
Local to-dos (DataStore) ββ β² β deleteIntent
β βΌ
WorkManager (15-min refresh) + ContentObserver SelfHealReceiver re-posts on swipe
A pure-Kotlin core (windowing, day-bucketing, content building) is unit-tested and decoupled from Android, and the platform layer (RemoteViews, WorkManager, receivers) consumes it. There is no foreground service: the notification persists on its own, and a delete-intent receiver makes it self-healing.
The app is split into two tabs.
To-dos β the week at a glance:
- Week overview card β how many items are pinned, day by day.
- Add, complete, and delete local to-dos that merge into the pinned agenda.
Settings β everything else, Material You styled:
- Notifications β pin on/off, priority (Top Β· Normal Β· Silent), and optional swipe-twice-to-remove. Top keeps the pin above your everyday notifications.
- Time window β 3 days Β· this week Β· 7 days Β· 14 days.
- Calendars β toggle each synced calendar on or off.
- Display β group by day, hide completed to-dos, and a max-items cap.
- Appearance β theme, Material You, AMOLED, accent seed, palette style, and font.
- Reliability β battery-optimization exemption.
- Full colour-picker for custom seed colours
- Home-screen widget companion
- Per-to-do due-date picker
- Google Tasks integration (opt-in)
- Recurring-task support
- Wear OS tile
Have an idea? Open an issue.
Contributions are welcome. Fork the repo, create a feature branch, run ./gradlew :app:testDebugUnitTest, and open a pull request. For larger changes, open an issue first to discuss the approach.
Released under the MIT License. See LICENSE.
- MaterialKolor for seed-based Material You theming.
- The bundled fonts (Figtree, Outfit, Inter, Google Sans Flex) and the Material 3 design system.



