Mobile App (oxygen-alliance-app)
The flagship client. Android is live on Google Play; iOS is planned, not shipped.
Stack
- Flutter 3.38.9, Dart SDK
>=3.2.6 <4.0.0. Java 17/21, Kotlin 2.1.21, AGP 8.12, Gradle 8.13, NDK 28.2, compileSdk 36 (see README). - State: flutter_bloc. Routing: go_router.
- Firebase: core, auth, storage, messaging (FCM), crashlytics, analytics; Google sign-in.
- Media/docs:
pdfrx,cached_network_image,youtube_player_iframe,file_picker,multiple_image_camera,share_plus. Local:sqflite,shared_preferences. in_app_update(Android in-app updates),app_links(deep links),connectivity_plus.- Current version: 1.4.2+68 (pubspec.yaml).
Layout
lib/
main.dart
firebase.dart, firebase_options.dart, firebase_options_staging.dart
data/ # models, repositories, data sources
presentation/ # UI (screens/widgets)
router/ # go_router config
Theme/, utils/
android/, ios/, web/ # platform projects
Flavors & environments
Two Android flavors (android/app/build.gradle):
| Flavor | App ID | Deep-link host | API (--dart-define=API_URL) |
Firebase project |
|---|---|---|---|---|
production |
org.bmekonza.app |
app.bme-konza.org |
https://api.bme-konza.org | <PROD_FIREBASE_PROJECT> |
staging |
org.bmekonza.app.stg |
<STAGING_DEEPLINK_HOST> |
https:// |
<STAGING_FIREBASE_PROJECT> |
namespace is com.example.oxygen_alliance (internal) but the published applicationId is
org.bmekonza.app. Firebase project/app IDs per flavor are in
firebase.json — see 11-firebase.md.
Signing
- Upload keystore:
android/app/upload-keystore.jks, configured viaandroid/key.properties(storeFile,storePassword,keyAlias,keyPassword). - In CI these are reconstructed from secrets
UPLOAD_KEYSTORE_BASE64,STORE_PASSWORD,KEY_ALIAS,KEY_PASSWORD(see 01-secrets-credentials (private handover docs)). - Google Play App Signing is enabled: you upload with the upload key, Google re-signs
with the app-signing key. That's why
assetlinks.jsoncarries two fingerprints (09-website.md).
🔑 Critical to preserve: the
.jks, all passwords, and the alias. Keep an offline backup. Losing the upload key requires a Google reset; losing app-signing is handled by Play but still document the current key.[TODO: where the master keystore + passwords are archived.]
Publishing (Google Play)
CI uploads via r0adkll/upload-google-play:
- staging-v* → build staging flavor → upload to [TODO: internal/closed track].
- v* → build production flavor → upload AAB + mapping.txt to production track,
inAppUpdatePriority: 2, status: completed.
Service accounts: STAGING_SERVICE_ACCOUNT, PROD_SERVICE_ACCOUNT (Play Console →
API access → service accounts). Package org.bmekonza.app.
[TODO: Play Console account owner; review/rollout settings; data-safety form location.]
Release steps
See 03-deploy-and-releases.md. Remember to
bump the +build number on every upload.
Crash reporting & analytics
Firebase Crashlytics and Firebase Analytics are integrated — see
13-monitoring-logging.md. ProGuard mapping.txt is uploaded on
prod builds for deobfuscated stack traces.
iOS — planned, not shipped
The ios/ project and firebase_options*.dart include iOS app IDs, but the app is not
published to the App Store. Outstanding for an iOS launch:
- [ ] Apple Developer Program account + App Store Connect access ([TODO: exists?]).
- [ ] iOS signing certs/provisioning profiles + CI signing.
- [ ] iOS deep-link setup (Associated Domains / apple-app-site-association).
- [ ] App Store listing, privacy nutrition labels, review.
Tracked in 15-known-issues-roadmap.md.