J'ai eu un problème avec les solutions proposées, l'utilisation lookup
ne renvoie pas toujours la valeur attendue.
Cela est dû à la mise en cache DNS, la valeur de l'appel est mise en cache et au lieu de faire un appel approprié lors du prochain essai, il rend la valeur mise en cache. Bien sûr, c'est un problème ici car cela signifie que si vous perdez la connectivité et que vous l'appelez, lookup
il pourrait toujours renvoyer la valeur mise en cache comme si vous aviez Internet, et inversement, si vous reconnectez votre Internet après avoir lookup
renvoyé null, il renverra toujours null pendant la durée du cache, ce qui peut durer quelques minutes, même si vous disposez maintenant d'Internet.
TL; DR: lookup
retourner quelque chose ne signifie pas nécessairement que vous avez Internet, et ne rien renvoyer ne signifie pas nécessairement que vous n'avez pas Internet. Ce n'est pas fiable.
J'ai implémenté la solution suivante en m'inspirant du data_connection_checker
plugin:
Future<bool> _checkInternetAccess() {
final List<InternetAddress> dnss = [
InternetAddress('8.8.8.8', type: InternetAddressType.IPv4),
InternetAddress('2001:4860:4860::8888', type: InternetAddressType.IPv6),
InternetAddress('1.1.1.1', type: InternetAddressType.IPv4),
InternetAddress('2606:4700:4700::1111', type: InternetAddressType.IPv6),
InternetAddress('208.67.222.222', type: InternetAddressType.IPv4),
InternetAddress('2620:0:ccc::2', type: InternetAddressType.IPv6),
InternetAddress('180.76.76.76', type: InternetAddressType.IPv4),
InternetAddress('2400:da00::6666', type: InternetAddressType.IPv6),
];
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;
}
L'appel à _checkInternetAccess
prend au plus une durée de timeout
pour se terminer (3 secondes ici), et si nous pouvons atteindre l'un des DNS, il se terminera dès que le premier est atteint, sans attendre les autres (car en atteindre un suffit pour sachez que vous avez Internet). Tous les appels à _pingDns
se font en parallèle.
Cela semble bien fonctionner sur un réseau IPV4, et quand je ne peux pas le tester sur un réseau IPV6 (je n'ai pas accès à un), je pense que cela devrait toujours fonctionner. Cela fonctionne également sur les versions en mode version, mais je dois encore soumettre mon application à Apple pour voir s'ils rencontrent un problème avec cette solution.
Cela devrait également fonctionner dans la plupart des pays (y compris la Chine), si cela ne fonctionne pas dans l'un d'entre eux, vous pouvez ajouter un DNS à la liste accessible depuis votre pays cible.