**Major Features Added:** - **Inline Reply System**: Replace compose screen with inline reply boxes - **Thread Navigation**: Parent/child navigation with jump functionality - **Chain Flow UI**: Reply counts, expand/collapse animations, visual hierarchy - **Enhanced Animations**: Smooth transitions, hover effects, micro-interactions **Frontend Changes:** - **ThreadedCommentWidget**: Complete rewrite with animations and navigation - **ThreadNode Model**: Added parent references and descendant counting - **ThreadedConversationScreen**: Integrated navigation handlers - **PostDetailScreen**: Replaced with threaded conversation view - **ComposeScreen**: Added reply indicators and context - **PostActions**: Fixed visibility checks for chain buttons **Backend Changes:** - **API Route**: Added /posts/:id/thread endpoint - **Post Repository**: Include allow_chain and visibility fields in feed - **Thread Handler**: Support for fetching post chains **UI/UX Improvements:** - **Reply Context**: Clear indication when replying to specific posts - **Character Counting**: 500 character limit with live counter - **Visual Hierarchy**: Depth-based indentation and styling - **Smooth Animations**: SizeTransition, FadeTransition, hover states - **Chain Navigation**: Parent/child buttons with visual feedback **Technical Enhancements:** - **Animation Controllers**: Proper lifecycle management - **State Management**: Clean separation of concerns - **Navigation Callbacks**: Reusable navigation system - **Error Handling**: Graceful fallbacks and user feedback This creates a Reddit-style threaded conversation experience with smooth animations, inline replies, and intuitive navigation between posts in a chain.
9.2 KiB
Android FCM Notifications - Troubleshooting Guide
Issue: Chat notifications work on Web but not Android
Current Status
- ✅ Web notifications working
- ✅ Android has
google-services.jsonconfigured - ✅ Android has FCM plugin in
build.gradle.kts - ✅ Android has notification permissions in
AndroidManifest.xml - ❓ Android FCM token registration status unknown
Diagnostic Steps
Step 1: Check Android Logs for FCM Token
Run the Android app with logging:
cd c:\Webs\Sojorn
.\run_dev.ps1
In Android Studio or terminal, check logcat:
adb logcat | findstr "FCM"
Look for these log messages:
[FCM] Initializing for platform: android
[FCM] Permission status: AuthorizationStatus.authorized
[FCM] Requesting token...
[FCM] Token registered (android): eXaMpLe...
[FCM] Syncing token with backend...
[FCM] Token synced with Go Backend successfully
[FCM] Initialization complete
Step 2: Check for Common Errors
Error: "Token is null after getToken()"
Cause: Firebase not properly initialized or google-services.json mismatch
Fix:
- Verify
google-services.jsonpackage name matches:"package_name": "com.gosojorn.app" - Check
build.gradle.ktshas:applicationId = "com.gosojorn.app" - Rebuild:
flutter clean && flutter pub get && flutter run
Error: "Permission denied"
Cause: User denied notification permission or Android 13+ permission not requested
Fix:
- Check
AndroidManifest.xmlhas:<uses-permission android:name="android.permission.POST_NOTIFICATIONS" /> - On Android 13+, permission must be requested at runtime
- Uninstall and reinstall app to re-trigger permission prompt
Error: "Failed to initialize notifications"
Cause: Firebase plugin not properly initialized
Fix:
- Check
android/build.gradle(project level) has:dependencies { classpath 'com.google.gms:google-services:4.4.0' } - Check
android/app/build.gradle.ktshas:plugins { id("com.google.gms.google-services") }
Step 3: Verify Backend Receives Token
Check Database for Android Tokens
SSH to server:
ssh -i "C:\Users\Patrick\.ssh\mpls.pem" patrick@194.238.28.122
Query database:
sudo -u postgres psql sojorn
-- Check for Android tokens
SELECT
user_id,
platform,
LEFT(fcm_token, 30) as token_preview,
created_at
FROM public.fcm_tokens
WHERE platform = 'android'
ORDER BY created_at DESC
LIMIT 5;
Expected output:
user_id | platform | token_preview | created_at
-------------------------------------+----------+--------------------------------+-------------------
5568b545-5215-4734-875f-84b3106cd170 | android | eXaMpLe_android_token_here... | 2026-01-29 06:00
If no Android tokens:
- Token registration failed
- Token sync to backend failed
- Check Android logs for errors
Step 4: Test Push Notification Manually
Send Test Notification from Server
# Get an Android FCM token from database
sudo -u postgres psql sojorn -c "SELECT fcm_token FROM public.fcm_tokens WHERE platform = 'android' LIMIT 1;"
The Go backend automatically sends notifications when:
- Someone sends you a chat message
- Someone follows you
- Someone accepts your follow request
Test by sending a chat message:
- Open app on Android device
- Have another user (or web browser) send you a message
- Check Android logs for:
[FCM] Foreground message received
Step 5: Check Notification Channel (Android 8+)
Android 8+ requires notification channels. Check strings.xml:
File: android/app/src/main/res/values/strings.xml
<resources>
<string name="default_notification_channel_id">chat_messages</string>
<string name="default_notification_channel_name">Chat messages</string>
</resources>
Referenced in AndroidManifest.xml:
<meta-data
android:name="com.google.firebase.messaging.default_notification_channel_id"
android:value="@string/default_notification_channel_id" />
Common Issues & Solutions
Issue 1: "google-services.json not found"
Symptoms:
- Build fails with "File google-services.json is missing"
- FCM token is null
Solution:
# Verify file exists
ls sojorn_app/android/app/google-services.json
# If missing, download from Firebase Console:
# https://console.firebase.google.com/project/sojorn-a7a78/settings/general
# Click "Add app" > Android > Download google-services.json
Issue 2: Package name mismatch
Symptoms:
- FCM token is null
- No errors in logs
Solution: Verify all package names match:
google-services.json:"package_name": "com.gosojorn.app"build.gradle.kts:applicationId = "com.gosojorn.app"AndroidManifest.xml:<manifest xmlns:android="...">(no package attribute needed)
Issue 3: Notification permission not granted
Symptoms:
- Log shows:
[FCM] Permission status: AuthorizationStatus.denied - No token generated
Solution:
# Uninstall app
adb uninstall com.gosojorn.app
# Reinstall and allow notification permission when prompted
flutter run
Issue 4: Token generated but not synced to backend
Symptoms:
- Log shows:
[FCM] Token registered (android): ... - Log shows:
[FCM] Sync failed: ... - No token in database
Solution: Check API endpoint exists:
# On server
sudo journalctl -u sojorn-api -f | grep "notifications/device"
Verify Go backend has the endpoint:
// Should be in cmd/api/main.go
authorized.POST("/notifications/device", settingsHandler.RegisterFCMToken)
Comparison: Web vs Android
Web (Working ✅)
- Uses VAPID key for authentication
- Service worker handles background messages
- Token format:
d2n2ELGKel7yzPL3wZLGSe:APA91b...
Android (Troubleshooting ❓)
- Uses
google-services.jsonfor authentication - Native Android handles background messages
- Token format: Different from web, longer
- Requires runtime permission on Android 13+
Debug Checklist
Run through this checklist:
google-services.jsonexists inandroid/app/- Package name matches in all files
build.gradle.ktshasgoogle-servicespluginAndroidManifest.xmlhasPOST_NOTIFICATIONSpermission- App has notification permission granted
- Android logs show FCM initialization
- Android logs show token generated
- Token appears in database
fcm_tokenstable - Backend logs show notification being sent
- Android logs show notification received
Next Steps
-
Run the app with enhanced logging:
cd c:\Webs\Sojorn .\run_dev.ps1 -
Monitor Android logs:
adb logcat | findstr "FCM" -
Look for the specific log messages:
[FCM] Initializing for platform: android[FCM] Token registered (android): ...[FCM] Token synced with Go Backend successfully
-
If token is null:
- Check
google-services.jsonis correct - Verify package name matches
- Rebuild:
flutter clean && flutter pub get && flutter run
- Check
-
If token generated but notifications not received:
- Check database has the token
- Send a test message
- Check backend logs for push notification being sent
- Verify Android device has internet connection
Files to Check
Android Configuration
sojorn_app/android/app/google-services.json- Firebase configsojorn_app/android/app/build.gradle.kts- Build configurationsojorn_app/android/app/src/main/AndroidManifest.xml- Permissionssojorn_app/android/app/src/main/res/values/strings.xml- Notification channel
Flutter Code
sojorn_app/lib/services/notification_service.dart- FCM initialization (now with enhanced logging)sojorn_app/lib/main.dart- App initialization
Backend
go-backend/internal/services/push_service.go- Push notification sendergo-backend/internal/handlers/settings_handler.go- FCM token registration endpoint
Quick Commands
# Check Android logs
adb logcat | findstr "FCM"
# Check if app is installed
adb shell pm list packages | findstr gosojorn
# Uninstall app
adb uninstall com.gosojorn.app
# Check notification settings
adb shell dumpsys notification | findstr gosojorn
# Check database for tokens
ssh -i "C:\Users\Patrick\.ssh\mpls.pem" patrick@194.238.28.122
sudo -u postgres psql sojorn -c "SELECT platform, COUNT(*) FROM fcm_tokens GROUP BY platform;"
Expected Behavior
When working correctly:
- App starts →
[FCM] Initializing for platform: android - Permission requested → User grants →
[FCM] Permission status: AuthorizationStatus.authorized - Token generated →
[FCM] Token registered (android): eXaMpLe... - Token synced →
[FCM] Token synced with Go Backend successfully - Message sent → Backend sends push →
[FCM] Foreground message received - Notification appears in Android notification tray
Contact & Support
If issues persist after following this guide:
- Share Android logcat output (filtered for FCM)
- Share database query results for
fcm_tokenstable - Share backend logs when sending notification
- Verify Firebase Console shows Android app is active