Repository navigation
Conversation
getStatus() returned the flags stored by the last reachability callback and only read them synchronously when they were nil, so a call made right after a network change could return the previous state.
…e events - Build the status from the NetworkCapabilities passed to onCapabilitiesChanged instead of re-querying the active network inside the callback. - Ignore onLost for a network that is no longer the default. - Only emit networkStatusChange when connected or connectionType changes. - Register the callback at load so events arrive before the first resume. - Make register/unregister no-ops when already in that state.
kcjonson
marked this pull request as ready for review
October 22, 2026 22:48
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.
Description
iOS:
getStatus()now reads the reachability flags synchronously instead of returning the value stored by the last callback. The SCNetworkReachability implementation stays; moving toNWPathMonitorbelongs with #2555, which already adds one.Android:
onCapabilitiesChangedbuilds the status from theNetworkCapabilitiesit's given instead of re-queryinggetActiveNetwork()/getNetworkCapabilities().onAvailableonly reads capabilities itself on API 24-25, whereonCapabilitiesChangedisn't guaranteed to follow.onLostfor a network that's no longer the default is ignored.networkStatusChangeis only emitted whenconnectedorconnectionTypechanges, so signal strength / bandwidth updates and the callback delivered on every re-registration no longer produce duplicate events.load(), so events arrive before the first resume. Pause/resume still unregister/re-register, and both are now no-ops when already in that state, sounregisterNetworkCallbackcan't throw when nothing is registered. Losing the connection while paused is still reported on resume (fix(network): fire networkStatusChanged if network lost while app paused #1655).getStatus()still queries the active network, andconnectedis stillVALIDATED && INTERNET. No public API changes.Change Type
Rationale / Problems Fixed
Closes #2620
Closes #2621
On iOS,
getStatus()only re-read the flags when they were nil, so a call right after a network change returned the previous state until the next callback landed.On Android, the
ConnectivityManager.NetworkCallbackreference warns against calling synchronousConnectivityManagermethods from inside a callback, since the answer can already be out of sync with the callback; the arguments are the source of truth. The plugin did exactly that, and also emitted on every capability change, which is the long-standing duplicate-event report (ionic-team/capacitor#1492, #1014, #2138).Tests or Reproductions
What ran, locally on macOS against @capacitor/core/ios/android 8.5.3:
npm run verify:ios(xcodebuild build -scheme CapacitorNetwork -destination generic/platform=iOS, Xcode 27.1): build succeeded.npm run verify:android(gradlew clean build testafternpm run set-settings-gradle-for-monorepo, JDK 21): build, lint, and unit tests passed. The only unit test in the module is the placeholderExampleUnitTest, so this proves it compiles and lints, not the behavior.npm run build(docgen, tsc, rollup): passed, README unchanged.npm run lint: eslint and prettier clean; swiftlint reports the same two existing warnings in Reachability.swift as main, nothing new.Not run: the iOS XCTest target, and nothing on a simulator, emulator, or device. The repro steps in #2620 and #2621 need no sample app.
Screenshots / Media
Platforms Affected
Notes / Comments
Captive-portal / limited-connectivity reporting is left to #2564 and constrained/expensive exposure to #2555; this only fixes the existing fields.
#2606 also changes
handleOnResume/handleOnPauseinNetworkPlugin.java(moving theConnectivityManagercalls off the main thread), so the two will conflict there. This PR leavesgetNetworkStatus()as it is on main to keep the overlap to that one file. It also removes thegetNetworkStatus()call fromhandleOnPause, which is one of the main-thread binder calls #2563 is about.