Lightweight, platform-aware reachability / probe checker for Flutter (native + web). Check whether your app can reach the network or a specific service (TCP, TLS, HTTP/GraphQL/SOAP, Web fetch, or a custom native handshake ) with a tiny API and minimal dependencies.
- Why
omni_connectivity - Features
- Install
- Quick start
- Public API
- Probe examples (copy-paste)
- Web considerations & CORS
- Best practices
- Troubleshooting
- Contributing
- License
Many apps need more than a simple "is there any network" boolean. They need to know whether a specific service or protocol is reachable (TCP/TLS endpoint, HTTP/GraphQL endpoint, gRPC service, SOAP Endpoint, WebSocket, or custom native handshake). omni_connectivity is a tiny package designed to:
- Be platform-aware (native vs web).
- Keep dependencies minimal.
- Let you plug custom probes (FFI/MethodChannel/native code) for protocol-specific checks.
- Provide an ergonomic, static API that’s easy for developers to call anywhere.
- Static API:
OmniConnectivity.*— easy to call from app code. - Flexible:
InternetCheckOption.customProbeaccepts anyFuture<bool>probe. strictmode: require all probes to succeed (or default: first success = connected).onStatusChangestream triggered byconnectivity_plusevents (used only as triggers; actual status relies on probes).
Add to your plugin/app pubspec.yaml:
dependencies:
omni_connectivity: ^0.0.2When packaging your plugin, add your omni_connectivity package and export lib/omni_connectivity.dart.
import 'package:flutter/widgets.dart';
import 'package:omni_connectivity/omni_connectivity.dart';
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await OmniConnectivity.init(
options: [
// native-friendly TCP probe (Cloudflare)
InternetCheckOption.fromHostPort('1.1.1.1', 443),
// custom probe (native/FFI/MethodChannel)
InternetCheckOption(
uri: Uri.parse('custom://custom-service'),
customProbe: () => myCustomProbe(),
),
],
checkInterval: Duration(seconds: 8),
strict: false,
);
final ok = await OmniConnectivity.hasInternetAccess();
print('Has internet access: $ok');
OmniConnectivity.onStatusChange.listen((status) {
print('Connectivity changed: $status');
});
}Initialize/override configuration. Optional; if not called, reasonable defaults are used.
options—List<InternetCheckOption>(probes to run).checkInterval—Durationbetween periodic checks.strict—bool(defaultfalse).
Convenience one-liner returning true when at least one probe succeeded (or all succeeded if strict).
Runs the configured probes once and returns InternetStatus.connected or InternetStatus.disconnected.
Subscribe to connectivity state changes.
Change polling interval and reset the timer.
Last known status (or null if no checks have been run).
Represents one probe:
class InternetCheckOption {
final Uri? uri;
final Duration timeout;
final Future<bool> Function()? customProbe;
const InternetCheckOption({ this.uri, this.timeout = const Duration(seconds: 3), this.customProbe });
factory InternetCheckOption.fromHostPort(String host, int port, { Duration timeout = const Duration(seconds: 3) }) => ...;
}fromHostPort(host, port)is a convenience factory for native TCP probes.customProbeaccepts any async function returningbool— ideal for FFI/MethodChannel native handshakes , gRPC health RPCs, or application-layer checks.
import 'dart:io';
Future<bool> tcpProbe(String host, int port, { Duration timeout = const Duration(seconds: 2) }) async {
try {
final socket = await Socket.connect(host, port, timeout: timeout);
socket.destroy();
return true;
} catch (_) {
return false;
}
}import 'dart:io';
Future<bool> tlsProbe(String host, int port, { Duration timeout = const Duration(seconds: 3) }) async {
try {
final socket = await SecureSocket.connect(host, port, timeout: timeout, onBadCertificate: (_) => true);
socket.destroy();
return true;
} catch (_) {
return false;
}
}import 'dart:io';
import 'dart:convert';
Future<bool> httpHeadProbe(Uri uri, { Duration timeout = const Duration(seconds: 3) }) async {
final client = HttpClient();
try {
client.connectionTimeout = timeout;
final req = await client.openUrl('HEAD', uri);
final resp = await req.close().timeout(timeout);
return resp.statusCode >= 200 && resp.statusCode < 400;
} catch (_) {
return false;
} finally {
client.close(force: true);
}
}// implemented inside web impl using package:web + dart:js_interop
Future<bool> fetchHeadProbe(String url, { Duration timeout = const Duration(seconds: 3) });import 'package:grpc/grpc.dart';
Future<bool> grpcProbe(String host, int port, { Duration timeout = const Duration(seconds: 3) }) async {
final channel = ClientChannel(host, port: port, options: const ChannelOptions(credentials: ChannelCredentials.insecure()));
try {
await channel.getConnection().isReady.timeout(timeout);
await channel.shutdown();
return true;
} catch (_) {
try { await channel.shutdown(); } catch (_) {}
return false;
}
}Future<bool> otherProbe() async {
// define any function that returns bool
}- Browser probes use
fetchand are subject to CORS. The server must allow cross-origin HEAD/GET requests for probes to succeed from web builds. dart:iosockets are unavailable on web — web builds must usefetchor a custom web-friendly probe.- Prefer to probe endpoints you control (CORS-enabled) for reliable web behavior.
- Keep probe timeouts short (1–3s) to avoid blocking UI.
- Use TCP/TLS probes for fast reachability checks (native).
- Use
customProbefor app-layer validation or protocol-specific handshakes. - Use
strict = trueonly when all endpoints are under your control. - Allow consumers of your plugin to override default endpoints (don’t hardcode public IPs as single source of truth).
- Web probes fail with CORS errors — ensure the endpoint returns
Access-Control-Allow-Origin: *(or your origin) and allows HEAD/GET. - Probe flaky on some networks — corporate or captive networks may block public DNS or certain IPs. Make endpoints configurable and prefer application-layer health endpoints you control.
Contributions welcome!
Please open issues or PRs. Follow the existing style and add tests for new behaviors.
If you liked the package, then please give it a Like 👍🏼 and Star ⭐ on GitHub.
omni_connectivity is meant to be a small, focused plugin: a developer-friendly, cross-platform probe abstraction. It keeps the core dependency-free for protocol-specific checks and lets apps plug in the exact probe they need (TCP, HTTP, gRPC, any binary protocol you made).
