# Wibber — Android integration (Stage 5 + 7)

Firebase is fully removed. The app now talks to the PHP/MySQL backend. The PeerJS/WebRTC video engine is untouched.

## 1. Before you build — set your backend URL (one place)
Edit `app/src/main/java/com/wibber/chatapp/data/ApiConfig.java`:

    public static final String BASE_URL = "https://YOUR-DOMAIN.com/api/v1/";

Must be HTTPS and end with `/`. Until you change it, every request fails with "Backend URL is not set".
Backend install: upload `public_html/*` to your web root and `app/` + `database/` ONE LEVEL ABOVE it, import `database/schema.sql`,
copy `app/config/config.sample.php` to `config.local.php`, and add the cPanel cron `* * * * * php /home/USER/<path>/app/cron/cleanup.php`.

## 2. Video-call flow (what changed, what did not)
UNCHANGED, byte-identical to your original: `call.html`, `call.js`, `peerjs.js`, `style.css`, the WebView settings, the `Android` JavaScript bridge,
camera/mic permission handling, mute / camera toggle, end-call, the 22-second connection timeout, the call-duration timer.

CHANGED (only the Firebase peer exchange inside `VideoCallActivity`):
1. `VideoCallFragment` -> `MatchSearcher` joins the server queue; both users learn of the match from their own status poll.
2. Each user receives a **server-issued random PeerJS id** (`my_peer_id`) and the partner's id (`partner_peer_id`). Previously the Firebase UID was the PeerJS id.
   `VideoCallActivity` passes `my_peer_id` straight to `call.js init(localId, isCreator)` and `partner_peer_id` to `setOtherUserId()`.
3. Handshake kept: `Android.onPeerOpen` -> `POST video/peer-ready` -> server reports `partner_ready` -> only then the creator calls `setOtherUserId` (1 s delay as before).
4. The room is polled every ~2 s for the whole call. This is how "partner left" is detected AND the server's "still here" signal. Hang-up -> `POST video/end-room`; the partner sees `ended`.
5. `EXTRA_LOCAL_ID` / `EXTRA_REMOTE_ID` keep their names but now carry PeerJS ids; new `EXTRA_PARTNER_NAME`. `EXTRA_ROOM_ID` is a `long`.

## 3. Files
### Added
- `app/src/main/java/com/wibber/chatapp/ForgotPasswordActivity.java`
- `app/src/main/java/com/wibber/chatapp/MatchSearcher.java`
- `app/src/main/java/com/wibber/chatapp/WibberApp.java`
- `app/src/main/java/com/wibber/chatapp/data/ApiCall.java`
- `app/src/main/java/com/wibber/chatapp/data/ApiCallback.java`
- `app/src/main/java/com/wibber/chatapp/data/ApiClient.java`
- `app/src/main/java/com/wibber/chatapp/data/ApiConfig.java`
- `app/src/main/java/com/wibber/chatapp/data/ApiException.java`
- `app/src/main/java/com/wibber/chatapp/data/AppState.java`
- `app/src/main/java/com/wibber/chatapp/data/Models.java`
- `app/src/main/java/com/wibber/chatapp/data/Poller.java`
- `app/src/main/java/com/wibber/chatapp/data/SessionManager.java`
- `app/src/main/java/com/wibber/chatapp/data/WibberApi.java`
- `app/src/main/res/layout/activity_forgot_password.xml`

### Modified
- `app/build.gradle`
- `app/src/main/AndroidManifest.xml`
- `app/src/main/java/com/wibber/chatapp/ChatMessage.java`
- `app/src/main/java/com/wibber/chatapp/CoinSpinActivity.java`
- `app/src/main/java/com/wibber/chatapp/LoginActivity.java`
- `app/src/main/java/com/wibber/chatapp/MainActivity.java`
- `app/src/main/java/com/wibber/chatapp/RegisterActivity.java`
- `app/src/main/java/com/wibber/chatapp/SettingsActivity.java`
- `app/src/main/java/com/wibber/chatapp/SplashActivity.java`
- `app/src/main/java/com/wibber/chatapp/TextChatActivity.java`
- `app/src/main/java/com/wibber/chatapp/TextChatFragment.java`
- `app/src/main/java/com/wibber/chatapp/VideoCallActivity.java`
- `app/src/main/java/com/wibber/chatapp/VideoCallFragment.java`
- `app/src/main/res/layout/activity_login.xml`
- `app/src/main/res/layout/activity_settings.xml`
- `app/src/main/res/xml/backup_rules.xml`
- `app/src/main/res/xml/data_extraction_rules.xml`
- `build.gradle`
- `gradle/libs.versions.toml`

### Removed
- `app/google-services.json`
- `app/release/baselineProfiles/0/app-release.dm`
- `app/release/baselineProfiles/1/app-release.dm`
- `app/release/output-metadata.json`
- `app/release/wibber.apk`
- `app/src/main/java/com/wibber/chatapp/Utils.java`
- `app/src/main/java/com/wibber/chatapp/WebRTCClient.java`

## 4. Firebase removed
- Gradle: `google-services` plugin (root + app), `firebase-auth`, `firebase-database`, version-catalog entries for all three.
- `app/google-services.json`.
- All Firebase imports / `FirebaseAuth` / `FirebaseDatabase` calls in 11 Java files (Splash, Login, Register, Main, VideoCallFragment, TextChatFragment, VideoCallActivity, TextChatActivity, CoinSpinActivity, Settings, plus the `OnSuccess/OnFailureListener` task imports).
- Firebase-only behaviour: queue scanning/claiming, `notifications/*` relay nodes, `active_*_room` nodes, `online_users`, client-side coin writes.
- Also removed (unused, verified by search): `WebRTCClient.java`, `Utils.java`, native `io.github.webrtc-sdk:android` (≈50 MB), old `app/release/*` build output.
- Kept: AdMob (`play-services-ads`), Lottie, AppCompat/Material/ConstraintLayout. No new dependencies were added (HttpURLConnection + org.json).
- Sweep result: `grep -ri "firebase|google-services"` over the whole project (excluding build output) returns nothing.

## 5. API integration summary
`data/ApiClient` is the only HTTP code: timeouts 10 s / 15 s, retries (max 2, back-off) ONLY for repeat-safe calls, JSON envelope parsing, never on the main thread, callbacks cancelled on `onDestroy`.
`data/WibberApi` holds all 24 endpoints. `data/SessionManager` stores the token (excluded from Android backup). `data/Poller` = no overlapping requests + back-off.
- 401 / suspended account -> session cleared, one toast, back to Login. Splash validates the saved token with `auth/me`.
- Duplicate protection: buttons disabled while a request runs; matchmaking join is idempotent server-side; chat send uses `client_msg_id`; spin is never auto-retried.
- Polling only while visible: heartbeat 30 s (MainActivity resumed), matchmaking 2 s (searching), chat 2 s (chat screen started), video room 2 s (during a call). Leaving the tab/app cancels a search and the server refunds it.
- Coins/spin/costs are server-authoritative; the wheel animates to the server's `segment_index`.
- New: Forgot-password screen (email code), Delete-account button in Settings (Play-Store requirement), report reasons + optional block in text chat.

## 6. Verification status (honest)
| Item | Status |
|---|---|
| Backend: 74 integration tests + peer-ready handshake simulation (both arrival orders) against MariaDB 10.11 / PHP 8.3 | PASSED |
| All Android Java compiles (`javac`, Android API 34 `android.jar`, resource ids from your real XML) | PASSED — with **stubs for AndroidX/Material/Ads/Lottie**, so this is NOT a Gradle build |
| XML (layouts, manifest, backup rules) well-formed; 24/24 endpoints exist on server | PASSED |
| Firebase sweep; video assets byte-identical | PASSED |
| **Gradle build / APK / merged-manifest check** | **NOT RUN** (no Google Maven access here). Build it in Android Studio and send me any error. |
| **Two-device video call** | **NOT TESTED** |
| Real-device UI behaviour, ads, camera/mic, Android 14/15 specifics | NOT TESTED |
| Password-reset email delivery on your host | NOT TESTED |

## 7. Two-device test procedure
Prereqs: backend live on HTTPS, `BASE_URL` set, two phones (A, B) on different networks if possible (one Wi-Fi, one mobile data), Android Studio build installed on both. Keep phpMyAdmin open.
0. Register two accounts (A: `a@test.com`, B: `b@test.com`). Each should show **20 coins**. Check `users` + `coin_wallets` rows.
1. **Video match:** both open the Video tab and tap Start within a few seconds. Expect: both show the searching animation, count "2 users are searching", both coins drop to **15**, within ~2-4 s both open the call screen.
   DB: `video_rooms` has 1 row; `user1_peer_id` / `user2_peer_id` differ and each phone's logcat line `onPeerOpen: peerId = wb…` matches its own id (`adb logcat -s ContentValues WebView`).
2. **Handshake:** within ~5 s both see the other's video and hear audio. `video_rooms.user1_ready = user2_ready = 1`, `status = active`.
3. **Controls:** mic button (partner stops hearing you), camera button (your tile fades, partner sees black), check each direction.
4. **Hang up:** A taps end. B must show "User has left the call" and return to Main within ~2 s. DB: room `ended`, `end_reason = left`, `active_sessions` empty. Search again works.
5. **Kill test:** start a call, force-stop the app on A. Within ~45 s B gets "User has left the call"; room `ended` with `partner_timeout`.
6. **Back-button / network drop:** B turns on airplane mode for 60 s mid-call -> A is ended after ≈45 s; B on reconnect returns to Main.
7. **No match:** A alone taps Start; after 30 s "No match found", coins back to **20**; `coin_transactions` shows one `search_cost` and one `search_refund`.
8. **Cancel:** tap Start then Cancel quickly -> coins back to 20, no open row in `matchmaking_queue`.
9. **Background:** tap Start, press Home -> search cancelled and refunded.
10. **Text chat:** match on Text tab; send messages both ways (appear instantly for sender, ≤2 s for receiver), typing dots, Back ends it for both. Report -> pick reason -> row in `user_reports` with the *partner* as reported; Block -> they never match again.
11. **Spin:** spin -> wheel stops on the server's segment, coins increase by that amount; second spin within 25 s is refused with a message.
12. **Session:** in phpMyAdmin set `user_sessions.revoked_at` for A, then open any screen -> toast + Login screen. Logout -> token row revoked.
13. **Hostile networks:** if calls connect on Wi-Fi/Wi-Fi but fail Wi-Fi/mobile-data, that is NAT traversal: PeerJS's public server provides STUN only (no TURN). See §8.

Record each result with phone models/Android versions; do not treat video as working until steps 1-6 pass on two physical devices.

## 8. Known limitations / recommendations (not changed, to preserve the working call)
- No TURN server: some mobile-carrier / symmetric-NAT pairs will not connect. Fix later with a paid/hosted TURN (not possible on shared hosting) and by passing `config.iceServers` in `call.js`.
- `call.html` loads PeerJS 1.3.2 from cdnjs (the bundled `peerjs.js` is a different build and is not used). Calls need cdnjs reachable.
- WebView: `setWebContentsDebuggingEnabled(true)` and file-URL access flags were left as in the original; consider disabling debugging in release builds.
- Orientation change recreates `VideoCallActivity` and drops the call (same as the original).
- Video screen has no Report/Block button yet (endpoints `reports/create`, `blocks/create` support `room_type=video`); UI is planned for the redesign stage.
- AdMob IDs are Google test IDs; Settings links (`yourwebsite.com/...`, "Your Developer Name") are still placeholders — replace before release.
- `minifyEnabled false` in release (unchanged).
