Keywords: Flutter | Internet Connectivity Detection | connectivity plugin | Dart Network Programming | Mobile App Development
Abstract: This article provides an in-depth exploration of comprehensive solutions for detecting internet connectivity in Flutter applications. By analyzing the limitations of the connectivity plugin, it presents reliable detection methods based on InternetAddress.lookup(), and details both one-time checking and continuous monitoring implementations. The article includes complete code examples and best practice recommendations to help developers build robust network connectivity detection features.
Problem Background and Challenges
In mobile application development, network connectivity detection is a fundamental yet crucial functionality. Many developers initially attempt to use the connectivity plugin to check network status, but this approach has significant limitations. The connectivity plugin can only detect whether the device is connected to a network (such as Wi-Fi or mobile data), but cannot confirm whether that network actually provides internet access. This can lead to false positives in many practical scenarios, such as when devices connect to public Wi-Fi requiring authentication, VPN networks, or environments with extremely poor network quality.
Core Solution
To accurately detect internet connectivity status, the most reliable method is to actually attempt to access a reliable internet address. The Dart language provides the InternetAddress.lookup() method, which attempts to resolve a specified domain name and return the corresponding IP address. If the resolution succeeds, it indicates that the device can indeed access the internet; if the resolution fails (throwing a SocketException), it indicates no valid internet connection.
Here is the basic one-time detection implementation:
import 'dart:io';
Future<bool> hasNetwork() async {
try {
final result = await InternetAddress.lookup('example.com');
return result.isNotEmpty && result[0].rawAddress.isNotEmpty;
} on SocketException catch (_) {
return false;
}
}
In actual usage, it can be called like this:
bool isOnline = await hasNetwork();
if (isOnline) {
// Execute network request
await getData();
} else {
// Handle no network situation
showOfflineMessage();
}
Advanced Implementation: Connection Status Monitoring
For scenarios requiring real-time monitoring of network status changes, a more comprehensive solution can be created by combining the connectivity_plus plugin. This approach not only detects the current connection status but also promptly notifies the application when network status changes occur.
First, add the dependency in pubspec.yaml:
dependencies:
connectivity_plus: ^2.0.2
Then create the connection status management class:
import 'dart:io';
import 'dart:async';
import 'package:connectivity_plus/connectivity_plus.dart';
class ConnectionStatusSingleton {
static final ConnectionStatusSingleton _singleton =
ConnectionStatusSingleton._internal();
ConnectionStatusSingleton._internal();
static ConnectionStatusSingleton getInstance() => _singleton;
bool hasConnection = false;
StreamController<bool> connectionChangeController =
StreamController<bool>.broadcast();
final Connectivity _connectivity = Connectivity();
void initialize() {
_connectivity.onConnectivityChanged.listen(_connectionChange);
checkConnection();
}
Stream<bool> get connectionChange => connectionChangeController.stream;
void dispose() {
connectionChangeController.close();
}
void _connectionChange(ConnectivityResult result) {
checkConnection();
}
Future<bool> checkConnection() async {
bool previousConnection = hasConnection;
try {
final result = await InternetAddress.lookup('google.com');
hasConnection = result.isNotEmpty && result[0].rawAddress.isNotEmpty;
} on SocketException catch(_) {
hasConnection = false;
}
if (previousConnection != hasConnection) {
connectionChangeController.add(hasConnection);
}
return hasConnection;
}
}
Integration in Applications
Initialize connection status monitoring at the application entry point:
void main() {
ConnectionStatusSingleton connectionStatus =
ConnectionStatusSingleton.getInstance();
connectionStatus.initialize();
runApp(MyApp());
}
Use connection status in specific Widgets:
class MyWidgetState extends State<MyWidget> {
StreamSubscription<bool>? _connectionChangeStream;
bool isOffline = false;
@override
void initState() {
super.initState();
ConnectionStatusSingleton connectionStatus =
ConnectionStatusSingleton.getInstance();
_connectionChangeStream =
connectionStatus.connectionChange.listen(connectionChanged);
}
void connectionChanged(bool hasConnection) {
setState(() {
isOffline = !hasConnection;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Text(isOffline ? 'Offline' : 'Online'),
),
);
}
@override
void dispose() {
_connectionChangeStream?.cancel();
super.dispose();
}
}
Best Practices and Considerations
When selecting detection domains, it is recommended to use stable and reliable public domains such as google.com, example.com, etc. Avoid using domains that might be blocked by local networks, and do not use your own server domains to prevent false positives due to server failures.
For network detection frequency, a balance between accuracy and performance must be struck. Too frequent detection increases device battery consumption and network traffic, while detection intervals that are too long may result in delayed status updates. It is recommended to perform detection when network status changes occur, or conduct one-time detection before executing important network operations.
Regarding error handling, in addition to catching SocketException, timeout handling should also be considered. Set reasonable timeout durations to avoid prolonged waiting in poor network conditions:
Future<bool> hasNetworkWithTimeout() async {
try {
final result = await InternetAddress.lookup('example.com')
.timeout(const Duration(seconds: 5));
return result.isNotEmpty && result[0].rawAddress.isNotEmpty;
} catch (_) {
return false;
}
}
Conclusion
By combining the connectivity_plus plugin's network type detection with InternetAddress.lookup()'s actual connection testing, developers can build internet connectivity detection solutions that are both accurate and efficient. This approach effectively distinguishes between "connected to a network" and "able to access the internet" as two different states, providing Flutter applications with reliable network status management capabilities.