Skip to main content

rx_connectivity_checker 2.0.0 copy "rx_connectivity_checker: ^2.0.0" to clipboard
rx_connectivity_checker: ^2.0.0 copied to clipboard

A robust, reactive Dart/Flutter package for monitoring network connectivity.

rx_connectivity_checker #

Pub Version License Platforms Pub Points

A robust, reactive, and high-performance federated Flutter library for monitoring network connectivity.

Beyond monitoring local connection states, this library verifies end-to-end internet access through active network probes. Validation is triggered by three distinct events:

  • Platform Change Events — when the system reports that the network is gone (e.g. Wi-Fi and mobile data turned off), offline is emitted instantly, without a probe. When a network becomes available or changes, a probe fires immediately; if it fails, follow-up probes run on a short back-off (250 ms, 500 ms, 1 s, 2 s, 4 s by default, configurable via recheckDelays) until the network is reachable — a link that has just come up often cannot carry traffic yet.
  • Periodic Polling — automated checks run every checkFrequency while online, to catch "silent" losses (e.g. a router losing its uplink while Wi-Fi remains connected), and every offlineCheckFrequency (5 s by default) while not online, to catch reconnections the platform does not report (e.g. the iOS Simulator). Polling pauses while the app is hidden and resumes with an immediate check when it becomes visible again.
  • Manual Triggers — checkConnectivity() runs a fresh probe right away, always emits its result and restarts the periodic timer.

Features #

  • Federated Architecture — native implementations for Android, iOS, macOS, Windows, and Linux.
  • True Reachability — distinguishes between "connected to a network" and "having internet access."
  • Performance Optimised — periodic probes are skipped while another probe is in flight, and results made stale by a newer network change are discarded.
  • Modern Web Support — WASM-ready using package:web and dart:js_interop with intelligent CORS-aware probes.
  • Energy Efficient — leverages native system observers (NWPathMonitor, ConnectivityManager, DBus, NLM) to trigger checks only when necessary.
  • Shared, Restartable Stream — one checker can back the whole app session or only some screens: monitoring starts with the first listener, stops with the last, restarts when a screen listens again, and new listeners immediately receive the last known status.
  • Zombie-Connection Detection — periodic background checks catch cases where a device is locally connected but has no actual internet access.
  • Manual Check Support — checkConnectivity() always runs a fresh, unthrottled check, always emits its result and restarts the periodic timer.
  • Testing Friendly — full dependency injection via IHttpClient and ReachabilityValidator eliminates the need for real network access in tests.

Installation #

Requires Flutter 3.44 or later. Add rx_connectivity_checker to your pubspec.yaml:

dependencies:
  rx_connectivity_checker: ^2.0.0

Then run:

flutter pub get

Usage #

Basic setup #

Initialise the checker with a reliable endpoint. Google's generate_204 is the default — it is fast, lightweight, and returns no body.

final connectivityChecker = ConnectivityChecker(
  url: 'https://connectivitycheck.gstatic.com/generate_204',
  checkFrequency: const Duration(seconds: 30),
  checkSlowConnection: true, // successful responses slower than slowConnectionThreshold report `slow`
  slowConnectionThreshold: const Duration(seconds: 3),
);

Reactive UI updates #

Use connectivityStream to rebuild your UI whenever the network state changes. A new listener immediately receives the last known status (ConnectivityStatus.unknown before the first check completes); after that the stream emits when the status changes, and for every checkConnectivity() result.

StreamBuilder<ConnectivityStatus>(
  stream: connectivityChecker.connectivityStream,
  initialData: ConnectivityStatus.unknown,
  builder: (context, snapshot) {
    final status = snapshot.data ?? ConnectivityStatus.unknown;
    return Column(
      children: [
        Icon(
          status == ConnectivityStatus.online ? Icons.wifi : Icons.wifi_off,
          color: status == ConnectivityStatus.online ? Colors.green : Colors.red,
        ),
        Text('Status: ${status.name}'),
      ],
    );
  },
)

Sharing one checker across the app or across screens #

Create a single ConnectivityChecker (e.g. in your dependency-injection setup) and listen to the same connectivityStream wherever you need it:

  • Whole app session — keep one long-lived listener (e.g. at the app root). Monitoring runs for the entire session, pausing periodic checks while the app is hidden.
  • Only some screens — listen from those screens only. Monitoring stops when the last screen stops listening and restarts, with the last known status replayed, when another screen listens.

Manual one-off checks #

For critical actions (like submitting a form), perform an immediate check. Every call runs a fresh probe — it never reuses an older in-flight one — completes within timeout, emits its result on connectivityStream (even when the status is unchanged) and restarts the periodic timer.

final status = await connectivityChecker.checkConnectivity();
if (status == ConnectivityStatus.online) {
  await apiService.uploadData();
}

Dependency injection (testing) #

ConnectivityChecker accepts an IHttpClient so you can swap in a mock during tests:

class MockHttpClient implements IHttpClient {
  @override
  Future<http.Response> get(Uri url, {Map<String, String>? headers}) async {
    return http.Response('', 204);
  }
}

final checker = ConnectivityChecker(client: MockHttpClient());

ConnectivityStatus #

Value Meaning
online Remote endpoint responded with a 2xx status code.
offline Endpoint unreachable, no response within timeout, or a non-2xx response.
slow A 2xx response that took longer than slowConnectionThreshold, with checkSlowConnection set to true.
unknown Initial state before the first check completes.

Platform-specific behaviour #

Slow vs. offline: a request that gets no response within timeout is always offline, on every platform — a network without internet access (for example an emulator whose Wi-Fi has no upstream) makes requests hang rather than fail. slow is reserved for connections that work but respond slower than slowConnectionThreshold; keep the threshold below timeout, otherwise slow can never occur.

Web limitation: The web implementation uses the browser's native fetch() API. IHttpClient injection and custom headers are not supported on web — passing either has no effect. Use a native platform build if you need header or client injection.


Platform support & native mechanisms #

Platform Mechanism Details
Android ConnectivityManager Follows the system default network via registerDefaultNetworkCallback.
iOS / macOS NWPathMonitor Native Swift implementation with event deduplication.
Linux D-Bus / NetworkManager Subscribes to StateChanged signals on the system bus.
Windows INetworkListManager C++ COM interop for high-performance desktop tracking.
Web fetch API Uses cors mode; a CORS rejection is treated as reachable since the server responded.

Platform setup #

Android #

Add the following permissions to android/app/src/main/AndroidManifest.xml:

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

iOS / macOS #

The plugin supports both Swift Package Manager and CocoaPods — no extra setup is needed for either.

No additional permissions are required for iOS.

For macOS, enable the network client entitlement in both macos/Runner/DebugProfile.entitlements and macos/Runner/Release.entitlements:

<key>com.apple.security.network.client</key>
<true/>

Windows #

The Windows implementation uses COM interop. No manifest changes are required for standard Win32 apps. For MSIX / packaged apps, declare the internetClient capability in Package.appxmanifest:

<Capability Name="internetClient" />

Ensure your build environment targets C++20 or later (required by the plugin's CMakeLists.txt).

Linux #

The Linux implementation communicates with NetworkManager via D-Bus. Most modern distributions (Ubuntu, Fedora, etc.) ship NetworkManager by default — no additional setup is required.

Web (CORS) #

The web implementation uses mode: cors. If the fetch succeeds the endpoint is reachable. If the server responds with a CORS rejection (e.g. TypeError), the browser still contacted the server — the validator treats this as online. A true network failure (DNS error, no route) sets navigator.onLine to false and is correctly reported as offline.


Example #

A complete, runnable example is in the example/ directory. It demonstrates:

  • implementing a global connectivity listener
  • handling ConnectivityStatus.slow states
  • using manual triggers before form submissions
cd example
flutter run

Contributing #

Contributions are welcome. For bugs or feature requests, please file them on the GitHub Issue Tracker.

2
likes
150
points
81
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

A robust, reactive Dart/Flutter package for monitoring network connectivity.

Repository (GitHub)
View/report issues

License

MIT (license)

Dependencies

dbus, flutter, flutter_web_plugins, http, integration_test, plugin_platform_interface, rxdart, web

More

Packages that depend on rx_connectivity_checker

Packages that implement rx_connectivity_checker