Repository navigation
Conversation
The card was posted by a dataSync foreground service that held the process so status polls and a 20 second redraw kept running. Google Play asks for a declaration and a demo video for that permission. The card is now a plain notification: the running app and Senoti's pushes redraw it, and the existing alarm marks it stale. The manifest no longer asks for FOREGROUND_SERVICE or FOREGROUND_SERVICE_DATA_SYNC. With nothing redrawing the card between updates, a count of the minutes left would go wrong, so the card shows the time the swap should be done by.
n13
left a comment
There was a problem hiding this comment.
Verdict: Approve
Reviewer: GPT-6.1 Sol
Reviewed c819e4186be18d408316b222d90aad07bfd26f9a against base 53f57a96ecd1e154a3b20251de1d2d43100bcc91. No blocking findings.
The direct notification write preserves the existing revision/dismissal checks, stale alarm, ongoing state, completion updates, and explicit cancellation. Both the native FCM receiver and Dart push handler reach this path; no references to the removed foreground service remain. The absolute ETA avoids a frozen countdown, and the payload contract stays compatible with Senoti and iOS. Background freshness depending on pushes is the intended behavior change.
The retained promotion settings match Android's Live Update requirements. The native receiver renders directly from the push payload, consistent with FCM's processing guidance.
Validation:
git diff --check: passed. Read-only Melos formatting: zero changed files, with unresolved dependency warnings.- GitHub CI passed at this exact head, including formatting, analysis, and mobile, SDK, and cold-wallet tests.
- Local locked bootstrap was blocked by installed Flutter 3.44.4 versus pinned 3.47.7; focused Dart tests could not start without resolved dependencies, and workspace analysis was stopped at the 10-second cap. Android unit tests could not start because this clean checkout lacks
gradlew, and no Java runtime is installed. No tracked files were changed.
Device behavior and real FCM delivery were not independently exercised in this review.
|
Closing without merging. Without the service nothing of ours runs between pushes, so the card cannot advance its own countdown or status, and it goes stale after two minutes in the background. We are keeping the foreground service that shipped in build 176 and filing the Play Console foreground service declaration for it instead. The branch stays in case we come back to this. |
Why
Build 176 is blocked in Play Console by the "Foreground service permissions" declaration. The only thing behind it is the swap card: it was posted by a
dataSyncforeground service whose job was to keep the process alive so the app could keep polling and redraw the card every 20 seconds. A notification does not need a service to exist or to be updated, so this drops the service instead of declaring it.What changes
FOREGROUND_SERVICEorFOREGROUND_SERVICE_DATA_SYNC, andSwapLiveActivityServiceis gone. The merged manifest of the build has no foreground service entry left.SwapLiveNotifications.showposts the card withNotificationManager.notify. The card is still ongoing while the swap is moving, and still becomes a Live Update on Android 16 QPR1 and later.Senoti needs no change. It already sends these updates as data-only FCM messages with
android.priority: HIGH(FcmService::send_data, covered bysend_data_is_a_high_priority_data_message_without_a_notification).Behaviour to expect
Why not a ticking countdown
I first built the pill as a native
Chronometercounting down, which ticks with no process. It cannot stop at zero, and the only wake-up available without a service is an inexact alarm. On the emulator that alarm arrived 21 seconds late and the pill read "~−00:21 left" until it did. In Doze it can be minutes.Tested
melos run format,melos run analyze, the swap live activity Dart tests (58 pass), and:app:testDebugUnitTest(30 pass).ONGOING_EVENT|ONLY_ALERT_ONCE|PROMOTED_ONGOING, the app has no running service, and the alarm flips it to the stale layout with the app in the background.swap_live_activitymessage delivered toSwapLivePushReceiverwhile the app is in the background redraws it with the new time, the alarm marks it stale, reopening the app refreshes it, and clearing the swap removes it.Not tested: a physical device, and a real FCM delivery from Senoti (the push was a broadcast to the same receiver).
After this ships
Play Console keeps asking for the declaration while any active release still carries the permission, so the answer for build 176 is still "yes, data sync". Once a build with this change replaces it on every track, the declaration can be switched to "no".