import 'dart:async'; import 'dart:io'; import 'package:fcs/config.dart'; import 'package:flutter/foundation.dart'; import 'package:logging/logging.dart'; import 'package:connectivity_plus/connectivity_plus.dart'; import 'api_helper.dart'; enum ConnectivityStatus { none, online } class NetworkConnectivity { final log = Logger('NetworkConnectivity'); static final NetworkConnectivity instance = NetworkConnectivity._internal(); static String _hostName = ""; static ConnectivityStatus? _currentResult; NetworkConnectivity._internal() { _initialise(); var uri = Uri.parse(Config.instance.apiURL); _hostName = uri.host; log.info("host name:$_hostName"); } Connectivity connectivity = Connectivity(); final StreamController _controller = StreamController.broadcast(); Stream get statusStream => _controller.stream; Timer? _checkTimer; void _initialise() async { await _checkStatus(await connectivity.checkConnectivity()); connectivity.onConnectivityChanged.listen((result) { if (_currentResult == null) { _checkStatus(result); } else { _checkTimer?.cancel(); _checkTimer = Timer(const Duration(seconds: 7), () { _checkTimer?.cancel(); _checkStatus(result); }); } }); } Future _checkStatus(List result) async { bool isOnline = false; if (!result.contains(ConnectivityResult.none) && !kIsWeb) { try { final hostNameLookup = await InternetAddress.lookup(_hostName); if (hostNameLookup.isNotEmpty && hostNameLookup[0].rawAddress.isNotEmpty) { if (await checkHeartbeat()) { isOnline = true; } } else { isOnline = false; } isOnline = true; } on Exception catch (_) { isOnline = false; } } _addStream(isOnline || kIsWeb ? ConnectivityStatus.online : ConnectivityStatus.none); } Future checkHeartbeat() async { try { var result = await requestAPI("/hb", "GET"); var status = result["status"]; if (status != null && status != "") { return true; } } catch (e) { return false; } return false; } void disposeStream() => _controller.close(); _addStream(ConnectivityStatus? updateResult) async { if (updateResult == null) return; if (updateResult == _currentResult) return; _currentResult = updateResult; if (!_controller.isClosed) { log.info("sink: $_currentResult"); _controller.sink.add(_currentResult!); } } }