A privacy-first Kotlin + Jetpack Compose app for Gapwise, currently focused on University of Toronto timetables, with secure on-device persistence, optional encrypted account sync, and native campus tools.
Kotlin · Jetpack Compose · Material 3 · Android Keystore · MapLibre · Supabase
Gapwise for Android is the native Android client for Gapwise, a free and open-source multi-university timetable and campus-intelligence platform.
While the Gapwise web platform supports 14 universities across 16 campus models in Canada, including UBC Vancouver, the University of Waterloo, and McGill Downtown, the current native Android client implementation focuses on the University of Toronto (Mississauga, St. George, Scarborough, and mixed-campus schedules), with broader multi-university native client expansion planned.
This is a real native Android application rather than a WebView wrapper. Android owns navigation, storage, lifecycle behavior, platform authentication hand-off, theming, and map rendering while the wider Gapwise ecosystem remains the source of truth for shared product semantics.
The current app includes:
- local ACORN
.icsimport through the Android system document picker; - UTM, UTSG, UTSC, and mixed-campus timetable parsing;
- normalized timetable persistence in app-private encrypted storage;
- Today, Timetable, Gap Plan, Map, and More navigation aligned with the mobile Gapwise information architecture;
- current-term/day-aware Today behavior and timetable term/weekday views;
- reserved-assessment (
RES) handling for source-backed assessment windows; - light and dark appearance modes;
- a native UTM MapLibre/OpenFreeMap map with building search, imported-class destinations, pan/zoom, compass, and theme-aware styles;
- optional Gapwise account sign-in with Google, Microsoft, or GitHub through Supabase Auth PKCE;
- optional encrypted account sync for normalized private timetable state;
- account/cloud-data deletion controls;
- native settings for appearance, routing preferences, campus-arrival context, Gap Plan preferences, account/sync, timetable management, privacy, integrations, exports, and academic-work entry points.
The Android map is functional but does not yet claim full feature parity with the web UTM routing/map stack. In particular, the web app's complete source-backed building geometry, entrance graph, indoor context, and route engine remain a separate implementation milestone for native Android.
The timetable flow is deliberately local-first:
- the original ACORN
.icssource is read on-device and is not retained as the app's persisted timetable; - only normalized meeting state is stored locally;
- local timetable/session state is encrypted with AES-256-GCM;
- the encryption key is non-exportable and held by Android Keystore;
- OAuth session tokens are stored through the same Keystore-backed encrypted local store;
- cloud sync is optional and only available after explicit sign-in and opt-in;
- the native sync client implements Gapwise's encrypted private-cloud protocol rather than uploading raw calendar bytes;
android:allowBackup="false"is used for the app;- the app requests Internet access for map tiles, authentication, and optional sync—not for basic local timetable parsing.
Gapwise does not describe its private-cloud architecture as zero-knowledge or end-to-end encrypted where the wider trust boundary does not actually support those claims.
The Android map uses MapLibre Native with OpenFreeMap light/dark styles and is centered on UTM.
Current behavior includes building search, campus recentering, mapped-building markers, imported UTM class context, marker selection, pan/zoom gestures, and compass controls. The MapLibre logo is disabled while required map attribution remains enabled.
UTSG and UTSC rooms remain valid timetable locations but are never falsely plotted onto the UTM map.
A Gapwise account is optional. Core timetable use remains available without sign-in.
When signed in, Android can use the same first-party account system as the web app:
- Google, Microsoft, or GitHub OAuth through Supabase;
- PKCE with the
gapwise://auth-callbackapp callback; - encrypted local session storage;
- explicit opt-in encrypted sync;
- manual sync/load controls;
- deletion of encrypted cloud data without deleting the device timetable;
- permanent account deletion with an optional local-timetable clear.
The Supabase project must allow this redirect URI:
gapwise://auth-callback
The native codebase keeps product responsibilities separated:
app/src/main/java/ca/gapwise/android/
├── core/
│ ├── designsystem/
│ ├── model/
│ └── persistence/
├── data/
│ ├── account/
│ ├── sync/
│ └── timetable/
├── feature/
│ ├── gapplan/
│ ├── map/
│ ├── settings/
│ ├── timetable/
│ └── today/
└── navigation/
Key implementation boundaries include timetable parsing, Keystore-backed persistence, account/auth, encrypted sync, map integration, app preferences, navigation, and feature UI.
Open the repository root in Android Studio and use JDK 17.
git clone https://github.com/GapwiseHQ/android.git
cd androidThe project targets modern Android SDKs and should be tested on both emulators and physical hardware before release. Emulator performance—especially MapLibre rendering—should not be treated as a substitute for real-device performance testing.
| Repository | Role | Primary surface |
|---|---|---|
gapwise |
Core web/PWA, canonical timetable/gap/routing semantics, public API, OpenAPI, and SDK source | gapwise.ca / api.gapwise.ca |
android |
Native Kotlin + Jetpack Compose Android client | Android app |
ios |
Native Swift + SwiftUI iOS client | iOS app |
ai |
OAuth/MCP layer for explicitly delegated student context and bounded actions | ai.gapwise.ca |
data |
Canonical public multi-university campus data, provenance, schemas, validation, and distribution | data.gapwise.ca |
docs |
Canonical public developer documentation | docs.gapwise.ca |
status |
Independent service-health monitoring and incident communication | status.gapwise.ca |
These repositories are separate implementation and trust boundaries within one Gapwise product ecosystem. Organization-wide GitHub defaults live in .github.
Gapwise is an independent student software project created by Andrew Muratov. It is not affiliated with, endorsed by, or an official service of the University of Toronto.
Original project code and documentation are available under the MIT License.
Built for the spaces between classes — native on Android.
Use Java 17 or newer, the Android SDK configured for this project, and Gradle 9.6.0
(the version in gradle/wrapper/gradle-wrapper.properties and CI):
gradle :app:compileDebugKotlin :app:testDebugUnitTest :app:lintDebugThe repository currently contains wrapper properties but no wrapper executable/JAR, so
install that Gradle version explicitly. The optional encrypted-sync adapter must send the
key broker's first-party Origin as well as the user's bearer token; the broker's web origin
guard remains enforced. Device/Keystore/OAuth behavior still needs emulator or device validation.