Android App — Play Store Launch Checklist¶
Mission: ship the Android app (AstraDial) to the Google Play Store with full call functionality working on real devices, on our own GPL-free engine.
How to read this: [x] = done and verified; [ ] = not done or not yet verified. Per the no-overclaim rule, audio/call items stay unchecked until confirmed on a real device (never the emulator — emulator audio is an artifact). Cross-refs: android-status, gpl-compliance-roadmap, mobile-app-access.
Last updated: 2026-07-10.
Phase 0 — App shell & UX (complete)¶
- Login/onboarding redesign (mockup #24) + pre-login server dropdown (prod/staging/custom)
- Contacts (org directory), Tickets, Pulse analytics tabs
- SIM Calls Only (click-to-call + routing toggle)
- App launcher icon (Astradial "a") + splash (#075FA7)
-
SecureStorecrash self-heal (EncryptedSharedPreferencesVERIFICATION_FAILED) - Vestigial linphone Core account purged at startup (no auth popups)
- Old linphone UI removed from the shell (drawer locked + gear→Settings rows gone)
- Meetings UI removed
Phase 1 — Own engine (AstraSIP + WebRTC), signaling (complete)¶
-
AstraEngineintegrated into the app (F1) — namespacecom.softphone.astradial.engine - Registers over WSS on staging (REGISTER→200)
- Registers over WSS on prod (
devsip:8089/wslistener enabled) - Call UI (mockup #37) bound to
AstraEngine.onCallState(F2) — incoming/outgoing/active/ended - Outbound INVITE→200→ACK→Established→BYE on the wire; hold wired; in-call DTMF numpad UI
- FGS crash on call-establish-while-backgrounded fixed (
b4f4a4a84) - Debug builds run native x86_64 (no arm-on-x86 libsrtp translation artifact)
Phase 2 — Real-device call functionality ⚠️ THE GATE — not verified¶
Do all of these on the moto g34 (arm64), destination *43 (echo) or +91 9944421125 only. - [x] 2-way audio on a real device via *43 echo — CONFIRMED 2026-07-11 on the V2037 (clean-room app, own engine, zero linphone); user heard the echo. Re-verified on a CLEAN install with zero adb (00a3400): the app now requests RECORD_AUDIO itself at the tab shell (granted via the OS dialog, USER_SET), first call has clean mic init, full 2-way audio. RCA: original one-way audio was purely the missing runtime mic request — fixed. - [x] Clean-install full flow (V2037): sign in (Staging) → wss line picker → REGISTER on wss://stagesip:8089/ws → land on tabs → all 5 tabs render (reactive-signedIn fix 00a3400) → Pulse dashboard live with real staging data → *43 2-way audio. GPL-free, own engine. - [ ] Ext-to-ext real call, 2-way audio - [ ] PSTN call to +91 9944421125 (adds Tata trunk + opus→alaw transcode) — 2-way audio - [ ] DTMF (RFC 2833 / dtmf_mode=rfc4733) works in-call - [ ] Mute / speaker / hold / resume work - [ ] Hangup tears down cleanly (BYE sent; no orphaned channel) - [ ] Incoming call rings over a locked/killed device (full-screen-intent notification) - [ ] Killed-app FCM wake cold-start rings (cred-restore-on-cold-process path) - [ ] Call quality acceptable on cellular (note: alaw-only, no FEC — cellular may be choppy)
Phase 2b — VoIP push registered on app open (iOS parity)¶
Full spec + iOS reference + 9 test cases: astradial-astracall-android/VOIP-PUSH-ON-OPEN-HANDOFF.md. Backend is shared + done (POST /users/voip-push-token + new GET /users/voip-push-status); this is the Android client flow, strictly gated on notification permission (parity with iOS). - [ ] AstradialApi.voipPushStatus(endpoint, token) → GET /users/voip-push-status (200→registered && token_matches, 404/error→null=proceed) - [ ] AstradialPush.ensureRegisteredOnOpen(promptIfNeeded) — guard SIP-registered + FCM-token present → GET-check (skip if already registered) → POST_NOTIFICATIONS gate → register; AtomicBoolean re-entrancy guard - [ ] Route triggers through the gate: onNewToken → ensureRegisteredOnOpen(promptIfNeeded=false); post-login SIP-attach → ensureRegisteredOnOpen() (first-login prompt) - [ ] App-open hook (main Activity onResume / ProcessLifecycleOwner ON_START) calls it on cold launch + every foreground - [ ] POST_NOTIFICATIONS declared in manifest; runtime request via ActivityResultContracts.RequestPermission (pre-API-33 = granted by default) - [ ] Bundle id com.astradial.phone accepted by the wake gateway / token registry - [ ] On-device: run the 9 TCs in the handoff (allow/deny/already-registered/rotation/404-fallback/flap re-entrancy…) — FCM has no reliable emulator token, so real device only
Phase 3 — Mobile App Access gate (on-device)¶
- Login gated to
sip_port='wss'lines (picker + manual reject;6bc29d83) — code + compile - On-device: only mobile-enabled lines show in the picker
- On-device: manual entry of a non-wss user shows "This SIP user is not provisioned"
- On-device: a
wss+SIM line (e.g. ext 1003) still logs in
Phase 4 — GPL compliance (the legal gate to ship) ⚠️ not done¶
See gpl-compliance-roadmap. Removing the SDK is necessary but not sufficient — the app is a GPLv3 fork. - [ ] Real-device audio proven (Phase 2) — the prerequisite to start deleting liblinphone - [ ] Delete the liblinphone call code (CoreContext Core/Call bodies, ui/call/model/*, telecom) - [ ] Remove the linphone-sdk-android dependency - [ ] Phase 3 clean-room app: port our org.linphone.astradial.* + AstraEngine into astradial-astracall-android, re-namespaced com.astradial.* - [ ] Verify built APK/AAB: no liblinphone*.so, no org.linphone.core classes, no linphone-sdk - [ ] App LICENSE → proprietary; WebRTC (BSD) + Firebase (Apache-2.0) attribution in About
Phase 5 — Release engineering (Play Console)¶
- Google Play Console app created (package
com.astradial.phone) - Upload signing key configured (Play App Signing) — keystore preserved (keeps FCM token)
- Release AAB built (
bundleRelease), minify/R8 verified, no debug receivers shipped - Store listing: title, short + full description, screenshots (phone), feature graphic, icon
- Privacy policy URL
- Data safety form (mic, contacts, push token, analytics)
- Content rating questionnaire
- Target API level meets Play's current requirement
- Permissions justified (RECORD_AUDIO, FGS microphone|phoneCall, USE_FULL_SCREEN_INTENT, POST_NOTIFICATIONS)
Phase 6 — QA & release rollout¶
- Full P1 regression on a real device (login, tabs, contacts, tickets, SIM-only, settings)
- Call regression matrix (Phase 2) re-run on the release build
- Internal testing track → closed testing (a few real testers) → verify install + calls
- Production rollout (staged %), monitor crashes (Crashlytics) + call-quality
- Docs finalised after launch confirmed
Right now, the one blocker that gates the rest¶
Phase 2 — real-device 2-way audio on the own engine. Everything downstream (delete liblinphone → GPL-clean binary → Play submission) waits on hearing audio on the moto g34. Nothing is release-ready until that [x].