# 39. Android App — Push Notifications, Biometrics, Voice Enrollment, Call Screening meta: id: shieldai-unified-restructure-39 feature: shieldai-unified-restructure priority: P1 depends_on: [shieldai-unified-restructure-34, shieldai-unified-restructure-35, shieldai-unified-restructure-36, shieldai-unified-restructure-37, shieldai-unified-restructure-38] tags: [android, jetpack-compose, native-features, push, biometrics, call-screening, mobile] objective: - Implement native Android features that differentiate the mobile experience: push notifications via FCM, biometric authentication, voice enrollment with audio recording, and call screening integration for SpamShield. deliverables: - `android/app/src/main/java/com/shieldai/android/service/FCMService.kt` — Firebase Cloud Messaging: - Extends `FirebaseMessagingService` - `onMessageReceived` — processes incoming notifications - `onNewToken` — sends token to backend (task 14) - Creates notification channels for different alert types - Rich notifications with images and actions - Deep links to relevant screens based on payload - `android/app/src/main/java/com/shieldai/android/ui/screens/auth/BiometricAuthScreen.kt` — Biometric prompt: - Uses `BiometricPrompt` from `androidx.biometric:biometric` - Face/fingerprint authentication - Fallback to device PIN/pattern/password - Stores credential in `EncryptedSharedPreferences` - `android/app/src/main/java/com/shieldai/android/ui/screens/voiceprint/RecordingScreen.kt` — Voice recording: - Real-time waveform visualization using `AudioRecord` + `Canvas` - Record / stop / playback controls - Duration timer - Quality check (minimum duration, amplitude threshold) - Submit enrollment to API - `android/app/src/main/java/com/shieldai/android/service/CallScreeningService.kt` — Call screening: - Extends `CallScreeningService` (API 29+) - Intercepts incoming calls - Queries `spamshield.checkNumber` via API - Displays caller info overlay with reputation score - Auto-blocks known spam numbers based on user rules - Logs screened calls for history - `android/app/src/main/java/com/shieldai/android/util/PermissionManager.kt` — Permission handling: - Centralized manager for all runtime permissions - Camera, microphone, phone, notifications, call screening - Handles permission rationale and denied states - `android/app/src/main/AndroidManifest.xml` — Updated permissions and services: - `INTERNET`, `RECORD_AUDIO`, `READ_PHONE_STATE`, `CALL_PHONE` - `BIND_CALL_SCREENING_SERVICE` - `RECEIVE_BOOT_COMPLETED` (for starting services) - FCM service declaration - Call screening service declaration steps: 1. **Push Notifications (FCM)**: - Add `google-services.json` to `app/` directory - Add `com.google.gms:google-services` plugin to build.gradle - Create `FCMService.kt` extending `FirebaseMessagingService` - `onNewToken`: send to backend via `api.notification.registerDevice` - `onMessageReceived`: - Parse notification payload - Create notification channel if not exists (Android 8+) - Show notification with `NotificationManager` - Handle data messages (silent pushes) for background sync - Add `FirebaseMessaging.getInstance().subscribeToTopic("alerts")` for broadcast alerts - Handle notification tap: extract `screen` and `id`, navigate via deep link 2. **Biometric Auth**: - `BiometricPrompt` with `BiometricPrompt.PromptInfo` - `setDeviceCredentialAllowed(true)` for fallback - `setConfirmationRequired(false)` for faster auth - On success: unlock `EncryptedSharedPreferences` - Show prompt on app launch if biometric is enabled 3. **Voice Recording**: - Request `RECORD_AUDIO` permission at runtime - `AudioRecord` with `MediaRecorder.AudioSource.MIC` - Configuration: 16kHz, mono, 16-bit PCM - Real-time waveform: read amplitude in a coroutine, update `Canvas` path - Minimum duration: 5 seconds - Save as WAV file - Playback with `MediaPlayer` - Submit to API via multipart upload 4. **Call Screening**: - Extend `CallScreeningService` - `onScreenCall(details)` callback when incoming call arrives - Extract phone number from `Call.Details` - Query API: `spamshield.checkNumber` (use cached result if available) - `respondToCall` with `CallResponse.Builder`: - If spam: `setDisallowCall(true)`, `setRejectCall(true)`, `setSkipCallLog(false)` - If suspicious: `setDisallowCall(false)` but show warning notification - If clean: `setDisallowCall(false)` - Show custom incoming call UI overlay (optional, requires additional permissions) - Log all screened calls to local DB 5. **Permission Manager**: - `checkPermission(permission)` → boolean - `requestPermission(permission, rationale)` → shows dialog, then system prompt - `handlePermissionResult(requestCode, permissions, grantResults)` - Guides user to Settings if permission permanently denied 6. Update manifest: - Add all required permissions - Declare FCM service with `android:exported="false"` - Declare call screening service with `android:permission="android.permission.BIND_CALL_SCREENING_SERVICE"` 7. Test on physical device (emulator cannot test FCM, biometrics, or call screening accurately). steps: - Unit: FCMService parses notification payload correctly - Unit: BiometricPrompt configuration is valid - Unit: PermissionManager returns correct status for each permission - Integration: FCM token registration sends correct data to backend - E2E: Receive test push notification and verify deep link navigation - E2E: Record voice sample and submit enrollment successfully - E2E: Simulate incoming call and verify screening logic acceptance_criteria: - [ ] App registers for FCM and sends device token to backend - [ ] Incoming push notifications display correctly with channels and actions - [ ] Tapping a notification deep links to the correct screen - [ ] Face/fingerprint authentication works for app unlock - [ ] Voice recording captures audio, shows waveform, and submits enrollment - [ ] Call screening intercepts incoming calls and blocks known spam - [ ] All permission requests include explanatory rationale - [ ] Denied permissions show helpful guidance to Settings app - [ ] Native features work on phones with API 26+ validation: - Test push notifications using Firebase Console - Verify biometric auth on device with face/fingerprint sensor - Record a 10-second voice sample and verify enrollment created in backend - Simulate incoming call using `adb shell am start -a android.intent.action.CALL -d tel:1234567890` - Run `./gradlew test` for unit tests notes: - FCM requires a `google-services.json` file from Firebase Console. Add setup instructions to README. - Call screening (`CallScreeningService`) is only available on Android 10+ (API 29+). For older versions, use a broadcast receiver for `PHONE_STATE` changes as fallback. - The call screening service runs in the background and must be lightweight. Offload API calls to a coroutine. - For call screening UI, the system provides a default incoming call screen. Custom UI overlays require `SYSTEM_ALERT_WINDOW` permission and are complex to implement correctly. - Voice recording quality matters for ML model accuracy. Use 16kHz mono WAV — this matches the web app's preprocessing pipeline. - Biometric auth should be optional. Users can always use password login. - Consider adding a Quick Settings tile for toggling call screening on/off. - For Android 14+ (API 34+), use the new `android.telecom.Call Screening` APIs if available.