I would like to make my flutter application to be able to check the connection status and prompt a warning if the wifi and mobile network is turned off. However, I want to make this globally across the application which means the application will constantly listen for network changes until the application is exited. I do not know how to achieve that. I use Provider as the state management for my project. The package I use for checking the network status are internet_connection_checker and connectivity_plus.
main.dart
import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:provider/provider.dart';
import 'package:test/page/error.dart';
import 'package:test/routes.dart';
import 'package:test/service/connection_manager.dart';
import 'package:test/service/firebase_service.dart';
import 'package:test/firebase_options.dart';
import 'package:test/globals.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
await FirebaseService().initNotifications();
await FirebaseService().initFirebaseRemoteConfig();
int mainCount = 1;
try {
await deviceManager.getCurrentLocation();
print('Main() is executed for $mainCount time(s)');
mainCount ++;
} catch(e) {
print('Error getting current location: $e');
try {
await deviceManager.getLastestLocation();
} catch (e) {
print('Error getting latest location: $e');
}
}
FlutterError.onError = (FlutterErrorDetails details) {
runApp(const MaterialApp(
debugShowCheckedModeBanner: false,
home: AppErrorScreen(),
));
};
runApp(
MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => ConnectionManager()),
ChangeNotifierProvider(create: (_) => Globals()),
],
child: MyApp(),
),
);
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp.router(
routerConfig: AppRoute().route,
localizationsDelegates: AppLocalizations.localizationsDelegates,
supportedLocales: AppLocalizations.supportedLocales,
debugShowCheckedModeBanner: false,
);
}
}
connection.dart
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:connectivity_plus/connectivity_plus.dart';
class ConnectionManager with ChangeNotifier {
final Connectivity _connectivity = Connectivity();
bool _isConnected = false;
late StreamSubscription<List<ConnectivityResult>> _subscription;
bool get isConnected => _isConnected;
ConnectionManager() {
_subscription = _connectivity.onConnectivityChanged.listen(_updateConnectionStatus);
_checkInitialConnection();
}
Future<void> _checkInitialConnection() async {
final List<ConnectivityResult> connectivityResult = await _connectivity.checkConnectivity();
// await _updateConnectionStatus(connectivityResult);
}
Future<void> _updateConnectionStatus(List<ConnectivityResult> result) async {
bool isConnected = false;
if (result != ConnectivityResult.none) {
try {
final lookupResult = await InternetAddress.lookup('google.com');
isConnected = lookupResult.isNotEmpty;
} on SocketException catch (_) {
isConnected = false;
}
}
_isConnected = isConnected;
notifyListeners();
}
I have tried to make the connection check function into a stream however I am new to stream I am not quite sure how can I implement it across the application.
You can use it like this
Packages
connectivity_plus: "5.0.0"
internet_connection_checker:
Code
import 'package:flutter/material.dart';
import 'package:next_app_prototype/features/home/presentation/pages/home_page.dart';
import 'package:provider/provider.dart';
import 'dart:async';
import 'dart:io';
import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:internet_connection_checker/internet_connection_checker.dart';
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
runApp(
MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => ConnectionManager()),
],
child: const MyApp(),
),
);
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Home'),
),
body: Consumer<ConnectionManager>(
builder: (context, connectionManager, child) {
if (!connectionManager.isConnected) {
WidgetsBinding.instance.addPostFrameCallback((_) {
showDialog(
context: context,
builder: (context) => AlertDialog(
title: const Text('No Internet Connection'),
content: const Text('Please check your internet settings.'),
actions: <Widget>[
TextButton(
onPressed: () => Navigator.of(context).pop(),
child: const Text('OK'),
),
],
),
);
});
}
return const HomeScreen();
},
),
),
);
}
}
class HomeScreen extends StatefulWidget {
const HomeScreen({super.key});
@override
State<HomeScreen> createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
@override
Widget build(BuildContext context) {
return const Center(child: Text('Home Page'));
}
}
class ConnectionManager with ChangeNotifier {
final Connectivity _connectivity = Connectivity();
bool _isConnected = true;
late StreamSubscription<ConnectivityResult> _subscription;
late StreamSubscription<InternetConnectionStatus> _internetSubscription;
bool get isConnected => _isConnected;
ConnectionManager() {
_subscription = _connectivity.onConnectivityChanged.listen(_updateConnectivityStatus);
_internetSubscription = InternetConnectionChecker().onStatusChange.listen(_updateInternetStatus);
_checkInitialConnection();
}
Future<void> _checkInitialConnection() async {
final connectivityResult = await _connectivity.checkConnectivity();
await _updateConnectivityStatus(connectivityResult);
final internetResult = await InternetConnectionChecker().hasConnection;
_updateInternetStatus(internetResult ? InternetConnectionStatus.connected : InternetConnectionStatus.disconnected);
}
Future<void> _updateConnectivityStatus(ConnectivityResult result) async {
_isConnected = result != ConnectivityResult.none;
if (_isConnected) {
try {
final lookupResult = await InternetAddress.lookup('google.com');
_isConnected = lookupResult.isNotEmpty && lookupResult[0].rawAddress.isNotEmpty;
} on SocketException catch (_) {
_isConnected = false;
}
}
notifyListeners();
}
Future<void> _updateInternetStatus(InternetConnectionStatus status) async {
_isConnected = status == InternetConnectionStatus.connected;
notifyListeners();
}
@override
void dispose() {
_subscription.cancel();
_internetSubscription.cancel();
super.dispose();
}
}