Flutter uygulamasında mevcut bir İnternet bağlantısı olup olmadığını kontrol edin


99

Yürütülecek bir ağ çağrım var. Ancak bunu yapmadan önce cihazın internet bağlantısı olup olmadığını kontrol etmem gerekiyor.

Şimdiye kadar yaptığım şey bu:

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

Yukarıdaki yöntem çalışmıyor.

Yanıtlar:


193

Bağlantı , bir ağ bağlantısı varsa, ancak ağ Internet'e bağlı değilse, sadece bilgi sağlar yönündeki docs durumlarını eklentisi

Android'de bunun İnternet bağlantısını garanti etmediğini unutmayın. Örneğin, uygulamanın wifi erişimi olabilir, ancak bu bir VPN veya erişimi olmayan bir otel WiFi olabilir.

Kullanabilirsiniz

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

2
"İsNotEmpty, InternetAddress içinde bildirilmedi" hatası alıyorum
Rissmon Suresh

2
Bu arka planda başarılabilir mi? Sanki yürütmek için bekleyen ve internet için bekleyen bir görevler kuyruğum var, ancak uygulama kapalı mı?
Vidor Vistrom

60
Lütfen google.com’a Çin’in içinden erişilemediğini ve bu nedenle örneğin Çin'de kullanılması halinde takılacağını unutmayın. Hedef kitlenizi genişletmek için lütfen google.com'u kullanmaktan kaçının ve bunun yerine ornek.com'u kullanın. nihai sonuç = InternetAddress.lookup ('example.com') bekleniyor;
otboss

4
Bu benim için işe yaramıyor, if (result.isNotEmpty && result[0].rawAddress.isNotEmpty)wifi olduğunda ancak internet bağlantısı olmadığında doğru dönüyor.
Denn

5
Oh, evet, bunu tamamen unuttum! Aslında kullanmaya devam edebileceğimi düşünüyorum await, .timeoutsonra ekleyebilirim lookup().
Michel Feinstein

73

Buraya gelenler için Günter Zöchbauer'in cevabına eklemek istiyorum ki bu, başka herhangi bir şeyden bağımsız olarak internet olup olmadığını bilmek için bir yardımcı program uygulamak için benim çözümümdü.

Feragatname:

Hem Dart hem de Flutter'da yeniyim, bu yüzden bu en iyi yaklaşım olmayabilir, ancak geri bildirim almayı çok isterim.


Flutter_connectivity ile Günter Zöchbauer'in bağlantı testini birleştirmek

Gereksinimlerim

Bağlantıyı kontrol etmem gereken herhangi bir yerde bir sürü tekrarlanan kod olmasını istemiyordum ve her değişiklik olduğunda bileşenleri veya bağlantıyla ilgilenen diğer her şeyi otomatik olarak güncellemesini istedim.

ConnectionStatusSingleton

Önce bir Singleton kurarız. Bu kalıba aşina değilseniz, çevrimiçi olarak onlar hakkında birçok iyi bilgi var. Ancak işin özü, uygulama yaşam döngüsü boyunca bir sınıfın tek bir örneğini oluşturmak ve onu her yerde kullanmak istemenizdir.

Bu singleton flutter_connectivity, bağlantı değişikliklerine bağlanır ve bunları dinler, ardından ağ bağlantısını test eder, ardından önemli StreamControllerolan her şeyi güncellemek için a kullanır .

Şöyle görünüyor:

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

Kullanım

Başlatma

Öncelikle, singleton'umuzu başlattığımızdan emin olmalıyız. Ama sadece bir kez. Bu kısım size kalmış ama bunu uygulamamda yaptım main():

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

İçinde Widgetveya başka bir yerde

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

Umarım başka biri bunu yararlı bulur!


Örnek github deposu: https://github.com/dennmat/flutter-connectiontest-example

Sonucu görmek için emülatörde uçak modunu değiştirin


2
Kodu test ettim ve benim için çalışıyor, yardım etmek için daha fazla bilgiye ihtiyacım var.
dennmat

3
Ahh, tamam görüyorum. Bu nedenle, gelecekteki referansınız için, gönderdiğiniz hata yalnızca editörün hatanın oluştuğunu düşündüğü dosyayı açmaya çalışmasıdır. Gerçek hata, editörlerinizin hata ayıklama konsolunda / yığın izleme panelinde mevcut olmalıdır. Sanırım runApp geri dönüyor, programın tüm ömrü boyunca çalışacağını varsaydım. Bunun temelde olduğunu görmek, burada imha etmek gerçekten gerekli değildir, bu yüzden yukarıdaki gibi connectionStatus.dispose()kurduğunuzu varsayarak kaldırın main(). Gönderiyi ve github örneğine bağlantıyı güncelleyecektir.
dennmat

1
Sadece wifi veya hücresel ağın değiştirilip değiştirilmediğini tespit etmek için sadece flutter bağlantısına ihtiyacınız var. Bu sarmalayıcı, geçiş gerçekleştikten sonra bağlantıyı kontrol eder. Ancak her ağ değişikliğini uyarmaz. Öykünücüyü kullanıyorsanız, uçak modunu değiştirmek, internet bağlantısını kaybetmenin en kolay yoludur. Gerçek bir cihaz kullanıyorsanız, hala veri içeren bir mobil ağa bağlı olmadığınızdan emin olmanız gerekir.
dennmat

1
Bunun için birkaç seçenek var, sık sık test etmek için Zamanlayıcıyı kullanmak için yukarıdakileri değiştirebilirsiniz. Veya sadece Zamanlayıcı yardımcı programını kullanarak sık sık test edin. Bakınız: api.dartlang.org/stable/2.1.0/dart-async/Timer-class.html Diğer bir seçenek, gönderdiğiniz her istekten önce bağlantıyı test etmektir. Web soketleri gibi bir şey arıyor olabilirsiniz gibi görünse de. Neyse iyi şanslar
dennmat

3
Widget'ın dispose () işlevindeki aboneliği iptal etmemiz gerekmez mi? Bunun, buradaki gibi diğer StreamController örneklerinde yapıldığını görüyorum: stackoverflow.com/questions/44788256/updating-data-in-flutter
Oren

41

görüntü açıklamasını buraya girin

İnternet bağlantısının dinleyicisini ve kaynağını gösteren tam örnek.

Kredi: bağlantı ve 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();
}

firebase üzerinden, SDK mümkün mü?
LOG_TAG

@LOG_TAG Bunun için Firebase kullanmanıza gerek yok.
CopsOnRoad

1
@CopsOnRoad Çok teşekkür ederim. zamanımı kurtardın.
Nimisha Ranipa

Harita _source = {ConnectivityResult.none: false}; Neden burada "yanlış" kullandınız
Faruk AYDIN

@CopsOnRoad Teşekkürler! Bu yöntemi kullandım, Ama bu yöntem bana ilk kez NoInternetConnection veriyor! Neden önce bana Hiç vermedin? Bu benim hata ayıklama yazım: connectivityResult.none connectivityResult.wifi connectivityResult.wifi.
Faruk AYDIN

23

İnternetin mevcut olup olmadığını söylemek için sadece bağlantı paketini kullanmanın yeterli olmadığını anladım . Android'de yalnızca WIFI olup olmadığını veya mobil verinin açık olup olmadığını kontrol eder, gerçek bir internet bağlantısını kontrol etmez. Testim sırasında hiçbir mobil sinyal olmasa bile ConnectivityResult.mobile doğru döndürür.

IOS ile yaptığım test, bağlantı eklentisinin telefonda sinyal olmadığında internet bağlantısı olup olmadığını doğru bir şekilde tespit ettiğini, sorunun yalnızca Android'de olduğunu buldu.

Bulduğum çözüm , bağlantı paketi ile birlikte data_connection_checker paketini kullanmaktı . Bu, birkaç güvenilir adrese istekte bulunarak bir internet bağlantısı olduğundan emin olmanızı sağlar, kontrol için varsayılan zaman aşımı yaklaşık 10 saniyedir.

Bitirdiğim isInternet işlevi biraz şuna benziyordu:

  Future<bool> isInternet() async {
    var connectivityResult = await (Connectivity().checkConnectivity());
    if (connectivityResult == ConnectivityResult.mobile) {
      // I am connected to a mobile network, make sure there is actually a net connection.
      if (await DataConnectionChecker().hasConnection) {
        // Mobile data detected & internet connection confirmed.
        return true;
      } else {
        // Mobile data detected but no internet connection found.
        return false;
      }
    } else if (connectivityResult == ConnectivityResult.wifi) {
      // I am connected to a WIFI network, make sure there is actually a net connection.
      if (await DataConnectionChecker().hasConnection) {
        // Wifi detected & internet connection confirmed.
        return true;
      } else {
        // Wifi detected but no internet connection found.
        return false;
      }
    } else {
      // Neither mobile data or WIFI detected, not internet connection found.
      return false;
    }
  }

if (await DataConnectionChecker().hasConnection)Bölüm hem mobil hem de wifi bağlantıları için aynıdır ve muhtemelen ayrı fonksiyona taşınmalı. Bunu daha okunabilir kılmak için burada yapmadım.

Bu benim ilk Yığın Taşması cevabım, umarım birine yardımcı olur.


1
Stackoverflow'a hoş geldiniz. Merak ediyorum, await DataConnectionChecker().hasConnectionilk başta kullanmanın avantajı nedir?
herbert

2
Bunun tek nedeni, IOS'ta bağlantı paketinin hemen hemen anında bağlantı olmadığını söyleyebilmesidir. Sadece data_connection_checker paketini kullandıysam, IOS üzerindeki uygulamanın yanlış dönmeden önce yaptığı http isteği zaman aşımına uğrayana kadar yaklaşık 10 saniye beklemek zorunda kalacaktı. Yine de bazı durumlarda bu kabul edilebilir. Bağlantı paketi, burada bilmem gerekmeyen ancak bilmem gereken WIFI veya mobil veri kullanıp kullanmadığınızı da söyleyebilir.
abernee

Bu, yukarıdaki kodda birkaç sözdizimi değişikliği ile mükemmel şekilde çalışır. 1. Türler küçük harf olduğundan, Gelecek <Bool> öğesini gelecekteki <bool> olarak değiştirmeniz gerekir. 2. 4. son dönüş ifadesi için noktalı virgül (;) ekleyin.
TDM

Teşekkürler TDM, yanıtı değişikliklerinizle düzenledim.
abernee

20

Kullanma

dependencies:
  connectivity: ^0.4.2

kaynaklardan elde ettiğimiz şey

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

Gelecek benim için biraz sorunlu, onu her seferinde uygulamak zorundayız:

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

Bu sorunu çözmek için boolean isNetworkPresent parametresine sahip bir işlevi kabul eden bir sınıf oluşturdum.

methodName(bool isNetworkPresent){}

Ve Fayda Sınıfı

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

Ve bağlantı denetimi özelliğini kullanmak için

  fetchPrefrence(bool isNetworkPresent) {
    if(isNetworkPresent){

    }else{

    }
  }

bu sözdizimini kullanacağım

NetworkCheck networkCheck = new NetworkCheck();
networkCheck.checkInternet(fetchPrefrence)

6

Bu konuyu güvenilir bir şekilde ele alan (sanırım) bir paket oluşturdum.

Pub.dev'deki paket

GitHub'daki paket

Tartışma çok açığız. Sorun izleyiciyi GitHub'da kullanabilirsiniz.


Artık bunun güvenilir bir yöntem olduğunu düşünmüyorum:


@ Oren'in cevabına bir şey eklemek ister misiniz : Diğer tüm istisnaları yakalayacak (güvenli olmak için) gerçekten bir tane daha yakalama eklemelisiniz VEYA istisna türünü tamamen kaldırıp tüm istisnalarla ilgilenen bir yakalama kullanmalısınız:

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

hatta daha basit ...

Durum 2:


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

5

Widget durumu için bir temel sınıf yaptım

Kullanım yerine State<LoginPage>kullanım BaseState<LoginPage> daha sonra boole değişkenini isOnline kullanın

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

İlk olarak, bağlantı eklentisi ekleyin:

dependencies:
  connectivity: ^0.4.3+2

Ardından BaseState sınıfını ekleyin

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 {

  void castStatefulWidget();

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

Ve widget'ı bulunduğunuz eyalette bu şekilde yayınlamanız gerekiyor

@override
  void castStatefulWidget() {
    // ignore: unnecessary_statements
    widget is StudentBoardingPage;
  }

2
bu sınıfı nasıl kullanabilirim?
DolDurma

@DolDurma Sadece ekleyin ve içe aktarın ardından State <LoginPage> yerine BaseState <LoginPage> kullanın ve boolean değişkenini kullanın isOnline
amorenew

bu kod ile değerli eşyalar alamıyorum widget. örneğin: RegisterBloc get _registerBloc => widget.registerBloc;bu hatayı alıyorum, error: The getter 'registerBloc' isn't defined for the class 'StatefulWidget'. (undefined_getter at lib\screens\fragmemt_register\view\register_mobile_number.dart:29)bu uygulamaya bakın:class _FragmentRegisterMobileNumberState extends BaseState<FragmentRegisterMobileNumber> with SingleTickerProviderStateMixin { RegisterBloc get _registerBloc => widget.registerBloc;
DolDurma

@DolDurma GitHub örneği olmadan sorunun ne olduğundan emin değilim çünkü bu bilgi yeterli değil
amorenew

1
lütfen bu depoyu kontrol edin ve is_onlinekonsolda oturum açmak için nasıl kullanabileceğimi gösterin github.com/MahdiPishguy/flutter-connectivity-sample
DolDurma

3

@Dennmatt'ın cevabını takiben InternetAddress.lookup, internet bağlantısı kapalı olsa bile başarılı sonuçlar verebileceğini fark ettim - simülatörümden evdeki WiFi ağıma bağlanarak ve ardından yönlendiricimin kablosunu çıkararak test ettim. Bence nedeni, yönlendiricinin etki alanı arama sonuçlarını önbelleğe alması, böylece her arama isteğinde DNS sunucularını sorgulamak zorunda kalmamasıdır.

Her neyse, Firestore'u benim gibi kullanırsanız, try-SocketException-catch bloğunu boş bir işlemle değiştirebilir ve TimeoutExceptions'ı yakalayabilirsiniz:

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

Ayrıca, previousConnectionasenkron intenet kontrolünden önce ayarlandığına dikkat edin, bu nedenle teorik olarak checkConnection()kısa sürede birden çok kez çağrılırsa, hasConnection=truearka arkaya birden çok veya arka arkaya birden çok olabilir hasConnection=false. @Dennmatt'ın bunu bilerek yapıp yapmadığından emin değilim, ancak bizim kullanım durumumuzda hiçbir yan etkisi olmadı ( setStateyalnızca aynı değerle iki kez çağrıldı).


3

Bağlantı: paket, gerçek internet bağlantısını garanti etmez (sadece internet erişimi olmayan wifi bağlantısı olabilir).

Belgelerden alıntı yapın:

Android'de bunun İnternet bağlantısını garanti etmediğini unutmayın. Örneğin, uygulamanın wifi erişimi olabilir, ancak bu bir VPN veya erişimi olmayan bir otel WiFi olabilir.

Www İnternet bağlantısını gerçekten kontrol etmeniz gerekiyorsa, daha iyi bir seçim olacaktır.

data_connection_checker paketi


1

İşte Benim Çözümüm İnternet Bağlantısını ve Veri Bağlantısını Kontrol Ediyor Umarım beğenirsiniz.

Öncelikle pubsec.yaml dosyanıza bağımlılıklar ekleyin
dependencies:        
    data_connection_checker:
Ve İşte Çözümümün main.dart'ı
import 'dart:async';

import 'package:data_connection_checker/data_connection_checker.dart';
import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: "Data Connection Checker",
      home: HomePage(),
    );
  }
}

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

class _HomePageState extends State<HomePage> {
  StreamSubscription<DataConnectionStatus> listener;

  var Internetstatus = "Unknown";

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
//    _updateConnectionStatus();
      CheckInternet();
  }

  @override
  void dispose() {
    // TODO: implement dispose
    listener.cancel();
    super.dispose();
  }

  CheckInternet() async {
    // Simple check to see if we have internet
    print("The statement 'this machine is connected to the Internet' is: ");
    print(await DataConnectionChecker().hasConnection);
    // returns a bool

    // We can also get an enum instead of a bool
    print("Current status: ${await DataConnectionChecker().connectionStatus}");
    // prints either DataConnectionStatus.connected
    // or DataConnectionStatus.disconnected

    // This returns the last results from the last call
    // to either hasConnection or connectionStatus
    print("Last results: ${DataConnectionChecker().lastTryResults}");

    // actively listen for status updates
    listener = DataConnectionChecker().onStatusChange.listen((status) {
      switch (status) {
        case DataConnectionStatus.connected:
          Internetstatus="Connectd TO THe Internet";
          print('Data connection is available.');
          setState(() {

          });
          break;
        case DataConnectionStatus.disconnected:
          Internetstatus="No Data Connection";
          print('You are disconnected from the internet.');
          setState(() {

          });
          break;
      }
    });

    // close listener after 30 seconds, so the program doesn't run forever
//    await Future.delayed(Duration(seconds: 30));
//    await listener.cancel();
    return await await DataConnectionChecker().connectionStatus;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Data Connection Checker"),
      ),
      body: Container(
        child: Center(
          child: Text("$Internetstatus"),
        ),
      ),
    );
  }
}

1

Önerilen çözümlerle ilgili bir sorun yaşadım, kullanmak lookupher zaman beklenen değeri döndürmüyor.

Bunun nedeni DNS önbelleğe alınmasıdır, aramanın değeri önbelleğe alınır ve bir sonraki denemede uygun bir arama yapmak önbelleğe alınan değeri geri verir. Elbette bu, bağlantınızı kaybederseniz ve ararsanızlookup , önbelleğe alınmış değeri internetiniz varmış gibi döndürebilir ve tersine, lookupnull döndükten sonra internetinizi yeniden bağlarsanız, bunun süresi boyunca hala boş dönecektir. önbellek, şu anda internetiniz olsa bile birkaç dakika sürebilir.

TL; DR: lookup şeyi iade etmek, mutlaka internetiniz olduğu anlamına gelmez ve herhangi bir şey iade etmemesi, mutlaka internetiniz olmadığı anlamına gelmez. Güvenilir değil.

Eklentiden ilham alarak aşağıdaki çözümü uyguladım data_connection_checker:

 /// If any of the pings returns true then you have internet (for sure). If none do, you probably don't.
  Future<bool> _checkInternetAccess() {
    /// We use a mix of IPV4 and IPV6 here in case some networks only accept one of the types.
    /// Only tested with an IPV4 only network so far (I don't have access to an IPV6 network).
    final List<InternetAddress> dnss = [
      InternetAddress('8.8.8.8', type: InternetAddressType.IPv4), // Google
      InternetAddress('2001:4860:4860::8888', type: InternetAddressType.IPv6), // Google
      InternetAddress('1.1.1.1', type: InternetAddressType.IPv4), // CloudFlare
      InternetAddress('2606:4700:4700::1111', type: InternetAddressType.IPv6), // CloudFlare
      InternetAddress('208.67.222.222', type: InternetAddressType.IPv4), // OpenDNS
      InternetAddress('2620:0:ccc::2', type: InternetAddressType.IPv6), // OpenDNS
      InternetAddress('180.76.76.76', type: InternetAddressType.IPv4), // Baidu
      InternetAddress('2400:da00::6666', type: InternetAddressType.IPv6), // Baidu
    ];

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

Çağrının tamamlanması _checkInternetAccessen fazla bir süre alır timeout(burada 3 saniye) ve DNS'den herhangi birine ulaşabilirsek, diğerlerini beklemeden ilkine ulaşılır ulaşılmaz tamamlanacaktır (birine ulaşmak için İnternetin olduğunu biliyorum). Tüm aramalar_pingDns paralel olarak yapılır.

Bir IPV4 ağında iyi çalışıyor gibi görünüyor ve bunu bir IPV6 ağında test edemediğimde (birine erişimim yok) yine de çalışması gerektiğini düşünüyorum. Aynı zamanda sürüm modu yapılarında da çalışıyor, ancak yine de bu çözümle ilgili herhangi bir sorun bulup bulmadıklarını görmek için uygulamamı Apple'a göndermem gerekiyor.

Ayrıca çoğu ülkede (Çin dahil) çalışmalıdır, eğer birinde çalışmıyorsa, hedef ülkenizden erişilebilen listeye bir DNS ekleyebilirsiniz.


1

Sonunda ( isteksiz de olsa ) bu soruya önceki yanıtımda @abernee tarafından verilen çözüme karar verdim . Projelerimde her zaman olabildiğince az harici paket deniyorum ve kullanıyorum - çünkü harici paketlerin oluşturduğum yazılımdaki tek [potansiyel] başarısızlık noktaları olduğunu biliyorum. Dolayısıyla, sadece böyle basit bir uygulama için İKİ harici pakete bağlanmak benim için kolay olmadı .

Yine de, abernee'in kodunu aldım ve daha yalın ve daha duyarlı hale getirmek için değiştirdim. Mantıklı derken, Bağlantı paketinin gücünü işlevinde tükettiğini, ancak daha sonra bu paketten en değerli çıktıları (yani ağ kimliğini) geri getirmeyerek dahili olarak boşa harcadığını kastediyorum . İşte abernee'nin çözümünün değiştirilmiş versiyonu:

import 'package:connectivity/connectivity.dart';
import 'package:data_connection_checker/data_connection_checker.dart';


// 'McGyver' - the ultimate cool guy (the best helper class any app can ask for).
class McGyver {

  static Future<Map<String, dynamic>> checkInternetAccess() async {
    //* ////////////////////////////////////////////////////////////////////////////////////////// *//
    //*   INFO: ONLY TWO return TYPES for Map 'dynamic' value => <bool> and <ConnectivityResult>   *//
    //* ////////////////////////////////////////////////////////////////////////////////////////// *//
    Map<String, dynamic> mapCon;
    final String isConn = 'isConnected', netType = 'networkType';
    ConnectivityResult conRes = await (Connectivity().checkConnectivity());
    switch (conRes) {
      case ConnectivityResult.wifi:   //* WiFi Network: true !!
        if (await DataConnectionChecker().hasConnection) {   //* Internet Access: true !!
          mapCon = Map.unmodifiable({isConn: true, netType: ConnectivityResult.wifi});
        } else {
          mapCon = Map.unmodifiable({isConn: false, netType: ConnectivityResult.wifi});
        }
        break;
      case ConnectivityResult.mobile:   //* Mobile Network: true !!
        if (await DataConnectionChecker().hasConnection) {   //* Internet Access: true !!
          mapCon = Map.unmodifiable({isConn: true, netType: ConnectivityResult.mobile});
        } else {
          mapCon = Map.unmodifiable({isConn: false, netType: ConnectivityResult.mobile});
        }
        break;
      case ConnectivityResult.none:   //* No Network: true !!
        mapCon = Map.unmodifiable({isConn: false, netType: ConnectivityResult.none});
        break;
    }
    return mapCon;
  }

}

Daha sonra bu statik işlevi, kodunuzun herhangi bir yerinden aşağıdaki gibi basit bir çağrı yoluyla kullanırsınız:

bool isConn; ConnectivityResult netType;
McGyver.checkInternetAccess().then(
  (mapCIA) {  //* 'mapCIA' == amalgamation for 'map' from 'CheckInternetAccess' function result.
    debugPrint("'mapCIA' Keys: ${mapCIA.keys}");
    isConn = mapCIA['isConnected'];
    netType = mapCIA['networkType'];
  }
);
debugPrint("Internet Access: $isConn   |   Network Type: $netType");

Flutter projenizde bu çok temel işlevselliği elde etmek için İKİ HARİCİ PAKETE bağlamanız üzücü - ama sanırım şimdilik elimizdeki en iyisi bu. Aslında Veri Bağlantısı Denetleyicisi paketini Bağlantı paketine tercih ediyorum - ancak (bunu yayınladığım sırada) eski, Bağlantı paketinden istediğim çok önemli ağ tanımlama özelliğini eksikti . Bu yaklaşımı [geçici olarak] varsayılan olarak kullanmamın nedeni budur.


0

Flutter'daki Bağlantı Paketini kullanarak kodu basitleştirmeye çalışıyorum .

import 'package:connectivity/connectivity.dart';

var connectivityResult = await (Connectivity().checkConnectivity());
if (connectivityResult == ConnectivityResult.mobile) {
  // I am connected to a mobile network.
} else if (connectivityResult == ConnectivityResult.wifi) {
  // I am connected to a wifi network.
} else {
  // I am not connected to the internet
}

Bununla ilgili Android'deki sorun, sadece wifi veya mobil ile bağlı olduğunuz için, internete bağlı olduğunuz anlamına gelmiyor.
Megadec

1
@Megadec ne yazık ki evet tek sorun bu :(
devDeejay

0

geç cevap, ancak kontrol etmek için bu paketi kullanın. Paket Adı: data_connection_checker

pubspec.yuml dosyanızda:

dependencies:
    data_connection_checker: ^0.3.4

connection.dart adında bir dosya veya istediğiniz herhangi bir ad oluşturun. paketi içe aktar:

import 'package:data_connection_checker/data_connection_checker.dart';

İnternet bağlantısının olup olmadığını kontrol edin:

print(await DataConnectionChecker().hasConnection);

0

Wifi veya mobil bağlantı mevcut olsa bile internet erişimini kontrol etmek için data_connection_checker paketini kullandım, iyi çalışıyor: işte bağlantıyı kontrol etmek için kod:

bool result = await DataConnectionChecker().hasConnection;
if(result == true) {
   print('YAY! Free cute dog pics!');
} else {
   print('No internet :( Reason:');
   print(DataConnectionChecker().lastTryResults);
}

Daha fazla bilgi istiyorsanız paketin üzerinden geçin. Veri Bağlantısı Denetleyicisi Paketi


Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.