243 votes

Vérifiez s'il y a une connexion Internet disponible sur l'application Flutter

J'ai un appel réseau à exécuter. Mais avant de le faire, je dois vérifier si l'appareil a une connectivité Internet.

Voici ce que j'ai fait jusqu'à présent:

  var connectivityResult = new Connectivity().checkConnectivity();// Classe définie par l'utilisateur
    if (connectivityResult == ConnectivityResult.mobile ||
        connectivityResult == ConnectivityResult.wifi) {*/
    this.getData();
    } else {
      neverSatisfied();
    }

La méthode ci-dessus ne fonctionne pas.

391voto

Günter Zöchbauer Points 21340

Le plugin de connectivité indique dans sa documentation qu'il ne fournit que des informations s'il y a une connexion réseau, mais pas si le réseau est connecté à Internet

Notez que sur Android, cela ne garantit pas la connexion à Internet. Par exemple, l'application pourrait avoir un accès wifi mais il pourrait s'agir d'un VPN ou d'un wifi d'hôtel sans accès.

Vous pouvez utiliser

import 'dart:io';
...
try {
  final result = await InternetAddress.lookup('example.com');
  if (result.isNotEmpty && result[0].rawAddress.isNotEmpty) {
    print('connecté');
  }
} on SocketException catch (_) {
  print('non connecté');
}

Mise à jour

Le package de connectivité est obsolète. Utilisez plutôt le package officiel de la communauté Flutter connectivity_plus.

3 votes

Je reçois l'erreur "isNotEmpty n'est pas déclaré à l'intérieur de InternetAddress"

0 votes

Ups, j'ai déjà supprimé le code localement, mais je pense que cela devrait être result[0].rawAddress.isNotEmpty. Désolé pour ça.

0 votes

Je rencontre des erreurs sur ce code ainsi que sur `on SocketException catch(_)`. Dit que on est indéfini.

130voto

dennmat Points 703

À toute personne qui atterrit ici, j'aimerais ajouter à la réponse de Günter Zöchbauer que voici ma solution pour implémenter une utilité pour savoir s'il y a internet ou non, peu importe tout le reste.

Avertissement :

Je suis novice à la fois en Dart et en Flutter, donc ce n'est peut-être pas la meilleure approche, mais j'aimerais recevoir des retours.


Combinaison de flutter_connectivity et du test de connexion de Günter Zöchbauer

Mes exigences

Je ne voulais pas avoir du code répété partout où je devais vérifier la connexion et je voulais qu'elle mette automatiquement à jour les composants ou tout autre élément qui se soucie de la connexion à chaque changement.

ConnectionStatusSingleton

Tout d'abord, nous mettons en place un Singleton. Si vous n'êtes pas familier avec ce modèle, il y a beaucoup d'informations disponibles en ligne à ce sujet. L'idée est de créer une seule instance d'une classe pendant le cycle de vie de l'application et de pouvoir l'utiliser n'importe où.

Ce singleton se connecte à flutter_connectivity et écoute les changements de connectivité, testant ensuite la connexion réseau, puis utilisant un StreamController pour mettre à jour tout élément qui en a besoin.

Voici à quoi cela ressemble :

import 'dart:io'; //Utilitaire InternetAddress
import 'dart:async'; //Pour StreamController/Stream

import 'package:connectivity/connectivity.dart';

class ConnectionStatusSingleton {
    //Cela crée la seule instance en appelant le constructeur `_internal` spécifié ci-dessous
    static final ConnectionStatusSingleton _singleton = new ConnectionStatusSingleton._internal();
    ConnectionStatusSingleton._internal();

    //C'est ce qui est utilisé pour récupérer l'instance dans l'application
    static ConnectionStatusSingleton getInstance() => _singleton;

    //Cela suit l'état actuel de la connexion
    bool hasConnection = false;

    //C'est ainsi que nous permettrons de s'abonner aux changements de la connexion
    StreamController connectionChangeController = new StreamController.broadcast();

    //flutter_connectivity
    final Connectivity _connectivity = Connectivity();

    //Se connecter au Stream de flutter_connectivity pour écouter les changements
    //Et vérifier l'état de la connexion dès le départ
    void initialize() {
        _connectivity.onConnectivityChanged.listen(_connectionChange);
        checkConnection();
    }

    Stream get connectionChange => connectionChangeController.stream;

    //Une méthode de nettoyage pour fermer notre StreamController
    //   Comme cela est censé exister pendant tout le cycle de vie de l'application, ce n'est pas
    //   vraiment un problème
    void dispose() {
        connectionChangeController.close();
    }

    //Écouteur de flutter_connectivity
    void _connectionChange(ConnectivityResult result) {
        checkConnection();
    }

    //Le test pour voir effectivement s'il y a une connexion
    Future checkConnection() async {
        bool previousConnection = hasConnection;

        try {
            final result = await InternetAddress.lookup('google.com');
            if (result.isNotEmpty && result[0].rawAddress.isNotEmpty) {
                hasConnection = true;
            } else {
                hasConnection = false;
            }
        } on SocketException catch(_) {
            hasConnection = false;
        }

        //Le statut de connexion a changé, envoyer une mise à jour à tous les auditeurs
        if (previousConnection != hasConnection) {
            connectionChangeController.add(hasConnection);
        }

        return hasConnection;
    }
}

Utilisation

Initialisation

Tout d'abord, nous devons nous assurer d'appeler l'initialisation de notre singleton. Mais une seule fois. C'est à vous de décider, mais je l'ai fait dans la fonction main() de mon application :

void main() {
    ConnectionStatusSingleton connectionStatus = ConnectionStatusSingleton.getInstance();
    connectionStatus.initialize();

    runApp(MyApp());

    //Appelez ceci si l'initialisation se produit dans un contexte qui se terminera pendant le cycle de vie de l'application
    //connectionStatus.dispose();   
}

Dans un Widget ou ailleurs

import 'dart:async'; //Pour StreamSubscription

...

class MyWidgetState extends State {
    StreamSubscription _connectionChangeStream;

    bool isOffline = false;

    @override
    initState() {
        super.initState();

        ConnectionStatusSingleton connectionStatus = ConnectionStatusSingleton.getInstance();
        _connectionChangeStream = connectionStatus.connectionChange.listen(connectionChanged);
    }

    void connectionChanged(dynamic hasConnection) {
        setState(() {
            isOffline = !hasConnection;
        });
    }

    @override
    Widget build(BuildContext ctxt) {
        ...
    }
}

J'espère que quelqu'un d'autre trouvera cela utile !


Référentiel Github d'exemple : https://github.com/dennmat/flutter-connectiontest-example

Activez le mode avion dans l'émulateur pour voir le résultat

0 votes

J'ai mis le premier code dans Main.dart et j'ai essayé avec une HomePage, mais cela lance l'erreur suivante : Could not load source 'dart:async/broadcast_stream_controller.dart': .

0 votes

Il y a vraisemblablement une autre erreur et c'est juste l'éditeur qui essaie d'ouvrir le fichier mais n'a pas accès à celui-ci. J'ai modifié cet exemple à partir de mon code pour le généraliser. J'ai peut-être cassé quelque chose. Je vérifierai quand je serai rentré à la maison. Mais si vous regardez le panneau de débogage, pouvez-vous trouver l'erreur réelle?

3 votes

Je suis désolé, je n'ai pas trouvé de balises HTML dans votre texte.

123voto

CopsOnRoad Points 4705

Code Null Safe :

  • Vérification unique :

    Créez cette méthode :

    Future hasNetwork() async {
      try {
        final result = await InternetAddress.lookup('example.com');
        return result.isNotEmpty && result[0].rawAddress.isNotEmpty;
      } on SocketException catch (_) {
        return false;
      }
    }

    Utilisation :

    bool isOnline = await hasNetwork();
  • Mise en place d'un écouteur :

    Ajoutez la dépendance suivante à votre fichier pubspec.yaml.

    connectivity_plus: ^2.0.2

    Code complet :

    void main() => runApp(MaterialApp(home: HomePage()));
    
    class HomePage extends StatefulWidget {
      @override
      _HomePageState createState() => _HomePageState();
    }
    
    class _HomePageState extends State {
      Map _source = {ConnectivityResult.none: false};
      final MyConnectivity _connectivity = MyConnectivity.instance;
    
      @override
      void initState() {
        super.initState();
        _connectivity.initialise();
        _connectivity.myStream.listen((source) {
          setState(() => _source = source);
        });
      }
    
      @override
      Widget build(BuildContext context) {
        String string;
        switch (_source.keys.toList()[0]) {
          case ConnectivityResult.mobile:
            string = 'Mobile : En ligne';
            break;
          case ConnectivityResult.wifi:
            string = 'WiFi : En ligne';
            break;
          case ConnectivityResult.none:
          default:
            string = 'Hors ligne';
        }
    
        return Scaffold(
          body: Center(child: Text(string)),
        );
      }
    
      @override
      void dispose() {
        _connectivity.disposeStream();
        super.dispose();
      }
    }
    
    class MyConnectivity {
      MyConnectivity._();
    
      static final _instance = MyConnectivity._();
      static MyConnectivity get instance => _instance;
      final _connectivity = Connectivity();
      final _controller = StreamController.broadcast();
      Stream get myStream => _controller.stream;
    
      void initialise() async {
        ConnectivityResult result = await _connectivity.checkConnectivity();
        _checkStatus(result);
        _connectivity.onConnectivityChanged.listen((result) {
          _checkStatus(result);
        });
      }
    
      void _checkStatus(ConnectivityResult result) async {
        bool isOnline = false;
        try {
          final result = await InternetAddress.lookup('example.com');
          isOnline = result.isNotEmpty && result[0].rawAddress.isNotEmpty;
        } on SocketException catch (_) {
          isOnline = false;
        }
        _controller.sink.add({result: isOnline});
      }
    
      void disposeStream() => _controller.close();
    }

Capture d'écran :

description de l'image

Crédit à : <a href="https://pub.dev/packages/connectivity_plus" rel="noreferrer">connectivity_plus</a> et Günter Zöchbauer

0 votes

Via firebase, est-il possible avec le SDK ?

0 votes

@LOG_TAG Vous n'avez pas besoin d'utiliser Firebase pour cela.

0 votes

Map _source = {ConnectivityResult.none: false}; Pourquoi avez-vous utilisé "false" ici

24voto

Tushar Pandey Points 417

En utilisant

dépendances:
  connectivité: ^0.4.2

ce que nous avons trouvé dans les ressources est

      import 'package:connectivity/connectivity.dart';

      Future vérifier() async {
        var résultatConnectivité = await (Connectivity().checkConnectivity());
        if (résultatConnectivité == ConnectivityResult.mobile) {
          return true;
        } else if (résultatConnectivité == ConnectivityResult.wifi) {
          return true;
        }
        return false;
      }

Le Future est un peu problématique pour moi, nous devons l'implémenter à chaque fois comme suit :

vérifier().then((intenet) {
      if (intenet != null && intenet) {
        // Cas de présence d'Internet
      }
      // Cas de non-Internet
    });

Donc, pour résoudre ce problème, j'ai créé une classe qui accepte une fonction avec le paramètre de type boolean isNetworkPresent comme ceci

nomDeLaMéthode(bool isNetworkPresent){}

Et la classe utilitaire est

import 'package:connectivity/connectivity.dart';

class VérificationRéseau {
  Future vérifier() async {
    var résultatConnectivité = await (Connectivity().checkConnectivity());
    if (résultatConnectivité == ConnectivityResult.mobile) {
      return true;
    } else if (résultatConnectivité == ConnectivityResult.wifi) {
      return true;
    }
    return false;
  }

  dynamic vérifierInternet(Function func) {
    vérifier().then((intenet) {
      if (intenet != null && intenet) {
        func(true);
      }
      else{
    func(false);
  }
    });
  }
}

Et pour utiliser l'utilitaire de vérification de connectivité

  récupérerPréférence(bool isNetworkPresent) {
    if(isNetworkPresent){

    }else{

    }
  }

je vais utiliser cette syntaxe

VérificationRéseau vérificationRéseau = new VérificationRéseau();
vérificationRéseau.vérifierInternet(récupérerPréférence)

0 votes

Ce package est obsolète et a été remplacé par Connectivity Plus

7voto

kristiyan.mitev Points 163

J'ai créé un package qui (je pense) traite de manière fiable ce problème.

Le package sur pub.dev

Le package sur GitHub

La discussion est la bienvenue. Vous pouvez utiliser le suivi des problèmes sur GitHub.


Je ne pense plus que la méthode ci-dessous soit fiable :


Voulez-vous ajouter quelque chose à @Oren's réponse: vous devriez vraiment ajouter un autre catch, qui capturera toutes les autres exceptions (pour être sûr), OU tout simplement supprimer complètement le type d'exception et utiliser un catch qui gère toutes les exceptions:

Cas 1:

try {
  await Firestore.instance
    .runTransaction((Transaction tx) {})
    .timeout(Duration(seconds: 5));
  hasConnection = true;
} on PlatformException catch(_) { // Peut être levée en mode avion
  hasConnection = false;
} on TimeoutException catch(_) {
  hasConnection = false;
} catch (_) {
  hasConnection = false;
}

ou encore plus simple...

Cas 2:

try {
  await Firestore.instance
    .runTransaction((Transaction tx) {})
    .timeout(Duration(seconds: 5));
  hasConnection = true;
} catch (_) {
  hasConnection = false;
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X