TigerDuck is a campus companion app built by a group of students at NTUST.
It was created to solve common pain points: scattered resources, delayed notifications, and unintuitive interfaces.
Ever used TAT? We're working hard to make TigerDuck feel even more OAO!
The project is under active development; some features are still being polished.
- See how many assignments are still due at a glance
- Fully automatic sync of assignments and deadlines from Moodle — no more surprise due dates!
- Ongoing notifications and push alerts — don't wait until the last hour for Moodle's reminder
- Synced directly from the course enrollment system — no more Moodle delay
- Interactive Time Slider — see exactly where your next class is
- Per-semester / cumulative GPA, rankings, and per-course grades in one place
- Interactive charts to track grade trends over time
- Aggregates the school's ICS calendar with Moodle deadlines
- Month view, date navigation, pull-to-refresh
- Instant library entry QR code with zero delay
- 50+ locales shared with the iOS client — follow the system language or set per-app
- Course / classroom names automatically abbreviated when long
- Add what you want, remove what you don't
- Editable tabs, freely add/remove home sections, accent color theming
- Now & Next main screen: current / upcoming class with an in-progress progress bar
- Today list and per-course detail screen
- Tile and Complication to surface the next class on the watch face
- Auto-syncs schedule, locale, and accent color from the phone over the Wearable Data Layer
- Tap the empty state on the watch to open TigerDuck on the paired phone
- Assignments — Fully automatic Moodle assignment sync
- Assignments+ — Push and ongoing notifications
- Class Table — Fetched from the course enrollment system
- Class Table+ — Editable course names, deletable courses
- Calendar — Aggregated events from school announcements, Moodle, etc.
- Historical GPA & Rankings — Per-semester / cumulative / per-course grades + interactive charts
- Graduation Credit Calculator — Check completion status for general education categories, college / department credits, PE, Chinese, English, and other requirements
- Course Search — Display GPA alongside results for better enrollment decisions
- Lottery Probability & Preference Suggestions — Estimate admission odds based on capacity and current enrollment
- Library Entry QR Code — Quick access to the library entry QR code
- Study Room Booking — Reserve and check availability of library study rooms
- NTUST Library Events — Event registration and lookup (campus network required)
- Department & Office Announcements — Aggregated announcements
- LLM-classified bulletins + subscriptions — Server-side classification & de-duplication, subscribable categories, unread filter
- Scholarships — Filterable by eligibility (low-income, indigenous, etc.)
- Daily Club Activities — Curated daily club event listings
- Empty Classroom Finder — Quickly find currently available classrooms
- Free Lunch Notifications — Anyone can register (real-name); aggregates info from NTUST and NTU with push notifications
- Multilingual (50+ locales, shared with iOS) — Follows system language or per-app override
- Course / Classroom name abbreviations — One-tap toggle, fully reversible
- RTL layout fixes — Arabic / Hebrew and other right-to-left scripts
- Now & Next main screen — Current / next class with an in-progress progress bar
- Today list + course detail
- Tile and Complication — Surface the next class directly on the home screen / watch face
- Phone ↔ Watch sync — Schedule, auth state, locale, and accent color over the Wearable Data Layer
- Empty-state wake — Tap on the watch to open TigerDuck on the phone
| Item | Requirement |
|---|---|
| OS | Android 10 (API 29) or later |
| Wear OS | Wear OS 4 (API 30) or later, paired with the Play build of the phone app |
| SSO Account | Student account (required for some features) |
| Library | Library account (required for some features) |
- Android Studio (latest preferred)
- Android SDK Platform 36
- JDK 11
# Clone the repository (with submodules: localization, name-abbr)
git clone --recurse-submodules https://github.com/tigerduck-app/tigerduck-app-android.git
cd tigerduck-app-android
# Already cloned without --recurse-submodules? Pull them in:
git submodule update --init --recursive
# Open in Android Studio, or build directly with Gradle.
# There are two product flavors — fdroid and play — pick one:
./gradlew :app:assembleFdroidDebug # or :app:assemblePlayDebug
./gradlew :app:installFdroidDebug # or :app:installPlayDebug💡 Course / classroom abbreviations (
name-abbr/) and localization strings (localization/generated/android/) come from submodules. Always initialize submodules before opening Android Studio, otherwise the build will fail to locate resource files.
The Wear app is Play only: it shares applicationId = org.ntust.app.tigerduck with the Play phone build, and shares Course / PeriodTimes / NextClassResolver / AppClock with the phone via the new :shared module.
./gradlew :wear:assembleDebug
./gradlew :wear:installDebug # requires a Wear OS emulator or paired watch
⚠️ The wear app depends onplay-services-wearable(GMS) for pairing, which is incompatible with F-Droid policy — there is no F-Droid variant of the wear app, and it will not appear on F-Droid.
Three install scripts under debug/ filter by ro.build.characteristics so they push each APK to the right device, which is especially handy when a phone and watch are connected at the same time:
| Script | What it does |
|---|---|
./debug/install-fdroid.sh |
Build + install :app:fdroidDebug |
./debug/install-play.sh |
Build + install :app:playDebug, optionally pushing :wear:debug to a paired watch in the same run |
./debug/install-play-release.sh |
Build + install :app:playRelease (and optionally :wear:release) — for testing R8 / signing behavior |
For the full picture of build variants, the debug clock override (time-travel testing), wireless ADB, push backend wiring, and common pitfalls, see debug/DEBUG.md.
Translation strings live in the localization/ submodule and are shared with the iOS client.
- Source files in
localization/source/— 50+ locales (en.json,zh-Hant.json,ja.json,ko.json,ar.json, …) - Generated outputs in
localization/generated/:- Android:
android/values/strings.xml(Traditional Chinese as default),android/values-<lang>/strings.xml - iOS:
ios/<lang>.lproj/Localizable.strings
- Android:
- The Android app's
app/src/main/res/values*/strings.xmlis overwritten by the same script — do not edit generated files by hand.
Run a one-shot sync:
python3 tools/localization/sync_localizations.pyThe Android build wires this in automatically (preBuild depends on syncLocalizations), so editing localization/source/*.json regenerates Android/iOS outputs before each build.
For new locales or strings, open a separate PR against the localization/ submodule — do not edit generated files.
The name-abbr/ submodule ships shared course / classroom abbreviation dictionaries used by both the Android and iOS apps to keep long names readable.
tigerduck-app-android/ # Android App + Wear OS (Kotlin 2.3 / Compose / API 26+)
├── app/ # Phone app (fdroid / play flavors)
│ ├── build.gradle.kts
│ └── src/main/java/org/ntust/app/tigerduck/
│ ├── auth/ # NTUST SSO authentication, login state
│ ├── data/
│ │ ├── cache/ # File cache
│ │ ├── local/ # Room data layer
│ │ ├── model/ # Domain / DTO models
│ │ └── preferences/ # App preferences and credential vault (EncryptedSharedPreferences)
│ ├── debug/ # Developer tools incl. debug clock override (debug builds only)
│ ├── di/ # Hilt modules
│ ├── liveactivity/ # Live activity / ongoing notification
│ ├── network/ # Class table / Moodle / bulletins / library APIs
│ │ └── model/
│ ├── notification/ # Assignment due notification scheduling
│ ├── ui/
│ │ ├── component/ # Shared composables
│ │ ├── navigation/ # NavHost / tab navigation
│ │ ├── screen/ # Screens and ViewModels
│ │ │ ├── home/ # Home (Time Slider, assignments, customizable sections)
│ │ │ ├── classtable/ # Class table
│ │ │ ├── calendar/ # Calendar
│ │ │ ├── library/ # Library
│ │ │ ├── score/ # Historical GPA & rankings
│ │ │ ├── more/ # "More" hub
│ │ │ ├── settings/ # Settings (language, tabs, notifications, live activity, source)
│ │ │ └── onboarding/ # First-run onboarding + privacy gate
│ │ ├── theme/ # Tokens, palette, visual presets
│ │ └── AppState.kt
│ ├── widget/ # Home screen widgets
│ ├── MainActivity.kt
│ └── TigerDuckApp.kt
├── shared/ # Phone + watch shared module (`:shared`)
│ └── src/main/java/org/ntust/app/tigerduck/shared/
│ ├── clock/ # AppClock abstraction (overridable by debug clock)
│ └── … # Course / PeriodTimes / CourseScheduleUtils / NextClassResolver
├── wear/ # ⌚ Wear OS app (Play only, `:wear`)
│ └── src/main/java/org/ntust/app/tigerduck/wear/
│ ├── ui/ # Now & Next / Today / course detail / settings
│ ├── tile/ # NextClassTileService
│ ├── complication/ # NextClassComplicationService
│ └── data/ # DataLayerListener / SchedulePersistence / Repository / SyncRequester
├── debug/ # Quick install scripts and [DEBUG.md](debug/DEBUG.md) (build variants, debug clock, push)
├── gradle/
│ └── libs.versions.toml # Version Catalog
├── localization/ # ⤴ git submodule: 50+ locale translations (incl. `watch_*` keys)
├── name-abbr/ # ⤴ git submodule: course / classroom abbreviations
├── tools/localization/ # Translation sync script (auto-triggered by preBuild)
├── build.gradle.kts
└── settings.gradle.kts
Pull requests and issues are welcome!
Before submitting, please make sure to:
- Follow the existing Kotlin / Compose code style and architectural conventions
- Run at least
:app:compileFdroidDebugKotlin/:app:compilePlayDebugKotlinor:app:assembleFdroidDebug/:app:assemblePlayDebugonce - Name your branch using
feature/your-featureorfix/your-fix - Target the
devbranch when opening a PR, and enable Copilot review - For translation strings, open a separate PR against the
localization/submodule — do not edit generated files
This project is licensed under the GNU Affero General Public License v3.0.
