web-dev-qa-db-fra.com

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

J'ai un appel réseau à exécuter. Mais avant cela, je dois vérifier si le périphérique dispose d'une connexion Internet.

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

  var connectivityResult = new Connectivity().checkConnectivity();// User defined class
    if (connectivityResult == ConnectivityResult.mobile ||
        connectivityResult == ConnectivityResult.wifi) {*/
    this.getData();
    } else {
      neverSatisfied();
    }

La méthode ci-dessus ne fonctionne pas.

10
Rissmon Suresh

Le plug-in connectivity indique dans sa documentation qu'il ne fournit des informations que s'il existe 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 peut avoir un accès wifi, mais il peut 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('google.com');
  if (result.isNotEmpty && result[0].rawAddress.isNotEmpty) {
    print('connected');
  }
} on SocketException catch (_) {
  print('not connected');
}
20

Pour ceux qui arrivent ici, j'aimerais ajouter quelque chose à la réponse de Günter Zöchbauer: telle était ma solution pour implémenter un utilitaire: savoir s'il existe un accès à Internet ou non.

Avertissement:

Dart et Flutter sont nouveaux pour moi, donc ce n’est peut-être pas la meilleure approche, mais j'aimerais beaucoup avoir vos commentaires.


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

Mes exigences

Je ne voulais pas avoir un tas de code répété n'importe où j'avais besoin de vérifier la connexion et je voulais qu'il mette à jour automatiquement les composants ou tout ce qui se souciait de la connexion chaque fois qu'il y avait un changement.

ConnectionStatusSingleton

Nous avons d'abord installé un Singleton. Si vous ne connaissez pas ce modèle, vous trouverez en ligne de nombreuses informations intéressantes à leur sujet. Mais, selon l’essentiel, vous souhaitez créer une instance unique d’une classe au cours du cycle de vie d’une application et pouvoir l’utiliser n’importe où.

Ce singleton s'accroche à flutter_connectivity et écoute les modifications de connectivité, puis teste la connexion réseau, puis utilise une StreamController pour mettre à jour tout ce qui est important.

Cela ressemble à ceci:

import 'Dart:io'; //InternetAddress utility
import 'Dart:async'; //For StreamController/Stream

import 'package:connectivity/connectivity.Dart';

class ConnectionStatusSingleton {
    //This creates the single instance by calling the `_internal` constructor specified below
    static final ConnectionStatusSingleton _singleton = new ConnectionStatusSingleton._internal();
    ConnectionStatusSingleton._internal();

    //This is what's used to retrieve the instance through the app
    static ConnectionStatusSingleton getInstance() => _singleton;

    //This tracks the current connection status
    bool hasConnection = false;

    //This is how we'll allow subscribing to connection changes
    StreamController connectionChangeController = new StreamController.broadcast();

    //flutter_connectivity
    final Connectivity _connectivity = Connectivity();

    //Hook into flutter_connectivity's Stream to listen for changes
    //And check the connection status out of the gate
    void initialize() {
        _connectivity.onConnectivityChanged.listen(_connectionChange);
        checkConnection();
    }

    Stream get connectionChange => connectionChangeController.stream;

    //A clean up method to close our StreamController
    //   Because this is meant to exist through the entire application life cycle this isn't
    //   really an issue
    void dispose() {
        connectionChangeController.close();
    }

    //flutter_connectivity's listener
    void _connectionChange(ConnectivityResult result) {
        checkConnection();
    }

    //The test to actually see if there is a connection
    Future<bool> 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;
        }

        //The connection status changed send out an update to all listeners
        if (previousConnection != hasConnection) {
            connectionChangeController.add(hasConnection);
        }

        return hasConnection;
    }
}

Usage

Initialisation

Nous devons d’abord nous assurer d’appeler l’initialisation de notre singleton. Mais seulement une fois . Ceci vous sépare mais je l'ai fait dans la fonction main() de mon application:

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

    runApp(MyApp());

    //Call this if initialization is occuring in a scope that will end during app lifecycle
    //connectionStatus.dispose();   
}

Dans Widget ou ailleurs

import 'Dart:async'; //For StreamSubscription

...

class MyWidgetState extends State<MyWidget> {
    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 trouve cela utile!


Exemple de repo github: https://github.com/dennmat/flutter-connectiontest-example

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

4
dennmat

Après @dennmatt answer , j’ai remarqué que InternetAddress.lookup pouvait donner de bons résultats même si la connexion Internet était désactivée. Je l’ai testée en le connectant depuis mon simulateur à mon réseau WiFi domestique, puis en débranchant le câble de mon routeur. Je pense que la raison en est que le routeur met en cache les résultats de la recherche de domaine, de sorte qu'il n'a pas à interroger les serveurs DNS à chaque demande de recherche.

Quoi qu'il en soit, si vous utilisez Firestore comme moi, vous pouvez remplacer le bloc try-SocketException-catch par une transaction vide et intercepter TimeoutExceptions:

try {
  await Firestore.instance.runTransaction((Transaction tx) {}).timeout(Duration(seconds: 5));
  hasConnection = true;
} on PlatformException catch(_) { // May be thrown on Airplane mode
  hasConnection = false;
} on TimeoutException catch(_) {
  hasConnection = false;
}

Veuillez également noter que previousConnection est défini avant la vérification asynchrone intenet, donc théoriquement, si checkConnection() est appelé plusieurs fois dans un court laps de temps, il pourrait y avoir plusieurs hasConnection=true dans une ligne ou plusieurs hasConnection=false dans une ligne . bien sûr si @dennmatt l'a fait exprès ou non, mais dans notre cas d'utilisation, il n'y a pas eu d'effets secondaires (setState n'a été appelé que deux fois avec la même valeur).

0
Oren

En utilisant 

dependencies:
  connectivity: ^0.4.2

ce que nous avons obtenu de ressources est 

      import 'package:connectivity/connectivity.Dart';

      Future<bool> check() async {
        var connectivityResult = await (Connectivity().checkConnectivity());
        if (connectivityResult == ConnectivityResult.mobile) {
          return true;
        } else if (connectivityResult == ConnectivityResult.wifi) {
          return true;
        }
        return false;
      }

L'avenir est peu problématique pour moi, nous devons le mettre en œuvre à chaque fois comme:

check().then((intenet) {
      if (intenet != null && intenet) {
        // Internet Present Case
      }
      // No-Internet Case
    });

Donc, pour résoudre ce problème, j'ai créé une classe qui accepte une fonction avec un paramètre boolean isNetworkPresent comme celui-ci. 

methodName(bool isNetworkPresent){}

Et la classe utilitaire est 

import 'package:connectivity/connectivity.Dart';

class NetworkCheck {
  Future<bool> check() async {
    var connectivityResult = await (Connectivity().checkConnectivity());
    if (connectivityResult == ConnectivityResult.mobile) {
      return true;
    } else if (connectivityResult == ConnectivityResult.wifi) {
      return true;
    }
    return false;
  }

  dynamic checkInternet(Function func) {
    check().then((intenet) {
      if (intenet != null && intenet) {
        func(true);
      }
      else{
    func(false);
  }
    });
  }
}

Et utiliser connectivity-check utilty

  fetchPrefrence(bool isNetworkPresent) {
    if(isNetworkPresent){

    }else{

    }
  }

je vais utiliser cette syntaxe 

NetworkCheck networkCheck = new NetworkCheck();
networkCheck.checkInternet(fetchPrefrence)
0
Tushar Pandey