Remove the remaining CONNECTIVITY_ACTION broadcast receivers - #23271
Open
nbradbury wants to merge 3 commits into
Open
Remove the remaining CONNECTIVITY_ACTION broadcast receivers#23271nbradbury wants to merge 3 commits into
nbradbury wants to merge 3 commits into
Conversation
Removes the second CONNECTIVITY_ACTION BroadcastReceiver, left behind when #23140 migrated the app's other connectivity listener to a ConnectivityManager.NetworkCallback. ConnectionStatusLiveData registered its own receiver in onActive/onInactive and read the deprecated activeNetworkInfo on the main thread in onReceive. It is now a MediatorLiveData over NetworkConnectionMonitor.isConnected. The public ConnectionStatus enum is unchanged, so UploadStarter, PostListViewModel, HistoryViewModel and WPWebViewViewModel are untouched. The monitor is a process-lifetime singleton that holds the current state, and LiveData replays its value to every new observer, so a direct swap would have re-run each observer's side effect (loadIfNecessary, fetchRevisions, retryOnConnectionAvailableAfterRefreshError) on every subscribe. The new class seeds a baseline from the source's value at construction and only emits on an actual change, which matches the old contract: under both implementations the first genuine connectivity change is the one UploadStarter's skip(1) swallows. Note this is not an ANR fix. The receiver was ProcessLifecycleOwner-scoped and mostly unregistered while backgrounded; the background ANRs in CMM-2174 come from Application.onCreate work on background process starts.
Removes the last CONNECTIVITY_ACTION BroadcastReceiver. MediaBrowserActivity registered one in onStart and unregistered it in onStop to resume pending media deletes when the connection returned; it now injects LiveData<ConnectionStatus> and observes it instead, so all connectivity listening goes through NetworkConnectionMonitor's NetworkCallback. observe(this, ...) is active between onStart and onStop, so the scoping is unchanged - it just isn't hand-rolled any more. Two small behaviour changes: - The old onReceive ran on any connectivity broadcast, including disconnects, despite its "Coming from zero connection" comment. The observer only acts on AVAILABLE, which is what the comment intended. startMediaDeleteService already returns early when the network is unavailable, so the disconnect-triggered calls only logged. - If the connection is restored while the Activity is stopped, the observer now fires on return to STARTED rather than missing the change entirely. onResume already called startMediaDeleteService unconditionally, so this only widens an existing path.
Collaborator
Generated by 🚫 Danger |
Contributor
|
|
Contributor
|
|
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## trunk #23271 +/- ##
==========================================
- Coverage 37.80% 37.80% -0.01%
==========================================
Files 2348 2348
Lines 128445 128441 -4
Branches 17805 17807 +2
==========================================
- Hits 48560 48558 -2
Misses 75925 75925
+ Partials 3960 3958 -2 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
A NetworkCallback only reports networks as they appear, so on a device that starts with no connectivity nothing is ever delivered and isConnected stayed null - indistinguishable from "offline" to observers. That broke UploadStarter. CONNECTIVITY_ACTION was a sticky broadcast, so registering the old receiver delivered the current state immediately, and that is what UploadStarter's skip(1) was written to absorb. With the receiver gone and no seeded value, the first reconnect after an offline launch became ConnectionStatusLiveData's first emission, skip(1) swallowed it, and queueUploadFromAllSites() never ran - leaving local drafts unuploaded until the next background/foreground cycle. start() now publishes the current ConnectivityManager state before registering the callback, routed through onConnectivityChanged so the existing de-dupe still applies: a seeded false followed by a network is a genuine change, while a seeded true followed by onAvailable for that same network is not. onConnectivityChanged becomes @VisibleForTesting internal so the seeded paths can be covered without the framework wiring in start().
nbradbury
marked this pull request as ready for review
August 28, 2026 18:04
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.


TL/DR
Removes the last two deprecated
CONNECTIVITY_ACTIONBroadcastReceiversin the app. All connectivity listening now goes throughNetworkConnectionMonitor'sConnectivityManager.NetworkCallback, finishing the migration #23140 started.Note that this a tech debt PR only - this fixes no known bugs and there are no user-facing changes.
Description
#23140 replaced the app's main connectivity receiver with a
NetworkCallbackbut left two behind:ConnectionStatusLiveDataregistered one inonActive/onInactiveand read the deprecatedactiveNetworkInfoon the main thread, andMediaBrowserActivityregistered its own inonStart/onStopto resume pending media deletes.ConnectionStatusLiveDatais now aMediatorLiveDataoverNetworkConnectionMonitor.isConnected, andMediaBrowserActivityinjects and observes it. The publicConnectionStatusenum is unchanged, soUploadStarter,PostListViewModel,HistoryViewModelandWPWebViewViewModelare untouched.NetworkConnectionMonitornow seedsisConnectedwith the currentConnectivityManagerstate instart(). ANetworkCallbackonly reports networks as they appear, so on a device that starts offline nothing is ever delivered andisConnectedstayed null — indistinguishable from "offline", and it made the first reconnect look like an initial value rather than a change.CONNECTIVITY_ACTIONwas a sticky broadcast that delivered the current state at registration, so this restores the behaviour the receivers relied on. Without it,UploadStarter'sskip(1)(UploadStarter.kt:100) would swallow the first reconnect after an offline launch and local drafts would sit unuploaded.One subtlety worth a reviewer's eye: the monitor is a process-lifetime singleton that holds state, and LiveData replays its value to every new observer — so a direct swap would re-run each observer's side effect (
loadIfNecessary,fetchRevisions,retryOnConnectionAvailableAfterRefreshError) on every subscribe.ConnectionStatusLiveDatatherefore seeds a baseline at construction and only emits on an actual change, which matches the old contract.The
MediaBrowserActivityhalf turns out to be a no-op in practice. Its observer only callsstartMediaDeleteServicewhenhasSiteMediaToDeleteis true, which needs media inDELETINGstate; onlydeleteMediasets that, anddeleteMediais reachable only from the grid trash button, which is shown only forFAILED/QUEUEDitems — exactly the statesdeleteMediaroutes tonewRemoveMediaActioninstead. So the guarded branch is unreachable, and this is kept as a like-for-like migration. Removing the dead path is a reasonable follow-up; the file already carries a TODO about the same drift atMediaBrowserActivity:876.Note this is not an ANR fix. Both receivers were lifecycle-scoped and unregistered while backgrounded — the background ANRs in CMM-2174 come from
Application.onCreatework on background process starts.Testing instructions
Editor offline banner:
Media library still opens: