webentwicklung-frage-antwort-db.com.de

Prüfen Sie, ob in der Flutter-App eine Internetverbindung verfügbar ist

Ich muss einen Netzwerkanruf ausführen. Zuvor muss ich jedoch überprüfen, ob das Gerät über eine Internetverbindung verfügt.

Das habe ich bisher gemacht:

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

Obige Methode funktioniert nicht.

10
Rissmon Suresh

Das connectivity-Plugin gibt in seinen Dokumenten an, dass es nur Informationen bereitstellt, wenn eine Netzwerkverbindung besteht, nicht aber, wenn das Netzwerk mit dem Internet verbunden ist

Beachten Sie, dass auf Android die Verbindung zum Internet nicht garantiert wird. Zum Beispiel kann die App über WLAN verfügen, es kann sich jedoch um ein VPN oder ein Hotel-WLAN ohne Zugriff handeln.

Sie können verwenden 

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

Für alle anderen, die hier landen, möchte ich die Antwort von Günter Zöchbauer hinzufügen. Dies war meine Lösung, ein Dienstprogramm zu implementieren, um zu wissen, ob es Internet gibt oder nicht.

Haftungsausschluss:

Ich bin neu bei Dart und Flutter, daher ist dies möglicherweise nicht der beste Ansatz, würde aber gerne Feedback erhalten.


Flutter_connectivity und den Verbindungstest von Günter Zöchbauer

Meine Anforderungen

Ich wollte nicht an jeder Stelle, an der ich die Verbindung überprüfen wollte, einen Haufen wiederholten Codes haben, und ich wollte, dass Komponenten oder alles andere, was die Verbindung betraf, automatisch aktualisiert werden, wenn sich Änderungen ergeben.

ConnectionStatusSingleton

Zuerst richten wir ein Singleton ein. Wenn Sie mit diesem Muster nicht vertraut sind, gibt es im Internet viele gute Informationen. Das Wichtigste ist jedoch, dass Sie während des Anwendungslebenszyklus eine einzelne Instanz einer Klasse erstellen und sie überall verwenden möchten.

Dieses Singleton hakt sich in flutter_connectivity ein, wartet auf Konnektivitätsänderungen, testet dann die Netzwerkverbindung und verwendet dann eine StreamController, um alle relevanten Informationen zu aktualisieren.

Es sieht aus wie das:

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;
    }
}

Verwendungszweck

Initialisierung

Zuerst müssen wir sicherstellen, dass wir die Initialisierung unseres Singleton nennen. Aber nur einmal ... Das ist Teil von dir, aber ich habe es in meiner App main() gemacht:

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();   
}

In Widget oder anderswo

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) {
        ...
    }
}

Hoffe, jemand anderes findet das nützlich!


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

Schalten Sie den Flugzeugmodus im Emulator um, um das Ergebnis zu sehen

4
dennmat

Ich habe ein Paket erstellt, das sich (meiner Meinung nach) zuverlässig mit diesem Problem befasst.

Das Paket auf pub.dev

Das Paket auf GitHub

Diskussion ist sehr willkommen. Sie können den Issues Tracker auf GitHub verwenden.


Ich halte das unten nicht mehr für eine verlässliche Methode:


Möchte etwas hinzufügen zu @ Oren's Antwort: Du solltest wirklich einen weiteren Fang hinzufügen, der alle anderen Ausnahmen abfängt (nur um sicher zu gehen), OR entfernen Sie einfach die Ausnahme tippe alles zusammen und benutze einen catch, der alle Ausnahmen behandelt:

Fall 1:

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;
} catch (_) {
  hasConnection = false;
}

oder noch einfacher ...

Fall 2:


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

enter image description here

Vollständiges Beispiel für einen Listener der Internetverbindung und ihrer Quelle.

Dank an: Konnektivität und Günter Zöchbauer

import 'Dart:async';
import 'Dart:io';
import 'package:connectivity/connectivity.Dart';
import 'package:flutter/material.Dart';

void main() => runApp(MaterialApp(home: HomePage()));

class HomePage extends StatefulWidget {
  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  Map _source = {ConnectivityResult.none: false};
  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.none:
        string = "Offline";
        break;
      case ConnectivityResult.mobile:
        string = "Mobile: Online";
        break;
      case ConnectivityResult.wifi:
        string = "WiFi: Online";
    }

    return Scaffold(
      appBar: AppBar(title: Text("Internet")),
      body: Center(child: Text("$string", style: TextStyle(fontSize: 36))),
    );
  }

  @override
  void dispose() {
    _connectivity.disposeStream();
    super.dispose();
  }
}

class MyConnectivity {
  MyConnectivity._internal();

  static final MyConnectivity _instance = MyConnectivity._internal();

  static MyConnectivity get instance => _instance;

  Connectivity connectivity = Connectivity();

  StreamController 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');
      if (result.isNotEmpty && result[0].rawAddress.isNotEmpty) {
        isOnline = true;
      } else
        isOnline = false;
    } on SocketException catch (_) {
      isOnline = false;
    }
    controller.sink.add({result: isOnline});
  }

  void disposeStream() => controller.close();
}
2
CopsOnRoad

Ich habe eine Basisklasse für den Widget-Status erstellt

Verwendung anstelle von State<LoginPage> verwenden BaseState<LoginPage> dann verwende einfach die boolesche Variable isOnline

Text(isOnline ? 'is Online' : 'is Offline')

Fügen Sie zunächst das Konnektivitäts-Plugin hinzu:

dependencies:
  connectivity: ^0.4.3+2

Fügen Sie dann die BaseState-Klasse hinzu

import 'Dart:async';
import 'Dart:io';
import 'package:flutter/services.Dart';

import 'package:connectivity/connectivity.Dart';
import 'package:flutter/widgets.Dart';

/// a base class for any statful widget for checking internet connectivity
abstract class BaseState<T extends StatefulWidget> extends State {
  final Connectivity _connectivity = Connectivity();

  StreamSubscription<ConnectivityResult> _connectivitySubscription;

  /// the internet connectivity status
  bool isOnline = true;

  /// initialize connectivity checking
  /// Platform messages are asynchronous, so we initialize in an async method.
  Future<void> initConnectivity() async {
    // Platform messages may fail, so we use a try/catch PlatformException.
    try {
      await _connectivity.checkConnectivity();
    } on PlatformException catch (e) {
      print(e.toString());
    }

    // If the widget was removed from the tree while the asynchronous platform
    // message was in flight, we want to discard the reply rather than calling
    // setState to update our non-existent appearance.
    if (!mounted) {
      return;
    }

    await _updateConnectionStatus().then((bool isConnected) => setState(() {
          isOnline = isConnected;
        }));
  }

  @override
  void initState() {
    super.initState();
    initConnectivity();
    _connectivitySubscription = Connectivity()
        .onConnectivityChanged
        .listen((ConnectivityResult result) async {
      await _updateConnectionStatus().then((bool isConnected) => setState(() {
            isOnline = isConnected;
          }));
    });
  }

  @override
  void dispose() {
    _connectivitySubscription.cancel();
    super.dispose();
  }

  Future<bool> _updateConnectionStatus() async {
    bool isConnected;
    try {
      final List<InternetAddress> result =
          await InternetAddress.lookup('google.com');
      if (result.isNotEmpty && result[0].rawAddress.isNotEmpty) {
        isConnected = true;
      }
    } on SocketException catch (_) {
      isConnected = false;
      return false;
    }
    return isConnected;
  }
}
1
amorenew

Nach @dennmatt's answer habe ich festgestellt, dass InternetAddress.lookup auch bei ausgeschalteter Internetverbindung zu erfolgreichen Ergebnissen führen kann. Ich habe es getestet, indem ich eine Verbindung zwischen meinem Simulator und meinem WLAN hergestellt habe und dann das Kabel meines Routers abgezogen habe. Ich denke, der Grund ist, dass der Router die Domain-Lookup-Ergebnisse zwischenspeichert, sodass er die DNS-Server nicht bei jeder Suchabfrage abfragen muss.

Wenn Sie Firestore wie mich verwenden, können Sie den Block try-SocketException-catch durch eine leere Transaktion ersetzen und TimeoutExceptions abrufen:

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;
}

Beachten Sie auch, dass previousConnection vor der asynchronen Intenet-Prüfung gesetzt ist. Wenn checkConnection() in kurzer Zeit mehrfach aufgerufen wird, könnte es mehrere hasConnection=true hintereinander oder mehrere hasConnection=false hintereinander geben sicher, ob @dennmatt es absichtlich getan hat oder nicht, aber in unserem Anwendungsfall gab es keine Nebenwirkungen (setState wurde nur zweimal mit demselben Wert aufgerufen).

0
Oren

Verwenden 

dependencies:
  connectivity: ^0.4.2

was wir von resouces bekommen haben 

      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;
      }

Die Zukunft ist für mich wenig problematisch, wir müssen sie jedes Mal umsetzen, wie:

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

Um dieses Problem zu lösen, habe ich eine Klasse erstellt, die eine Funktion mit dem booleschen Parameter isNetworkPresent wie diesem akzeptiert 

methodName(bool isNetworkPresent){}

Und die Utility-Klasse ist 

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);
  }
    });
  }
}

Und Connectivity-Check-Dienstprogramme verwenden

  fetchPrefrence(bool isNetworkPresent) {
    if(isNetworkPresent){

    }else{

    }
  }

ich werde diese Syntax verwenden 

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