Your server logs Push "It's your turn": 1 delivered, 0 failed, Firebase agrees, and
the phone shows nothing — because you "closed" the app with adb shell am force-stop,
and Android delivers nothing, push included, to an app in the stopped state.
am force-stop is the Force stop button on the app's settings page. It puts the app
into Android's stopped state, in which the system deliberately withholds every broadcast
— including the one Google Play services uses to hand your
FirebaseMessagingService a message — until the user launches the app again. A user
swiping the app out of Recents does not do that. To test "app closed" the way a patient
closes an app, press Home and then am kill the process.
The error
Real, in order: what the harness did, what the server logged, what the phone showed.
adb shell am force-stop com.cliniclive.pocket
# the server, after reception called next (Firebase accepted the message):
Push "It's your turn": 1 delivered, 0 failed
# the phone's notification shade:
(nothing)
Why it happens
Since Android 3.1, a package that has never been launched or has been force-stopped is "stopped", and implicit broadcasts skip stopped packages by default. That is how Android makes Force stop mean something: an app the user has explicitly killed can't wake itself up through a broadcast receiver. Firebase's delivery to your app is one of those broadcasts, so it is skipped too — even a message with a notification payload, which the system would otherwise display without running your code.
"Delivered" in Firebase's response means the FCM backend accepted the message for that token, not that a notification was shown. The server had done its job, Play services on the phone had received it, and Android had filed it under "the user said no". The harness had redefined a word: "closed", to a patient, is a swipe or a phone that reclaimed memory, and neither leaves the app stopped.
The fix
Simulate a real close: leave the app, end the process, confirm it's gone, then send the push.
adb shell input keyevent KEYCODE_HOME
adb shell am kill com.cliniclive.pocket
adb shell pidof com.cliniclive.pocket # no output = no process; not stopped, just not running
Then call next. A new process id appears for the package — Firebase woke the app — and the tray
shows "It's your turn". Two prerequisites the same part learned: the notification channel must
exist before the push arrives, so the app creates it at startup in
MainActivity rather than on first use; and the manifest names the channel and icon
Android should use when it shows a background message itself. If you ever did force-stop the app,
launching it once by hand clears the stopped state.
What the AI got wrong: for a while this looked like a Firebase problem, a channel problem, a manifest problem. It was a test-harness problem: the command chosen to mean "closed" meant something stricter. "Delivered to Firebase" is not "shown on the phone", and your harness can lie to you about what a word means.
Where it bit us
Season three, Part 6: push, for
real, on the prompt's own acceptance test — "prove it with the app not running". Tag
pocket-06 in the repo has
the channel-at-startup and manifest pieces; the screenshot of the shade with the app not running
is the proof the part shipped. The lesson: prove the thing the user does, not the thing that is
easiest to type.
Frequently asked
- Why does Firebase say the push was delivered but Android shows no notification?
- Delivered means the FCM backend accepted the message for that device token, not that a notification was displayed. If the app was force-stopped, with adb shell am force-stop or the Force stop button in Settings, Android puts it in the stopped state and withholds every broadcast, including Firebase's delivery, until the user launches the app again.
- How do I test Firebase push to a closed Android app with adb?
- Press Home with adb shell input keyevent KEYCODE_HOME, end the process with adb shell am kill followed by the package name, and confirm with adb shell pidof that no process remains. That matches a user swiping the app away or the system reclaiming memory, and the push will wake the app. Do not use am force-stop, which blocks delivery entirely.
- Does swiping an app away in Recents stop Firebase notifications?
- No. Swiping an app out of Recents ends its process but does not put it in the stopped state, so Firebase messages are still delivered and a notification-payload message is shown by the system. Only Force stop, or the app never having been launched, blocks delivery.
More decoded errors in the Fixes category; the season starts at Part 1.