check internet connection in flutter - flutter

I am trying to use the following code to check an internet connection in flutter, we want to make our application usable offline but this code just seems to loop. Is there a better way to do this? Im calling this on a button press before calling an http api.
package is = connectivity: ^0.4.6+1
var connectivityResult = await (Connectivity().checkConnectivity());
if (connectivityResult == ConnectivityResult.mobile || connectivityResult == ConnectivityResult.wifi) {
//Connection Exists
} else {
//No connection
}

You should listen to network connection event instead of calling it directly.
Take a try with this:
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:connectivity/connectivity.dart';
class CheckNetworkPage extends StatefulWidget {
#override
_CheckNetworkPageState createState() => _CheckNetworkPageState();
}
class _CheckNetworkPageState extends State<CheckNetworkPage> {
StreamSubscription<ConnectivityResult> _networkSubscription;
#override
initState() {
super.initState();
_networkSubscription = Connectivity().onConnectivityChanged.listen((ConnectivityResult result) {
if (result == ConnectivityResult.mobile) {
// I am connected to a mobile network.
} else if (result == ConnectivityResult.wifi) {
// I am connected to a wifi network.
} else if (result == ConnectivityResult.none) {
// I am not connected any network.
}
});
}
#override
Widget build(BuildContext context) {
return Container();
}
// Be sure to cancel subscription after you are done
#override
dispose() {
super.dispose();
_networkSubscription.cancel();
}
}

Related

how to await for network connectivity status in flutter

I have used connectivity_plus and internet_connection_checker packages to check the internet connectivity.
The problem occured is , the app works perfectly fine as expected when the app start's with internet on state. But when the app is opened with internet off, the dialog isn't shown !!
I assume this is happening because the build method is called before the stream of internet is listened.
Code :
class _HomePageState extends State<HomePage> {
late StreamSubscription subscription;
bool isDeviceConnected = false;
bool isAlertSet = false;
#override
void initState() {
getConnectivity();
super.initState();
}
getConnectivity() {
subscription = Connectivity().onConnectivityChanged.listen(
(ConnectivityResult result) async {
isDeviceConnected = await InternetConnectionChecker().hasConnection;
if (!isDeviceConnected && isAlertSet == false) {
showDialogBox();
setState(() {
isAlertSet = true;
});
}
},
);
}
#override
void dispose() {
subscription.cancel();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
...
);
}
showDialogBox() => showDialog(/* no internet dialog */)
Extending the question: Is it assured that this works for all the pages ?
if yes, how ?
if not , how to overcome this?
First of all you need to listen for internet connectivity in your app first screen which is probably app.dart
GlobalKey<NavigatorState> navigatorKey = GlobalKey();
final noInternet = NoInternetDialog();
class TestApp extends StatefulWidget {
#override
State<TestApp> createState() => _TestAppState();
}
class _TestAppState extends State<TestApp> {
#override
void initState() {
super.initState();
checkInternetConnectivity();
}
#override
Widget build(BuildContext context) {
return MaterialApp(...);
}
Future<void> checkInternetConnectivity() async {
Connectivity().onConnectivityChanged.getInternetStatus().listen((event)
{
if (event == InternetConnectionStatus.disconnected) {
if (!noInternet.isShowing) {
noInternet.showNoInternet();
}
}
});
}
}
Make the screen stateful in which you are calling MaterialApp and in initState of that class check for your internet connection, like above
You are saying how can I show dialog when internet connection changes for that you have to create a Generic class or extension which you can on connectivity change. You have to pass context to that dialogue using NavigatorKey
class NoInternetDialog {
bool _isShowing = false;
NoInternetDialog();
void dismiss() {
navigatorKey.currentState?.pop();
}
bool get isShowing => _isShowing;
set setIsShowing(bool value) {
_isShowing = value;
}
Future showNoInternet() {
return showDialog(
context: navigatorKey.currentState!.overlay!.context,
barrierDismissible: true,
barrierColor: Colors.white.withOpacity(0),
builder: (ctx) {
setIsShowing = true;
return AlertDialog(
elevation: 0,
backgroundColor: Colors.transparent,
insetPadding: EdgeInsets.all(3.0.h),
content: Container(...),
);
},
);
}
}
Use checkConnectivity to check current status. Only changes are exposed to the stream.
final connectivityResult = await Connectivity().checkConnectivity();

Flutter : is it possible to implement a snackbar one time in main.dart for example for all screen when the connectivity status changed

i make an enum for a connectivity :
enum ConnectivityStatus{
Wifi,
Cellular,
Offline
}
then i create a service to check the Connectivity :
import 'dart:async';
import 'package:Zabatnee/activities_app/enum/connectivity_status.dart';
import 'package:connectivity/connectivity.dart';
class ConnectivityService{
StreamController<ConnectivityStatus> connectionStatusController = StreamController<ConnectivityStatus>();
ConnectivityService(){
Connectivity().onConnectivityChanged.listen((ConnectivityResult result) {
var connectionStatus = _getStatusFromResult(result);
connectionStatusController.add(connectionStatus);
});
}
ConnectivityStatus _getStatusFromResult(ConnectivityResult result) {
switch (result) {
case ConnectivityResult.mobile:
return ConnectivityStatus.Cellular;
case ConnectivityResult.wifi:
return ConnectivityStatus.Wifi;
case ConnectivityResult.none:
return ConnectivityStatus.Offline;
default:
return ConnectivityStatus.Offline;
}
}
}
and what i need is to check the connectivity status in all screen that i created. Can I do it once for all screens all, or i must check the connnectivity for each one individually.
You can check the connectivity status once & that will be implemented for all of your app.
You just have to create a wrapper class & subscribe to the Connectivity stream & apply the logic in this wrapper class.
Your whole widget will be wrapped by this widget.
MaterialApp(
..
home: ConnectivityWrapper(
childWidget: YourWidget(), // replace this with your own home widget
),
);
The wrapper widget will look something like this:
class ConnectivityWrapper extends StatefulWidget {
ConnectivityWrapper(this.childWidget);
final Widget childWidget;
#override
_ConnectivityWrapperState createState() => _ConnectivityWrapperState();
}
class _ConnectivityWrapperState extends State<ConnectivityWrapper> {
StreamSubscription<ConnectivityStatus> subscription;
#override
void initState() {
super.initState();
subscription = connectionStatusController.stream.listen((status)
{
if(status == ConnectivityStatus.Offline) {
// Your logic here (Toast message or something else)
}
},
onDone() {
// Your logic here
},
onError: () {
// Your logic here
});
}
#override
Widget build(BuildContext context) {
return widget.childWidget;
}
#override
void dispose() {
// unsubscribe to the stream
subscription.cancel();
super.dispose();
}
}

Pass Widgets in Connectivity check in flutter

I want to implement internet connectivity check into my app and I used official connectivity plugin and it is working great for displaying String Value but instead of showing string value in screen I want to display different widgets for connected and disconnected.
Here What I am Using
//
Widget result;
//
body: Container(
alignment: Alignment.center,
child: result != null ?
result : Text("unknown", style :
TextStyle(fontSize: 30,fontWeight: FontWeight.bold),
),
void checkStatus(){
Connectivity().onConnectivityChanged.listen((ConnectivityResult result) {
if(
result == ConnectivityResult.mobile ||
result == ConnectivityResult.wifi){
Text("Connected", style:TextStyle(color:Colors.red));
} else {
Text("No InterNet", style:TextStyle(color:Colors.red));
}
});
}
#override
void initState() {
super.initState();
checkStatus();
}
And I am Getting 'unknown' value
try this
class Sample extends StatefulWidget {
#override
_SampleState createState() => _SampleState();
}
class _SampleState extends State<Sample> {
Widget result;
#override
void initState() {
super.initState();
checkStatus();
}
void checkStatus() async {
var connectivityResult = await (Connectivity().checkConnectivity());
if (connectivityResult == ConnectivityResult.mobile) {
result = Text("Connected to Mobile Network");
setState(() {});
} else if (connectivityResult == ConnectivityResult.wifi) {
result = Text("Connected to WiFi");
print("Connected to WiFi");
setState(() {});
} else {
result = Text("Unable to connect. Please Check Internet Connection");
setState(() {});
print("Unable to connect. Please Check Internet Connection");
}
}
#override
Widget build(BuildContext context) {
return Center(child: result);
}
}
Try this:
Use this package for checking Internet:
data_connection_checker:
And, Inside your stateful class create stream listener i.e and a boolean value.
StreamSubscription<DataConnectionStatus> listener; bool isConnected = true;
and Inside initState:
#override
void initState() {
super.initState();
listener = DataConnectionChecker().onStatusChange.listen((status) {
switch (status) {
case DataConnectionStatus.connected:
print('Data connection is available. $status');
setState(() {
isConnected = true;
});
break;
case DataConnectionStatus.disconnected:
print('You are disconnected from the internet. $status');
setState(() {
isConnected = false;
});
break;
}
});
}
Done, This will keep listening to changes in your internet status, Thus you can prompt user as you like. Cheers, Feel free to ask if confusion and if it helps upvote :D

How to show message to the snackBar when user does not have internet in flutter app?

if internet connection is off i want to show "No internet connection" message in SnackBar.
if internet connection is on it will show UI.
This is my code:
import 'dart:io';
import 'package:flutter/material.dart';
import 'main.dart';
class InternetCheck extends StatefulWidget {
#override
_InternetState createState() => _InternetState();
}
class _InternetState extends State<InternetCheck> {
bool _isInternet = true;
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
checkInternet() async {
try {
final response = await InternetAddress.lookup('example.com'); // google
if (response.isNotEmpty && response[0].rawAddress.isNotEmpty) {
_isInternet = true; // internet
setState(() {});
}
} on SocketException catch (_) {
_isInternet = false; // no internet
setState(() {
_showSnackBar();
});
}
return _isInternet;
}
#override
void initState() {
checkInternet();
super.initState();
}
void _showSnackBar() {
SnackBar snackBar = SnackBar(content: Text('No Connection'));
_scaffoldKey.currentState.showSnackBar(snackBar);
}
#override
Widget build(BuildContext context) {
// checkInternet();
return MaterialApp(
home: Scaffold(
key: _scaffoldKey,
body: _isInternet == true ? Text('internet') : Text('no Internet'),
),
);
}
}
using my code when app run first time with internet off it show SnackBar but when i switch internet on and again switch internet off then it will not showing snakbar.
Check out the connectivity package. It allows you to listen for network state changes :
#override
initState() {
super.initState();
subscription = Connectivity().onConnectivityChanged.listen((ConnectivityResult result) {
if(connectivityResult == ConnectivityResult.none)
_showSnackbar();
})
}
// Be sure to cancel subscription after you are done
#override
dispose() {
super.dispose();
subscription.cancel();
}

Fetch data when internet connection comes back in Flutter

I'm developing an app that fetchs some data from the internet. In order to avoid issues with the internet connection I added the connectivity package.
If internet is connected when the app starts and then the internet connection is switched off, I can display a Container with the Text of "no internet". If I switch internet on again, the data is displayed.
The code to achive this is the following:
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:connectivity/connectivity.dart';
class CheckNetworkPage extends StatefulWidget {
#override
_CheckNetworkPageState createState() => _CheckNetworkPageState();
}
class _CheckNetworkPageState extends State<CheckNetworkPage> {
StreamSubscription<ConnectivityResult> _networkSubscription;
Future<List<Data>> fetchData() async {
// Code to fetch data
}
#override
initState() {
super.initState();
fetchData();
_networkSubscription = Connectivity().onConnectivityChanged.listen((ConnectivityResult result) {
_connectionStatus = result.toString();
print(_connectionStatus);
if (result == ConnectivityResult.wifi ||
result == ConnectivityResult.mobile ||
result == ConnectivityResult.none) {
print("Result: $result");
setState(() {});
}
});
}
// Cancel subscription after you are done
#override
dispose() {
super.dispose();
_networkSubscription.cancel();
}
#override
Widget build(BuildContext context) {
// More code. I can use the result of _connectionStatus to build my app
}
}
However, if the app starts without internet, when I switch it on, the data doesn't load, as it is fetched in initState().
How to fetch the data when it was no fetched before and internet connection is switched on?
You could store latest fetched data in a variable.
List<Data> fetchedData;
Future<List<Data>> fetchData() async {
// Code to fetch data
// Add this :
fetchedData = ...
}
Then in your listener, check whether this data is defined :
if (result == ConnectivityResult.wifi ||
result == ConnectivityResult.mobile ||
result == ConnectivityResult.none) {
print("Result: $result");
setState(() {});
// Add this :
if (fetchedData == null) fetchData()
}