connectivity_watcher

pub package pub points License: MIT

A lightning-fast Flutter plugin for true internet connectivity monitoring and connection mode detection. Most connectivity packages only check if the device's Wi-Fi or Mobile radio is "on." ZoConnectivityWatcher goes further by combining OS-level hardware detection (via connectivity_plus) with active reachability probes. It tells you the exact Connection Mode (Wi-Fi, Mobile Data, Ethernet, VPN, etc.) and detects "Liar Wi-Fi" (connected to a router but no data flow) in sub-second time without flooding Flutter DevTools.

network

๐Ÿง‘โ€๐Ÿ’ป Getting Started

1. Install the package

dependencies:
  flutter:
    sdk: flutter
  connectivity_watcher: ^[latest_version]

2. Import it

import 'package:connectivity_watcher/connectivity_watcher.dart';

3. Initialize it in main.dart

Basic Setup

Initialize the watcher in your main.dart. By default, it uses DNS socket checks (Google/Cloudflare) to verify connectivity.

WidgetsFlutterBinding.ensureInitialized();
ZoConnectivityWatcher().setUp(
  checkInterval: Duration(seconds: 1)
  );

๐Ÿ”Œ Basic Usage

Custom UI SnackBar Style Alert Dialog
Custom SnackBar Alert

Wrap Your App

Use ZoConnectivityWrapper at the root of your app to monitor connection changes:

ZoConnectivityWrapper(
  connectivityStyle: NoConnectivityStyle.SNACKBAR,
  builder: (context, connectionKey) {
    return MaterialApp(
      navigatorKey: connectionKey,
      home: LoginDemo(),
    );
  },
);

Use Prebuilt UI Styles

Snackbar Style

connectivityStyle: NoConnectivityStyle.SNACKBAR,

Alert Dialog Style

connectivityStyle: NoConnectivityStyle.ALERT,

๐Ÿงฉ Custom Offline Widget

Want to show your own offline UI? Use NoConnectivityStyle.CUSTOM:

ZoConnectivityWrapper(
  connectivityStyle: NoConnectivityStyle.CUSTOM,
  offlineWidget: CustomNoInternetWrapper(
    builder: (context) => CustomNoInternet(),
  ),
  builder: (context, connectionKey) => MaterialApp(
    navigatorKey: connectionKey,
    home: LoginDemo(),
  ),
);

The widget is auto-removed once the internet is back. You can also remove it manually:

bool removed = await ZoConnectivityWatcher().hideNoInternet();
if (!removed) {
  print("Still no internet");
}

๐Ÿ” API Call with Retry

Automatically retries failed API calls after connectivity is restored:

ZoConnectivityWatcher().makeApiCallWithRetry(
  maxRetries: 2,
  delay: const Duration(seconds: 1),
  apiCall: () async {
    final dio = Dio();
    dio.interceptors.add(CurlInterceptor());

    final response = await dio.post(
      "https://jsonplaceholder.typicode.com/posts",
      data: {
        "title": 'foo',
        "body": 'bar',
        "userId": 1,
      },
    );
  },
);

๐ŸŒ Check Internet Manually

bool hasInternet = await ZoConnectivityWatcher().isInternetAvailable;

๐Ÿง  Network-Aware Widgets

Use ZoNetworkAwareWidget to render UI dynamically based on real-time internet status and connection mode:

ZoNetworkAwareWidget(
  builder: (context, status, ConnectionMode mode) {
    if (status == ConnectivityWatcherStatus.disconnected) {
      return const Text('Offline', style: TextStyle(color: Colors.red));
    }
    return Text(
      'Online via ${mode.label}', // e.g. "Online via Wi-Fi" or "Online via Mobile Data"
      style: const TextStyle(color: Colors.green),
    );
  },
);

Connection Mode Detection

Know exactly where your user's internet is coming from (Wi-Fi, Mobile Data, Ethernet, VPN, etc.) so you can optimize data-heavy tasks like video streaming or background file sync:

1. Get Connection Mode Directly

// Asynchronous real-time hardware query
ConnectionMode mode = await ZoConnectivityWatcher().getConnectionMode();

print(mode.label);    // "Wi-Fi", "Mobile Data", "Ethernet", "VPN", etc.
print(mode.isWifi);   // true / false
print(mode.isMobile); // true / false
print(mode.isVpn);    // true / false

// Instant synchronous access
ConnectionMode currentMode = ZoConnectivityWatcher().getCurrentConnectionMode();
// or: ZoConnectivityWatcher().connectionMode;

2. Listen to Mode Changes in Real-Time

// Emits only when the network interface switches (e.g. Wi-Fi -> Mobile Data)
ZoConnectivityWatcher().connectionModeStream.listen((ConnectionMode mode) {
  print("Switched to: ${mode.label}");
});

// Unified stream emitting both connectivity status and connection mode
ZoConnectivityWatcher().eventStream.listen((ConnectivityWatcherEvent event) {
  print("Status: ${event.status}");                 // connected / disconnected
  print("Mode: ${event.mode.label}");               // "Wi-Fi", "Mobile Data"
  print("Active Interfaces: ${event.activeModes}"); // e.g. [wifi, vpn]
  print("Timestamp: ${event.timestamp}");
});

3. Make API Calls with Mode Awareness

ZoConnectivityWatcher().makeApiCall(
  apiCall: (bool isConnected, ConnectionMode mode) {
    if (isConnected && mode.isWifi) {
      // Perform large file sync on unmetered Wi-Fi
    }
  },
);

๐Ÿงช Curl Logging for Dio

Log API requests as curl commands in your console:

final dio = Dio();
dio.interceptors.add(CurlInterceptor());

๐Ÿ”Ž In-App Network Inspector (Beta)

Monitor all HTTP traffic directly inside your app, similar to the Chrome Network Tab. You can view status codes, active connection mode (Wi-Fi, Mobile Data, etc.), request/response bodies, headers, and easily copy cURL commands.

1. Attach the Logger

Add the NetworkLoggerInterceptor to your Dio client to start tracking:

final dio = Dio();
ZoConnectivityWatcher().setupDioLogger(dio);

2. Open the Inspector

Open the UI from anywhere in your app to view the logs:

ZoConnectivityWatcher().showNetworkLogsScreen(context);

3. Manage Logs Programmatically

You can also access or clear the logs in code:

// Get all logs
final logs = ZoConnectivityWatcher().getNetworkLogs();

// Clear logs
ZoNetworkLogManager.instance.clearLogs();

โšก Ping System

Measure exact round-trip latency to servers in real-time and display it in your app, similar to AAA gaming titles (e.g. PUBG, Valorant). It uses ultra-lightweight stealth DNS resolution with automatic multi-host failover across major global networks (google.com, apple.com, microsoft.com, cloudflare.com). It never gets blocked by corporate firewalls and never floods your Flutter DevTools Network tab.

1. Initialize the Ping Service

Start the service in your initialization block. You can ping your own API or backend server, or leave it blank to automatically failover across globally whitelisted major backbones:

// Defaults to multi-host failover across Google, Apple, Microsoft & Cloudflare
ZoConnectivityWatcher().initPingService();

// Or measure latency to your own corporate server / API:
ZoConnectivityWatcher().initPingService(
  targetHosts: ['api.yourdomain.com', 'google.com'],
  interval: const Duration(seconds: 2),
);

2. Display the Ping Widget

Add the ZoPingWidget anywhere in your UI. It automatically updates and color-codes the ping in milliseconds (Green for <100ms, Orange for <200ms, Red for >200ms):

AppBar(
  actions: [
    ZoPingWidget(
      goodPingThreshold: 100,
      mediumPingThreshold: 200,
    ),
  ],
)

๐Ÿ› ๏ธ Feature Requests & Bugs

Have an idea or found a bug? Open an issue on GitHub.


๐Ÿ“ฆ More From Me