Server-side: - Add push credential auto-creation for FCM incoming call notifications - Add queue alert FCM notifications (data-only for background delivery) - Add queue alert cancellation on call accept/disconnect - Fix caller ID to show caller's number instead of Twilio number - Fix FCM token storage when refresh_token is null - Add pre_call_status tracking to revert agent status 30s after call ends - Add SSE fallback polling for mobile app connectivity Mobile app: - Add Android telecom permissions and phone account registration - Add VoiceFirebaseMessagingService for incoming call push handling - Add insistent queue alert notifications with custom sound - Fix caller number display on active call screen - Add caller ID selection dropdown on dashboard - Add phone numbers endpoint and provider support - Add unit tests for CallInfo, QueueState, and CallProvider - Remove local.properties from tracking, add .gitignore Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
5.8 KiB
TWP Softphone — Mobile App
Flutter-based VoIP softphone client for the Twilio WordPress Plugin. Uses the Twilio Voice SDK (WebRTC) to make and receive calls via the Android Telecom framework.
Requirements
- Flutter 3.29+ (tested with 3.41.4)
- Android device/tablet (API 26+)
- TWP WordPress plugin installed and configured on server
- Twilio account with Voice capability
Quick Start
cd mobile
flutter pub get
flutter build apk --debug
adb install build/app/outputs/flutter-apk/app-debug.apk
Server Setup
The app connects to your WordPress site running the TWP plugin. The server must have:
- TWP Plugin installed and activated
- Twilio credentials configured (Account SID, Auth Token)
- At least one Twilio phone number purchased
- A WordPress user with agent permissions
SSE (Server-Sent Events) — Apache + PHP-FPM
The app uses SSE for real-time updates (queue changes, agent status). On Apache with PHP-FPM, mod_proxy_fcgi buffers output by default, which breaks SSE streaming.
Fix — Create a config file on the web server:
echo 'ProxyPassMatch "^/wp-json/twilio-mobile/v1/stream/events$" "unix:/run/php-fpm/www.sock|fcgi://localhost/path/to/wordpress/index.php" flushpackets=on' > /etc/httpd/conf.d/twp-sse.conf
httpd -t && systemctl restart httpd
Adjust the paths:
- Socket path must match your PHP-FPM config (check
grep fcgi /etc/httpd/conf.d/php.conf)- Document root must match your WordPress installation path
Diagnosis — If the green connection dot stays red:
# Check current PHP-FPM proxy config
grep -r "fcgi\|php-fpm" /etc/httpd/conf.d/
# Check if flushpackets is configured
grep -r "flushpackets" /etc/httpd/conf.d/
# Test SSE endpoint (should stream data continuously, not hang)
curl -N -H "Authorization: Bearer YOUR_TOKEN" \
https://your-site.com/wp-json/twilio-mobile/v1/stream/events
Notes:
flushpackets=onis aProxyPassMatchdirective — it cannot go in.htaccess- If using nginx instead of Apache, the
X-Accel-Buffering: noheader (already in the PHP code) handles this automatically - The app automatically falls back to 5-second polling if SSE fails, so the app still works without this config — just with higher latency
App Setup (Android)
First Launch
- Open the app and enter your server URL (e.g.,
https://phone.cloud-hosting.io) - Log in with your WordPress credentials
- Grant permissions when prompted:
- Microphone (required for calls)
- Phone/Call (required for Android Telecom integration)
Phone Account
Android requires a registered and enabled phone account for VoIP apps. The app registers automatically, but enabling must be done manually:
- If prompted, tap "Open Settings" to go to Android's Phone Account settings
- Find "TWP Softphone" in the list and toggle it ON
- Return to the app
If you skipped this step, tap the orange warning card on the dashboard.
Path: Settings → Apps → Default apps → Phone → Calling accounts → TWP Softphone
Making Calls
- Tap the phone FAB (bottom right) to open the dialer
- Enter the phone number
- Caller ID is auto-selected from your Twilio numbers
- Tap Call — the Android system call screen (InCallUI) handles the active call
Receiving Calls
Incoming calls appear via Android's native call UI. Answer/reject using the standard Android interface.
Note: FCM push notifications are required for receiving calls when the app is in the background. This requires
google-services.jsoninandroid/app/.
Queue Management
- View assigned queues on the dashboard
- Tap a queue with waiting calls to see callers
- Tap Accept to take a call from the queue
Agent Status
Toggle between Available, Busy, and Offline using the status bar at the top of the dashboard.
Development
Project Structure
lib/
├── config/ # App configuration
├── models/ # Data models (CallInfo, QueueState, AgentStatus, User)
├── providers/ # State management (AuthProvider, CallProvider, AgentProvider)
├── screens/ # UI screens (Login, Dashboard, Settings, ActiveCall)
├── services/ # API/SDK services (VoiceService, SseService, ApiClient, AuthService)
├── widgets/ # Reusable widgets (Dialpad, QueueCard, AgentStatusToggle)
└── main.dart # App entry point
Running Tests
flutter test
34 tests covering CallInfo, QueueState, and CallProvider.
Building
# Debug APK
flutter build apk --debug
# Release APK (requires signing config)
flutter build apk --release
ADB Deployment (WiFi)
# Connect to device
adb connect DEVICE_IP:PORT
# Install
adb install -r build/app/outputs/flutter-apk/app-debug.apk
# Launch
adb shell am start -n io.cloudhosting.twp.twp_softphone/.MainActivity
# View logs
adb logcat -s flutter
Key Dependencies
| Package | Purpose |
|---|---|
twilio_voice |
Twilio Voice SDK (WebRTC calling) |
provider |
State management |
dio |
HTTP client (REST API, SSE) |
firebase_messaging |
FCM push for incoming calls |
flutter_secure_storage |
Secure token storage |
Troubleshooting
| Problem | Solution |
|---|---|
| Green dot stays red | SSE buffering — see Server Setup |
| "No registered phone account" | Enable phone account in Android Settings (see Phone Account) |
| Calls fail with "Invalid callerId" | Server webhook needs phone number validation — check handle_browser_voice in class-twp-webhooks.php |
| App hangs on login | Check server is reachable: curl https://your-site.com/wp-json/twilio-mobile/v1/auth/login |
| No incoming calls | Ensure FCM is configured (google-services.json) and phone account is enabled |