spotube/lib/services/connectivity_adapter.dart
2023-10-14 12:31:10 +06:00

96 lines
2.2 KiB
Dart

import 'dart:async';
import 'dart:io';
import 'package:fl_query/fl_query.dart';
import 'package:flutter/widgets.dart';
class FlQueryInternetConnectionCheckerAdapter extends ConnectivityAdapter
with WidgetsBindingObserver {
final _connectionStreamController = StreamController<bool>.broadcast();
FlQueryInternetConnectionCheckerAdapter() : super() {
Timer.periodic(const Duration(minutes: 3), (timer) async {
if (WidgetsBinding.instance.lifecycleState == AppLifecycleState.paused) {
return;
}
await isConnected;
});
}
@override
didChangeAppLifecycleState(AppLifecycleState state) async {
if (state == AppLifecycleState.resumed) {
await isConnected;
}
}
final vpnNames = [
'tun',
'tap',
'ppp',
'pptp',
'l2tp',
'ipsec',
'vpn',
'wireguard',
'openvpn',
'softether',
'proton',
'strongswan',
'cisco',
'forticlient',
'fortinet',
'hideme',
'hidemy',
'hideman',
'hidester',
'lightway',
];
Future<bool> isVpnActive() async {
final interfaces = await NetworkInterface.list(
includeLoopback: false,
type: InternetAddressType.any,
);
if (interfaces.isEmpty) {
return false;
}
return interfaces.any(
(interface) =>
vpnNames.any((name) => interface.name.toLowerCase().contains(name)),
);
}
Future<bool> doesConnectTo(String address) async {
try {
final result = await InternetAddress.lookup(address);
if (result.isNotEmpty && result[0].rawAddress.isNotEmpty) {
return true;
}
return false;
} on SocketException catch (_) {
return false;
}
}
Future<bool> _isConnected() async {
return await doesConnectTo('google.com') ||
await doesConnectTo('www.baidu.com') || // for China
await isVpnActive(); // when VPN is active that means we are connected
}
@override
Future<bool> get isConnected async {
final connected = await _isConnected();
if (connected != isConnectedSync /*previous value*/) {
_connectionStreamController.add(connected);
}
return connected;
}
@override
Stream<bool> get onConnectivityChanged => _connectionStreamController.stream;
}