Reputation: 14063
I have a network call to be executed. But before doing that I need to check whether the device have internet connectivity.
This is what i have done so far:
var connectivityResult = new Connectivity().checkConnectivity();// User defined class
if (connectivityResult == ConnectivityResult.mobile ||
connectivityResult == ConnectivityResult.wifi) {*/
this.getData();
} else {
neverSatisfied();
}
Above method is not working.
Upvotes: 262
Views: 364114
Reputation: 562
try {
final result = await InternetAddress.lookup('google.com');
if (result.isNotEmpty && result[0].rawAddress.isNotEmpty) {
print('connected');
}
} on SocketException catch (_) {
print('not connected');
}
abstract class InternetCheck {
Future<bool> get connected;
}
class InternetCheckImpl1 implements InternetCheck {
@override
Future<bool> get connected async {
try {
final result = await InternetAddress.lookup('google.com');
return result.isNotEmpty && result[0].rawAddress.isNotEmpty;
} on SocketException catch (_) {
return Future.value(false);
}
}
}
class InternetCheckImpl2 implements InternetCheck {
InternetCheckImpl2(this.connectionChecker);
final DataConnectionChecker connectionChecker;
@override
Future<bool> get connected => connectionChecker.hasConnection;
}
You may ask why this complexity since we can do it the easy way ? ok here is why
/// implementations for testing
class InternetMockImplActive implements InternetCheck {
@override
Future<bool> get connected async => true;
}
class InternetMockImplInactive implements InternetCheck {
@override
Future<bool> get connected async => false;
}
/// injecting it in DI
injection.registerLazySingleton<InternetCheck>(() =>
InternetCheckImpl1(),
// InternetCheckImpl2(),
// InternetMockImplActive(),
// InternetMockImplInactive(),
);
Upvotes: 2
Reputation: 1
best solution :
Future<bool> checkInternet() async {
try {
final response = await http.head(Uri.parse('https://www.google.com'));
return response.statusCode == 200;
} catch (_) {
return false;
}
}
Upvotes: 0
Reputation: 61
We are in 2024, and I wanted to contribute to try to make life easier for new people who land on this old question. Most of the answers given above are probably obsolete nowadays due to changing technologies.
To reliably check that you actually have access to the internet (via wifi or mobile data), simply use the internet_connection_checker_plus widget.
1 - add this permissions to your AndroidManifest.xml file <uses-permission android:name="android.permission.INTERNET" />
2 - execute the flutter pub add internet_connection_checker_plus command in your terminal, this will add the latest version of the widget available, currently it is:
internet_connection_checker_plus: ^2.1.0
3 - add import package:internet_connection_checker_plus/internet_connection_checker_plus.dart
; on your project's .dart file
Now all you have to do is use the InternetConnection class anywhere in your project to verify that the internet is available before each action that requires an internet connection:
if(await InternetConnection().hasInternetAccess){
//You have access to the internet, do what you want
}else{
//You don't have access to the internet, do what you want
}
For example
onPressed: () async {
if(await InternetConnection().hasInternetAccess){
print("You are online");
}else{
print("You are offline");
}
},
To listen to the change in state of the internet connection you can use
final listener = InternetConnection().onStatusChange.listen((InternetStatus status) {
switch (status) {
case InternetStatus.connected:
// The internet is now connected
break;
case InternetStatus.disconnected:
// The internet is now disconnected
break;
}
});
For more details please refer to the widget page https://pub.dev/packages/internet_connection_checker_plus
Upvotes: 5
Reputation: 91
In order to check internet connection, you can ping google.com or any address you want with dart_ping package. Before using this package, I used InternetAddress lookup method. But probably it can return result from dns cache. So, using that is not consistent.
final result = await Ping('google.com', count: 1).stream.first;
Upvotes: 0
Reputation: 338
Today is 2023, Here is the solution I have
try {
final dio = Dio();
final response = await dio.get('https://www.google.com');
if (response.statusCode == 200) {
internetAccessible = "Ready";
} else {
internetAccessible = "Not Ready";
}
} catch (_) {
internetAccessible = "Not Ready";
}
This seems to work on my android pad with wlan turn off, and connect to wifi that has no internet.
Upvotes: -1
Reputation: 1268
The main problem with the connectivity package is that it only triggers, if the interface goes completely down. As I am not really interested how the user is connected, but rather IF he is connected, I came up with this solution that can be wrapped around any other widget that requires internet access.
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
class ConnectivityWidget extends StatefulWidget {
const ConnectivityWidget({super.key, required this.child});
final Widget child;
@override
State<ConnectivityWidget> createState() => _ConnectivityWidgetState();
}
class _ConnectivityWidgetState extends State<ConnectivityWidget> {
final myConnectivity = MyConnectivity.instance;
bool? isOnline;
@override
void initState() {
super.initState();
myConnectivity.continueslyCheckInternetConnection().listen((result) {
setState(() => isOnline = result);
});
}
@override
Widget build(BuildContext context) {
if (isOnline == null) {
return const Scaffold(
body: Center(child: Text('Checking internet connection...')),
);
}
if (isOnline == false) {
return const Scaffold(
body: Center(child: Text('No Internet connection.', style: TextStyle(color: Colors.red))),
);
}
return widget.child;
}
@override
void dispose() {
debugPrint('NEVER SHOULD HAPPEN: Disposing MainApp...');
myConnectivity.disposeStream();
super.dispose();
}
}
class MyConnectivity {
MyConnectivity._();
static final _instance = MyConnectivity._();
static MyConnectivity get instance => _instance;
final _controller = StreamController<bool>.broadcast();
Stream<bool> continueslyCheckInternetConnection() {
Timer.periodic(const Duration(seconds: 1), (timer) async {
bool isOnline = false;
try {
final result = await InternetAddress.lookup('www.google.com');
isOnline = result.isNotEmpty && result[0].rawAddress.isNotEmpty;
} on SocketException catch (_) {
isOnline = false;
}
final timestamp = DateTime.timestamp().millisecondsSinceEpoch;
debugPrint('$timestamp - Internet:$isOnline');
_controller.add(isOnline);
});
return _controller.stream;
}
void disposeStream() => _controller.close();
}
Upvotes: 0
Reputation: 951
As this an old question a lot of things has be changed since last 5 years and connectivity_plus
is no more working (at least for me) as I tried it today.
Luckily I found https://pub.dev/packages/internet_connection_checker which works like a charm, for checking internet connectivity.
As the author says the Purpose of the package:
The reason this package exists is that
connectivity_plus
package cannot reliably determine if a data connection is actually available. More info on its page here: https://pub.dev/packages/connectivity_plus
So recommend using internet_connection_checker
and below code should work:
bool result = await InternetConnectionChecker().hasConnection;
if(result == true) {
print('YAY! Free cute dog pics!');
} else {
print('No internet :( Reason:');
// print(InternetConnectionChecker().lastTryResults);
}
Best thing is its all dart, which is what flutter is based on.
Upvotes: 0
Reputation: 754
To check whether you have internet access or not, even if you are connected to wifi, use the below function.
Future<bool> checkInternetStatus() async {
try {
final url = Uri.https('google.com');
var response = await http.head(url);
if (response.statusCode == 200) {
return true;
} else {
return false;
}
} catch (e) {
return false;
}
}
also add http: ^0.13.5 dependency then import 'package:http/http.dart' as http;
Upvotes: 2
Reputation: 477
I found that just using the connectivity package was not enough to tell if the internet was available or not. In Android it only checks if there is WIFI or if mobile data is turned on, it does not check for an actual internet connection . During my testing, even with no mobile signal ConnectivityResult.mobile would return true.
With IOS my testing found that the connectivity plugin does correctly detect if there is an internet connection when the phone has no signal, the issue was only with Android.
The solution I found was to use the data_connection_checker package along with the connectivity package. This just makes sure there is an internet connection by making requests to a few reliable addresses, the default timeout for the check is around 10 seconds.
My finished isInternet function looked a bit like this:
Future<bool> isInternet() async {
var connectivityResult = await (Connectivity().checkConnectivity());
if (connectivityResult == ConnectivityResult.mobile) {
// I am connected to a mobile network, make sure there is actually a net connection.
if (await DataConnectionChecker().hasConnection) {
// Mobile data detected & internet connection confirmed.
return true;
} else {
// Mobile data detected but no internet connection found.
return false;
}
} else if (connectivityResult == ConnectivityResult.wifi) {
// I am connected to a WIFI network, make sure there is actually a net connection.
if (await DataConnectionChecker().hasConnection) {
// Wifi detected & internet connection confirmed.
return true;
} else {
// Wifi detected but no internet connection found.
return false;
}
} else {
// Neither mobile data or WIFI detected, not internet connection found.
return false;
}
}
The if (await DataConnectionChecker().hasConnection)
part is the same for both mobile and wifi connections and should probably be moved to a separate function. I've not done that here to leave it more readable.
Upvotes: 47
Reputation: 658067
The connectivity plugin states in its docs that it only provides information if there is a network connection, but not if the network is connected to the Internet
Note that on Android, this does not guarantee connection to Internet. For instance, the app might have wifi access but it might be a VPN or a hotel WiFi with no access.
You can use
import 'dart:io';
...
try {
final result = await InternetAddress.lookup('example.com');
if (result.isNotEmpty && result[0].rawAddress.isNotEmpty) {
print('connected');
}
} on SocketException catch (_) {
print('not connected');
}
The connectivity package is deprecated. Use the official Flutter Community connectivity_plus package instead.
Upvotes: 411
Reputation: 1
Use the observe_internet_connectivity package.
final hasInternet = await InternetConnectivity().hasInternetConnection;
if (hasInternet) {
//You are connected to the internet
} else {
//"No internet connection
}
final subscription =
InternetConnectivity().observeInternetConnection.listen((bool hasInternetAccess) {
if(!hasInternetAccess){
showToast('No Internet Connection');
}
});
await Future.delayed(const Duration(seconds: 10 ));
subscription.cancel();
InternetConnectivityListener
to listen to internet connectivity changes inside a flutter widget return InternetConnectivityListener(
connectivityListener: (BuildContext context, bool hasInternetAccess) {
if (hasInternetAccess) {
context.showBanner('You are back Online!', color: Colors.green);
} else {
context.showBanner('No internet connection', color: Colors.red);
}
},
child: Scaffold(
body: Container(),
),
);
InternetConnectivityBuilder
to build internet connection aware widgets return InternetConnectivityBuilder(
connectivityBuilder: (BuildContext context, bool hasInternetAccess, Widget? child) {
if(hasInternetAccess) {
return OnlineWidget();
} else {
return OfflineWidget();
}
},
child: ChildWidget(),
);
Upvotes: 0
Reputation: 9
final ConnectivityResult result = await Connectivity().checkConnectivity();
if (result == ConnectivityResult.wifi) {
print('Connected to a Wi-Fi network');
} else if (result == ConnectivityResult.mobile) {
print('Connected to a mobile network');
} else {
print('Not connected to any network');
}
Upvotes: 0
Reputation: 2459
I have written a package to check the active internet connection and display a widget accordingly.
Example:
InternetWidget(
online: Text('Online'),
offline: Text('Offline),
);
As per the network state, the appropriate widgets will be displayed. If you have an active internet connection an online widget will be displayed.
All the heavyweight is done by the package and all you have to do is provide online and offline widgets. Optionally you can provide a loading widget and lookup URL.
Discussion, PRs or suggestions are welcome.
Upvotes: 2
Reputation: 609
The connectivity plugin states in its docs that it only provides information if there is a network connection, but not if the network is connected to the Internet. Use the below code and don't forget to use ".timeout()" because you can stuck forever using "await".
import 'dart:io';
Future<bool> isConnected() async {
try {
List<InternetAddress> result = await InternetAddress.lookup('example.com')
.timeout(Duration(seconds: 5));
//
if (result.isNotEmpty && result[0].rawAddress.isNotEmpty) {
return true;
}
//
else {
return false;
}
} on SocketException catch (_) {
return false;
}
}
Upvotes: -1
Reputation: 984
You can make use of this package https://pub.dev/packages/flutter_network_connectivity
Underhood it makes use of NetworkCapabilities on Android and NetworkMonitor on iOS and listens to connectivity changes and pings to check internet availability, you can also configure to lookup internet availability in a periodic interval.
Add to your pubspec.yaml
flutter_network_connectivity: ^0.0.6
Create an Object
FlutterNetworkConnectivity flutterNetworkConnectivity =
FlutterNetworkConnectivity(
isContinousLookUp: true, // optional, false if you cont want continous lookup
lookUpDuration: const Duration(seconds: 5), // optional, to override default lookup duration
lookUpUrl: 'example.com', // optional, to override default lookup url
);
and you can use its methods to check for network connectivity continuously or a call to check the current status
_flutterNetworkConnectivity.getInternetAvailabilityStream().listen((isInternetAvailable) {
// do something
});
and register listener
await _flutterNetworkConnectivity.registerAvailabilityListener();
to check status on call
bool _isNetworkConnectedOnCall = await _flutterNetworkConnectivity.isInternetConnectionAvailable();
Upvotes: 0
Reputation: 268414
Create this method:
Future<bool> hasNetwork() async {
try {
final result = await InternetAddress.lookup('example.com');
return result.isNotEmpty && result[0].rawAddress.isNotEmpty;
} on SocketException catch (_) {
return false;
}
}
Usage:
bool isOnline = await hasNetwork();
Add the following dependency to your pubspec.yaml
file.
connectivity_plus: ^2.0.2
Full code:
void main() => runApp(MaterialApp(home: HomePage()));
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
Map _source = {ConnectivityResult.none: false};
final MyConnectivity _connectivity = MyConnectivity.instance;
@override
void initState() {
super.initState();
_connectivity.initialise();
_connectivity.myStream.listen((source) {
setState(() => _source = source);
});
}
@override
Widget build(BuildContext context) {
String string;
switch (_source.keys.toList()[0]) {
case ConnectivityResult.mobile:
string = 'Mobile: Online';
break;
case ConnectivityResult.wifi:
string = 'WiFi: Online';
break;
case ConnectivityResult.none:
default:
string = 'Offline';
}
return Scaffold(
body: Center(child: Text(string)),
);
}
@override
void dispose() {
_connectivity.disposeStream();
super.dispose();
}
}
class MyConnectivity {
MyConnectivity._();
static final _instance = MyConnectivity._();
static MyConnectivity get instance => _instance;
final _connectivity = Connectivity();
final _controller = StreamController.broadcast();
Stream get myStream => _controller.stream;
void initialise() async {
ConnectivityResult result = await _connectivity.checkConnectivity();
_checkStatus(result);
_connectivity.onConnectivityChanged.listen((result) {
_checkStatus(result);
});
}
void _checkStatus(ConnectivityResult result) async {
bool isOnline = false;
try {
final result = await InternetAddress.lookup('example.com');
isOnline = result.isNotEmpty && result[0].rawAddress.isNotEmpty;
} on SocketException catch (_) {
isOnline = false;
}
_controller.sink.add({result: isOnline});
}
void disposeStream() => _controller.close();
}
Credit to : connectivity_plus and Günter Zöchbauer
Upvotes: 131
Reputation: 11
Based on this answer https://stackoverflow.com/a/68436867/10761151
If you used dart null safety you will get an error, so you can update the dependencies data_connection_checker: ^0.3.4 to internet_connection_checker: ^0.0.1+2
and you can use this code
import 'dart:async';
import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:internet_connection_checker/internet_connection_checker.dart';
class ConnectionUtil {
static final ConnectionUtil _singleton = new ConnectionUtil._internal();
ConnectionUtil._internal();
static ConnectionUtil getInstance() => _singleton;
bool hasConnection = false;
StreamController connectionChangeController = StreamController();
final Connectivity _connectivity = Connectivity();
void initialize() {
_connectivity.onConnectivityChanged.listen(_connectionChange);
}
void _connectionChange(ConnectivityResult result) {
_hasInternetInternetConnection();
}
Stream get connectionChange => connectionChangeController.stream;
Future<bool> _hasInternetInternetConnection() async {
bool previousConnection = hasConnection;
var connectivityResult = await (Connectivity().checkConnectivity());
if (connectivityResult == ConnectivityResult.mobile || connectivityResult == ConnectivityResult.wifi) {
// this is the different
if (await InternetConnectionChecker().hasConnection) {
hasConnection = true;
} else {
hasConnection = false;
}
} else {
hasConnection = false;
}
if (previousConnection != hasConnection) {
connectionChangeController.add(hasConnection);
}
return hasConnection;
}
}
and on the stateful widget you can implement this code
bool hasInterNetConnection = false;
@override
initState() {
ConnectionUtil connectionStatus = ConnectionUtil.getInstance();
connectionStatus.initialize();
connectionStatus.connectionChange.listen(connectionChanged);
super.initState();
}
void connectionChanged(dynamic hasConnection) {
setState(() {
hasInterNetConnection = hasConnection;
});
}
Upvotes: 1
Reputation: 3004
Well I read almost all post and @dennmat post is most usedful to me. though it did't work for me and it is outdated too. I have update with flutter updated connectivity
package(i.e connectivity_plus
) and data_connection_checker
(to check whether there is actual internet connection for mobile and wifi).
After this post you will be able to listen for internet connection continuosly.
1. Add dependencies
a) connectivity_plus: ^1.0.6
b) data_connection_checker: ^0.3.4
2. Custom class that handle all the connection.
import 'dart:async';
import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:data_connection_checker/data_connection_checker.dart';
class ConnectionUtil {
//This creates the single instance by calling the `_internal` constructor specified below
static final ConnectionUtil _singleton = new ConnectionUtil._internal();
ConnectionUtil._internal();
//This is what's used to retrieve the instance through the app
static ConnectionUtil getInstance() => _singleton;
//This tracks the current connection status
bool hasConnection = false;
//This is how we'll allow subscribing to connection changes
StreamController connectionChangeController = StreamController();
//flutter_connectivity
final Connectivity _connectivity = Connectivity();
void initialize() {
_connectivity.onConnectivityChanged.listen(_connectionChange);
}
//flutter_connectivity's listener
void _connectionChange(ConnectivityResult result) {
hasInternetInternetConnection();
}
Stream get connectionChange => connectionChangeController.stream;
Future<bool> hasInternetInternetConnection() async {
bool previousConnection = hasConnection;
var connectivityResult = await (Connectivity().checkConnectivity());
//Check if device is just connect with mobile network or wifi
if (connectivityResult == ConnectivityResult.mobile ||
connectivityResult == ConnectivityResult.wifi) {
//Check there is actual internet connection with a mobile network or wifi
if (await DataConnectionChecker().hasConnection) {
// Network data detected & internet connection confirmed.
hasConnection = true;
} else {
// Network data detected but no internet connection found.
hasConnection = false;
}
}
// device has no mobile network and wifi connection at all
else {
hasConnection = false;
}
// The connection status changed send out an update to all listeners
if (previousConnection != hasConnection) {
connectionChangeController.add(hasConnection);
}
return hasConnection;
}
}
@override
initState() {
print('called');
//Create instance
ConnectionUtil connectionStatus = ConnectionUtil.getInstance();
//Initialize
connectionStatus.initialize();
//Listen for connection change
_connectionChangeStream = connectionStatus.connectionChange.listen((event) {
print(event);
});
super.initState();
}
Now check the log while toggle flight mode. you should get log with true and false value.
Note: this will not work in flutter web, if you wish to make it work than use dio
or http
plugin instead of data_connection_checker
.
Example Project can be found here. Thanks
Upvotes: 7
Reputation: 179
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:app_settings/app_settings.dart';
import 'package:connectivity/connectivity.dart';
class InternetConnect extends StatefulWidget {
@override
InternetConnectState createState() => InternetConnectState();
}
class InternetConnectState extends State<InternetConnect> {
ConnectivityResult previous;
bool dialogshown = false;
StreamSubscription connectivitySubscription;
Future<bool> checkinternet() async {
try {
final result = await InternetAddress.lookup('google.com');
if (result.isNotEmpty && result[0].rawAddress.isNotEmpty) {
return Future.value(true);
}
} on SocketException catch (_) {
return Future.value(false);
}
}
void checkInternetConnect(BuildContext context) {
connectivitySubscription = Connectivity()
.onConnectivityChanged
.listen((ConnectivityResult connresult) {
if (connresult == ConnectivityResult.none) {
dialogshown = true;
showDialog(
context: context, barrierDismissible: false, child: alertDialog());
} else if (previous == ConnectivityResult.none) {
checkinternet().then((result) {
if (result == true) {
if (dialogshown == true) {
dialogshown = false;
Navigator.pop(context);
}
}
});
}
previous = connresult;
});
}
AlertDialog alertDialog() {
return AlertDialog(
title: Text('ERROR'),
content: Text("No Internet Detected."),
actions: <Widget>[
FlatButton(
// method to exit application programitacally
onPressed: () {
AppSettings.openWIFISettings();
},
child: Text("Settings"),
),
],
);
}
@override
Widget build(BuildContext context) {
return Container();
}
}
and you can use this method in init of any class
@override
void initState() {
// TODO: implement initState
InternetConnectState().checkInternetConnect(context);
super.initState();
}
Upvotes: 2
Reputation: 1789
use connectivity_widget: ^0.1.7
add dependencies:
dependencies:
connectivity_widget: ^0.1.7
add code:
ConnectivityWidget(
builder: (context, isOnline) => Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
"${isOnline ? 'Connected' : 'Offline'}",
style: TextStyle(
fontSize: 30,
color: isOnline ? Colors.green : Colors.red),
),
],
),
),
)
OUTPUT:
Upvotes: 3
Reputation: 1
For me I just create a single data in Firebase and use future builder to await for the data. Here, like this, you can check if the connection is too slow so the data will be loading:
FutureBuilder(
future: _getImage(context),
builder: (context, snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.none:
return Text('Press button to start.');
case ConnectionState.active:
case ConnectionState.waiting:
return Container(
height:
MediaQuery.of(context).size.height / 1.25,
width:
MediaQuery.of(context).size.width / 1.25,
child: Loading());
case ConnectionState.done:
if (snapshot.hasData) {
return snapshot.data;
} else {
return FlatButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
ProfilePage()));
},
child: Icon(
Icons.add_a_photo,
size: 50,
),
);
}
// You can reach your snapshot.data['url'] in here
}
return null;
},
),
Upvotes: 0
Reputation: 551
I having some problem with the accepted answer, but it seems it solve answer for others. I would like a solution that can get a response from the url it uses, so I thought http would be great for that functionality, and for that I found this answer really helpful. How do I check Internet Connectivity using HTTP requests(Flutter/Dart)?
Upvotes: 0
Reputation: 613
I used the data_connection_checker package to check the internet access even if the connection available by wifi or mobile, it works well: here is the code to check the connection:
bool result = await DataConnectionChecker().hasConnection;
if(result == true) {
print('YAY! Free cute dog pics!');
} else {
print('No internet :( Reason:');
print(DataConnectionChecker().lastTryResults);
}
head over the package if you want more information. Data Connection Checker Package
Upvotes: 1
Reputation: 519
I ultimately (though reluctantly) settled on the solution given by @abernee in a previous answer to this question. I always try and use as few external packages in my projects as possible - as I know external packages are the only [ potential ] points of failure in the software I create. So to link to TWO external packages just for a simple implementation like this was not easy for me.
Nevertheless, I took abernee's code and modified it to make it leaner and more sensible. By sensible I mean he consumes the power of the Connectivity package in his function but then wastes it internally by not returning the most valuable outputs from this package ( i.e. the network identification ). So here is the modified version of abernee's solution:
import 'package:connectivity/connectivity.dart';
import 'package:data_connection_checker/data_connection_checker.dart';
// 'McGyver' - the ultimate cool guy (the best helper class any app can ask for).
class McGyver {
static Future<Map<String, dynamic>> checkInternetAccess() async {
//* ////////////////////////////////////////////////////////////////////////////////////////// *//
//* INFO: ONLY TWO return TYPES for Map 'dynamic' value => <bool> and <ConnectivityResult> *//
//* ////////////////////////////////////////////////////////////////////////////////////////// *//
Map<String, dynamic> mapCon;
final String isConn = 'isConnected', netType = 'networkType';
ConnectivityResult conRes = await (Connectivity().checkConnectivity());
switch (conRes) {
case ConnectivityResult.wifi: //* WiFi Network: true !!
if (await DataConnectionChecker().hasConnection) { //* Internet Access: true !!
mapCon = Map.unmodifiable({isConn: true, netType: ConnectivityResult.wifi});
} else {
mapCon = Map.unmodifiable({isConn: false, netType: ConnectivityResult.wifi});
}
break;
case ConnectivityResult.mobile: //* Mobile Network: true !!
if (await DataConnectionChecker().hasConnection) { //* Internet Access: true !!
mapCon = Map.unmodifiable({isConn: true, netType: ConnectivityResult.mobile});
} else {
mapCon = Map.unmodifiable({isConn: false, netType: ConnectivityResult.mobile});
}
break;
case ConnectivityResult.none: //* No Network: true !!
mapCon = Map.unmodifiable({isConn: false, netType: ConnectivityResult.none});
break;
}
return mapCon;
}
}
Then you'd use this static function via a simple call from anywhere in your code as follows:
bool isConn; ConnectivityResult netType;
McGyver.checkInternetAccess().then(
(mapCIA) { //* 'mapCIA' == amalgamation for 'map' from 'CheckInternetAccess' function result.
debugPrint("'mapCIA' Keys: ${mapCIA.keys}");
isConn = mapCIA['isConnected'];
netType = mapCIA['networkType'];
}
);
debugPrint("Internet Access: $isConn | Network Type: $netType");
It's a pity that you have to link to TWO EXTERNAL PACKAGES to get this very basic functionality in your Flutter project - but I guess for now this is the best we have. I actually prefer the Data Connection Checker package over the Connectivity package - but (at the time of posting this) the former was missing that very important network identification feature that I require from the Connectivity package. This is the reason I defaulted onto this approach [ temporarily ].
Upvotes: 2
Reputation: 838
I had an issue with the proposed solutions, using lookup
does not always return the expected value.
This is due to DNS caching, the value of the call is cached and intead of doing a proper call on the next try it gives back the cached value. Of course this is an issue here as it means if you lose connectivity and call lookup
it could still return the cached value as if you had internet, and conversely, if you reconnect your internet after lookup
returned null it will still return null for the duration of the cache, which can be a few minutes, even if you do have internet now.
TL;DR: lookup
returning something does not necessarily mean you have internet, and it not returning anything does not necessarily mean you don't have internet. It is not reliable.
I implemented the following solution by taking inspiration from the data_connection_checker
plugin:
/// If any of the pings returns true then you have internet (for sure). If none do, you probably don't.
Future<bool> _checkInternetAccess() {
/// We use a mix of IPV4 and IPV6 here in case some networks only accept one of the types.
/// Only tested with an IPV4 only network so far (I don't have access to an IPV6 network).
final List<InternetAddress> dnss = [
InternetAddress('8.8.8.8', type: InternetAddressType.IPv4), // Google
InternetAddress('2001:4860:4860::8888', type: InternetAddressType.IPv6), // Google
InternetAddress('1.1.1.1', type: InternetAddressType.IPv4), // CloudFlare
InternetAddress('2606:4700:4700::1111', type: InternetAddressType.IPv6), // CloudFlare
InternetAddress('208.67.222.222', type: InternetAddressType.IPv4), // OpenDNS
InternetAddress('2620:0:ccc::2', type: InternetAddressType.IPv6), // OpenDNS
InternetAddress('180.76.76.76', type: InternetAddressType.IPv4), // Baidu
InternetAddress('2400:da00::6666', type: InternetAddressType.IPv6), // Baidu
];
final Completer<bool> completer = Completer<bool>();
int callsReturned = 0;
void onCallReturned(bool isAlive) {
if (completer.isCompleted) return;
if (isAlive) {
completer.complete(true);
} else {
callsReturned++;
if (callsReturned >= dnss.length) {
completer.complete(false);
}
}
}
dnss.forEach((dns) => _pingDns(dns).then(onCallReturned));
return completer.future;
}
Future<bool> _pingDns(InternetAddress dnsAddress) async {
const int dnsPort = 53;
const Duration timeout = Duration(seconds: 3);
Socket socket;
try {
socket = await Socket.connect(dnsAddress, dnsPort, timeout: timeout);
socket?.destroy();
return true;
} on SocketException {
socket?.destroy();
}
return false;
}
The call to _checkInternetAccess
takes at most a duration of timeout
to complete (3 seconds here), and if we can reach any of the DNS it will complete as soon as the first one is reached, without waiting for the others (as reaching one is enough to know you have internet). All the calls to _pingDns
are done in parallel.
It seems to work well on an IPV4 network, and when I can't test it on an IPV6 network (I don't have access to one) I think it should still work. It also works on release mode builds, but I yet have to submit my app to Apple to see if they find any issue with this solution.
It should also work in most countries (including China), if it does not work in one you can add a DNS to the list that is accessible from your target country.
Upvotes: 6
Reputation: 31
dependencies:
data_connection_checker:
And Here Is The main.dart Of My Solution
import 'dart:async';
import 'package:data_connection_checker/data_connection_checker.dart';
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: "Data Connection Checker",
home: HomePage(),
);
}
}
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
StreamSubscription<DataConnectionStatus> listener;
var Internetstatus = "Unknown";
@override
void initState() {
// TODO: implement initState
super.initState();
// _updateConnectionStatus();
CheckInternet();
}
@override
void dispose() {
// TODO: implement dispose
listener.cancel();
super.dispose();
}
CheckInternet() async {
// Simple check to see if we have internet
print("The statement 'this machine is connected to the Internet' is: ");
print(await DataConnectionChecker().hasConnection);
// returns a bool
// We can also get an enum instead of a bool
print("Current status: ${await DataConnectionChecker().connectionStatus}");
// prints either DataConnectionStatus.connected
// or DataConnectionStatus.disconnected
// This returns the last results from the last call
// to either hasConnection or connectionStatus
print("Last results: ${DataConnectionChecker().lastTryResults}");
// actively listen for status updates
listener = DataConnectionChecker().onStatusChange.listen((status) {
switch (status) {
case DataConnectionStatus.connected:
Internetstatus="Connectd TO THe Internet";
print('Data connection is available.');
setState(() {
});
break;
case DataConnectionStatus.disconnected:
Internetstatus="No Data Connection";
print('You are disconnected from the internet.');
setState(() {
});
break;
}
});
// close listener after 30 seconds, so the program doesn't run forever
// await Future.delayed(Duration(seconds: 30));
// await listener.cancel();
return await await DataConnectionChecker().connectionStatus;
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Data Connection Checker"),
),
body: Container(
child: Center(
child: Text("$Internetstatus"),
),
),
);
}
}
Upvotes: 2
Reputation: 1991
late answer, but use this package to to check. Package Name: data_connection_checker
in you pubspec.yuml file:
dependencies:
data_connection_checker: ^0.3.4
create a file called connection.dart or any name you want. import the package:
import 'package:data_connection_checker/data_connection_checker.dart';
check if there is internet connection or not:
print(await DataConnectionChecker().hasConnection);
Upvotes: 1
Reputation: 6059
Just trying to simplify the code using Connectivity Package in Flutter.
import 'package:connectivity/connectivity.dart';
var connectivityResult = await (Connectivity().checkConnectivity());
if (connectivityResult == ConnectivityResult.mobile) {
// I am connected to a mobile network.
} else if (connectivityResult == ConnectivityResult.wifi) {
// I am connected to a wifi network.
} else {
// I am not connected to the internet
}
Upvotes: 0
Reputation: 38029
The connectivity: package does not guarantee the actual internet connection (could be just wifi connection without internet access).
Quote from the documentation:
Note that on Android, this does not guarantee connection to Internet. For instance, the app might have wifi access but it might be a VPN or a hotel WiFi with no access.
If you really need to check the connection to the www Internet the better choice would be
data_connection_checker package
Upvotes: 3
Reputation: 10906
I made a base class for widget state
Usage instead of State<LoginPage>
use BaseState<LoginPage>
then just use the boolean variable isOnline
Text(isOnline ? 'is Online' : 'is Offline')
First, add connectivity plugin:
dependencies:
connectivity: ^0.4.3+2
Then add the BaseState class
import 'dart:async';
import 'dart:io';
import 'package:flutter/services.dart';
import 'package:connectivity/connectivity.dart';
import 'package:flutter/widgets.dart';
/// a base class for any statful widget for checking internet connectivity
abstract class BaseState<T extends StatefulWidget> extends State {
void castStatefulWidget();
final Connectivity _connectivity = Connectivity();
StreamSubscription<ConnectivityResult> _connectivitySubscription;
/// the internet connectivity status
bool isOnline = true;
/// initialize connectivity checking
/// Platform messages are asynchronous, so we initialize in an async method.
Future<void> initConnectivity() async {
// Platform messages may fail, so we use a try/catch PlatformException.
try {
await _connectivity.checkConnectivity();
} on PlatformException catch (e) {
print(e.toString());
}
// If the widget was removed from the tree while the asynchronous platform
// message was in flight, we want to discard the reply rather than calling
// setState to update our non-existent appearance.
if (!mounted) {
return;
}
await _updateConnectionStatus().then((bool isConnected) => setState(() {
isOnline = isConnected;
}));
}
@override
void initState() {
super.initState();
initConnectivity();
_connectivitySubscription = Connectivity()
.onConnectivityChanged
.listen((ConnectivityResult result) async {
await _updateConnectionStatus().then((bool isConnected) => setState(() {
isOnline = isConnected;
}));
});
}
@override
void dispose() {
_connectivitySubscription.cancel();
super.dispose();
}
Future<bool> _updateConnectionStatus() async {
bool isConnected;
try {
final List<InternetAddress> result =
await InternetAddress.lookup('google.com');
if (result.isNotEmpty && result[0].rawAddress.isNotEmpty) {
isConnected = true;
}
} on SocketException catch (_) {
isConnected = false;
return false;
}
return isConnected;
}
}
And you need to cast the widget in your state like this
@override
void castStatefulWidget() {
// ignore: unnecessary_statements
widget is StudentBoardingPage;
}
Upvotes: 7