Periksa apakah ada sambungan Internet yang tersedia di aplikasi Flutter


99

Saya memiliki panggilan jaringan untuk dieksekusi. Tetapi sebelum melakukan itu saya perlu memeriksa apakah perangkat memiliki konektivitas internet.

Inilah yang telah saya lakukan sejauh ini:

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

Metode di atas tidak berfungsi.

Jawaban:


193

The konektivitas Plugin negara di docs nya yang hanya menyediakan informasi jika ada koneksi jaringan, tetapi tidak jika jaringan terhubung ke Internet

Perhatikan bahwa di Android, ini tidak menjamin koneksi ke Internet. Misalnya, aplikasi mungkin memiliki akses wifi tetapi mungkin itu VPN atau WiFi hotel tanpa akses.

Kamu dapat memakai

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
Saya mendapatkan kesalahan "isNotEmpty tidak dideklarasikan di dalam InternetAddress"
Rissmon Suresh

2
Bisakah ini dicapai di latar belakang? Seperti saya memiliki antrian tugas yang menunggu eksekusi dan menunggu internet tetapi aplikasi ditutup?
Vidor Vistrom

60
Harap dicatat bahwa google.com tidak dapat diakses di dalam China dan dengan demikian contoh akan hang jika digunakan di China. Untuk memperluas audiens Anda, harap hindari menggunakan google.com dan sebagai gantinya gunakan example.com. hasil akhir = menunggu InternetAddress.lookup ('example.com');
otboss

4
Ini tidak berfungsi untuk saya if (result.isNotEmpty && result[0].rawAddress.isNotEmpty)mengembalikan true ketika ada wifi tetapi tidak ada koneksi internet.
Denn

5
Oh, ya, saya benar-benar lupa tentang ini! Sebenarnya saya rasa saya bisa terus menggunakan await, saya bisa menambahkan .timeoutsetelahnya lookup().
Michel Feinstein

73

Bagi siapa pun yang mendarat di sini, saya ingin menambahkan jawaban Günter Zöchbauer ini adalah solusi saya untuk menerapkan utilitas untuk mengetahui apakah ada internet atau tidak terlepas dari hal lain.

Penolakan:

Saya baru mengenal Dart dan Flutter, jadi ini mungkin bukan pendekatan terbaik, tetapi saya ingin mendapatkan masukan.


Menggabungkan flutter_connectivity dan pengujian koneksi Günter Zöchbauer

Persyaratan saya

Saya tidak ingin memiliki banyak kode berulang di mana pun saya perlu memeriksa koneksi dan saya ingin secara otomatis memperbarui komponen atau apa pun yang peduli dengan koneksi setiap kali ada perubahan.

ConnectionStatusSingleton

Pertama kami menyiapkan Singleton. Jika Anda tidak terbiasa dengan pola ini, ada banyak info bagus online tentangnya. Namun intinya adalah Anda ingin membuat satu instance kelas selama siklus hidup aplikasi dan dapat menggunakannya di mana saja.

Singleton ini menghubungkan flutter_connectivitydan mendengarkan perubahan konektivitas, kemudian menguji koneksi jaringan, kemudian menggunakan StreamControlleruntuk memperbarui apapun yang penting.

Ini terlihat seperti ini:

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

Pemakaian

Inisialisasi

Pertama kita harus memastikan kita memanggil inisialisasi singleton kita. Tapi hanya sekali. Bagian ini terserah Anda, tetapi saya melakukannya di aplikasi saya 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();   
}

Di Widgetatau di tempat lain

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

Semoga orang lain menganggap ini berguna!


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

Alihkan mode pesawat di emulator untuk melihat hasilnya


2
Menguji kode dan berfungsi untuk saya, saya memerlukan info lebih lanjut untuk membantu.
dennmat

3
Ahh, oke saya melihatnya. Jadi sekali lagi untuk referensi Anda di masa mendatang, kesalahan yang Anda posting hanyalah editor yang mencoba membuka file yang menurutnya kesalahan itu terjadi. Error yang sebenarnya seharusnya tersedia di konsol debug / panel pelacakan tumpukan editor Anda. Jadi saya kira runApp mengembalikan saya berasumsi itu akan berjalan untuk keseluruhan program. Karena ini pada dasarnya, pembuangan tidak terlalu diperlukan di sini jadi hapus saja connectionStatus.dispose()dengan asumsi Anda mengaturnya main()seperti di atas. Akan memperbarui posting dan tautan ke contoh github.
dennmat

1
Untuk hanya mendeteksi apakah wifi atau seluler sedang diaktifkan, Anda hanya perlu konektivitas flutter. Pembungkus ini memeriksa koneksi setelah sakelar terjadi. Tetapi tidak akan memperingatkan setiap perubahan jaringan. Jika Anda menggunakan emulator, mengubah mode pesawat adalah cara termudah untuk kehilangan koneksi internet. Jika Anda menggunakan perangkat yang sebenarnya, Anda harus memastikan bahwa Anda tidak masih terhubung ke jaringan seluler dengan data.
dennmat

1
Ada beberapa opsi untuk itu, Anda dapat memodifikasi yang di atas untuk menggunakan Timer untuk sering menguji. Atau cukup uji sering menggunakan utilitas Timer. Lihat: api.dartlang.org/stable/2.1.0/dart-async/Timer-class.html Opsi lain adalah menguji koneksi sebelum setiap permintaan yang Anda kirim. Meskipun sepertinya Anda mencari sesuatu seperti websockets. Pokoknya semoga berhasil
dennmat

3
Bukankah kita harus membatalkan langganan dalam fungsi widget's dispose ()? Saya melihat ini dilakukan dalam contoh StreamController lain seperti di sini: stackoverflow.com/questions/44788256/updating-data-in-flutter
Oren

41

masukkan deskripsi gambar di sini

Contoh lengkap yang menunjukkan pendengar konektivitas internet dan sumbernya.

Penghargaan untuk: konektivitas dan 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();
}

melalui firebase, SDK apakah mungkin?
LOG_TAG

@LOG_TAG Anda tidak perlu menggunakan Firebase untuk ini.
CopsOnRoad

1
@CopsOnRoad Terima kasih banyak. Anda menghemat waktu saya.
Nimisha Ranipa

Map _source = {ConnectivityResult.none: false}; Mengapa Anda menggunakan "false" di sini
Faruk AYDIN

@CopsOnRoad Terima kasih! Saya menggunakan metode ini, Tapi metode ini memberi saya NoInternetConnection pertama kali! Mengapa pertama kali memberi saya Tidak ada? Ini adalah cetakan debug saya: konektivitasResult.none konektivitasResult.wifi konektivitasResult.wifi.
Faruk AYDIN

23

Saya menemukan bahwa hanya menggunakan paket konektivitas tidak cukup untuk mengetahui apakah internet tersedia atau tidak. Di Android itu hanya memeriksa apakah ada WIFI atau jika data seluler dihidupkan, itu tidak memeriksa koneksi internet yang sebenarnya. Selama pengujian saya, bahkan tanpa sinyal seluler, ConnectivityResult.mobile akan mengembalikan true.

Dengan IOS pengujian saya menemukan bahwa plugin konektivitas mendeteksi dengan benar jika ada koneksi internet ketika ponsel tidak memiliki sinyal, masalahnya hanya dengan Android.

Solusi yang saya temukan adalah menggunakan paket data_connection_checker bersama dengan paket konektivitas. Ini hanya memastikan ada koneksi internet dengan membuat permintaan ke beberapa alamat yang dapat diandalkan, batas waktu default untuk pemeriksaan adalah sekitar 10 detik.

Fungsi isInternet saya yang sudah selesai terlihat seperti ini:

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

The if (await DataConnectionChecker().hasConnection)bagian adalah sama untuk kedua koneksi mobile dan wifi dan mungkin harus dipindahkan ke fungsi yang terpisah. Saya tidak melakukannya di sini agar lebih mudah dibaca.

Ini adalah jawaban Stack Overflow pertama saya, semoga bisa membantu seseorang.


1
Selamat datang di stackoverflow. Hanya bertanya-tanya, apa keuntungan dari sekedar menggunakan await DataConnectionChecker().hasConnection?
herbert

2
Satu-satunya alasan adalah bahwa di iOS, paket konektivitas dapat langsung mengetahui bahwa tidak ada koneksi. Jika saya hanya menggunakan paket data_connection_checker, aplikasi di IOS harus menunggu hingga permintaan http yang dibuat habis waktunya, sekitar 10 detik, sebelum mengembalikan false. Ini mungkin dapat diterima dalam beberapa kasus. Paket konektivitas juga dapat mengetahui apakah Anda menggunakan WIFI atau data seluler yang tidak perlu saya ketahui di sini tetapi mungkin berguna untuk mengetahuinya.
abernee

Ini bekerja sempurna dengan sedikit modifikasi sintaks pada kode di atas. 1. Anda perlu mengubah <Bool> Future menjadi <bool> mendatang), karena tipenya adalah huruf kecil. 2. Tambahkan titik koma (;) untuk pernyataan pengembalian terakhir ke-4.
TDM

Terima kasih TDM, saya telah mengedit jawabannya dengan modifikasi Anda.
abernee

20

Menggunakan

dependencies:
  connectivity: ^0.4.2

apa yang kami dapatkan dari sumber daya adalah

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

Masa depan sedikit bermasalah bagi saya, kami harus menerapkannya setiap saat seperti:

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

Jadi untuk mengatasi masalah ini saya telah membuat kelas yang menerima fungsi dengan parameter isNetworkPresent boolean seperti ini

methodName(bool isNetworkPresent){}

Dan Kelas Utilitas adalah

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

Dan untuk menggunakan utilitas pemeriksaan konektivitas

  fetchPrefrence(bool isNetworkPresent) {
    if(isNetworkPresent){

    }else{

    }
  }

saya akan menggunakan sintaks ini

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

6

Saya telah membuat paket yang (menurut saya) andal menangani masalah ini.

Paket di pub.dev

Paket di GitHub

Diskusi sangat disambut baik. Anda dapat menggunakan pelacak masalah di GitHub.


Menurut saya, di bawah ini tidak lagi metode yang dapat diandalkan:


Ingin menambahkan sesuatu ke jawaban @ Oren : Anda harus benar-benar menambahkan satu tangkapan lagi, yang akan menangkap semua pengecualian lainnya (hanya untuk amannya), ATAU cukup hapus semua jenis pengecualian dan gunakan tangkapan, yang berhubungan dengan semua pengecualian:

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

atau bahkan lebih sederhana ...

Kasus 2:


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

5

Saya membuat kelas dasar untuk status widget

Gunakan alih-alih State<LoginPage>gunakan BaseState<LoginPage> maka cukup gunakan variabel boolean isOnline

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

Pertama, tambahkan plugin konektivitas:

dependencies:
  connectivity: ^0.4.3+2

Kemudian tambahkan kelas BaseState

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

Dan Anda perlu mentransmisikan widget di negara Anda seperti ini

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

2
bagaimana saya bisa menggunakan kelas ini?
DolDurma

@DolDurma Cukup tambahkan dan impor lalu alih-alih Status <LoginPage> gunakan BaseState <LoginPage> lalu gunakan saja variabel boolean isOnline
amorenew

dengan kode ini saya tidak bisa mendapatkan valiables dari widget. sebagai contoh: RegisterBloc get _registerBloc => widget.registerBloc;saya mendapatkan kesalahan error: The getter 'registerBloc' isn't defined for the class 'StatefulWidget'. (undefined_getter at lib\screens\fragmemt_register\view\register_mobile_number.dart:29)ini, lihat class _FragmentRegisterMobileNumberState extends BaseState<FragmentRegisterMobileNumber> with SingleTickerProviderStateMixin { RegisterBloc get _registerBloc => widget.registerBloc;
penerapan

@DolDurma Saya tidak yakin apa masalahnya tanpa sampel GitHub karena informasi ini tidak cukup
amorenew

1
tolong periksa repo ini dan tunjukkan bagaimana saya bisa menggunakan is_onlineuntuk masuk ke konsol github.com/MahdiPishguy/flutter-connectivity-sample
DolDurma

3

Mengikuti jawaban @dennmatt , saya perhatikan ituInternetAddress.lookup mungkin mengembalikan hasil yang sukses meskipun koneksi internet mati - Saya mengujinya dengan menghubungkan dari simulator saya ke WiFi rumah saya, dan kemudian melepaskan kabel router saya. Saya pikir alasannya adalah karena router menyimpan hasil pencarian domain sehingga tidak perlu meminta server DNS pada setiap permintaan pencarian.

Bagaimanapun, jika Anda menggunakan Firestore seperti saya, Anda dapat mengganti blok try-SocketException-catch dengan transaksi kosong dan menangkap 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;
}

Juga, harap perhatikan bahwa previousConnectionitu diatur sebelum pemeriksaan intenet asinkron, jadi secara teoritis jika checkConnection()dipanggil beberapa kali dalam waktu singkat, mungkin ada beberapa hasConnection=truedalam satu baris atau beberapa hasConnection=falsedalam satu baris. Saya tidak yakin apakah @dennmatt melakukannya dengan sengaja atau tidak, tetapi dalam kasus penggunaan kami tidak ada efek samping ( setStatehanya dipanggil dua kali dengan nilai yang sama).


3

Konektivitas: paket tidak menjamin koneksi internet yang sebenarnya (bisa saja koneksi wifi tanpa akses internet).

Kutipan dari dokumentasi:

Perhatikan bahwa di Android, ini tidak menjamin koneksi ke Internet. Misalnya, aplikasi mungkin memiliki akses wifi tetapi mungkin itu VPN atau WiFi hotel tanpa akses.

Jika Anda benar-benar perlu memeriksa koneksi ke Internet www, pilihan yang lebih baik adalah

paket data_connection_checker


1

Inilah Solusi Saya Ini Memeriksa Konektivitas Internet serta Koneksi Data Saya harap Anda Menyukainya.

Pertama-tama tambahkan dependensi di pubsec.yaml Anda
dependencies:        
    data_connection_checker:
Dan Di Sini Adalah Main.dart Solusi Saya
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

Saya memiliki masalah dengan solusi yang diusulkan, menggunakan lookuptidak selalu mengembalikan nilai yang diharapkan.

Ini karena DNS caching, nilai panggilan di-cache dan bukannya melakukan panggilan yang benar pada percobaan berikutnya, ia mengembalikan nilai yang di-cache. Tentu saja ini menjadi masalah di sini karena artinya jika Anda kehilangan konektivitas dan memanggilnya lookupmasih dapat mengembalikan nilai yang di-cache seolah-olah Anda memiliki internet, dan sebaliknya, jika Anda menyambungkan kembali internet Anda setelah lookupmengembalikan nol, itu akan tetap mengembalikan nol selama durasi cache, yang dapat memakan waktu beberapa menit, meskipun Anda memiliki internet sekarang.

TL; DR: lookupmengembalikan sesuatu tidak selalu berarti Anda memiliki internet, dan tidak mengembalikan apa pun tidak berarti Anda tidak memiliki internet. Itu tidak bisa diandalkan.

Saya menerapkan solusi berikut dengan mengambil inspirasi dari data_connection_checkerplugin:

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

Panggilan untuk _checkInternetAccessmemakan waktu paling lama timeouthingga selesai (3 detik di sini), dan jika kita dapat mencapai salah satu DNS, itu akan selesai segera setelah yang pertama tercapai, tanpa menunggu yang lain (karena mencapai satu sudah cukup untuk tahu Anda memiliki internet). Semua panggilan ke _pingDnsdilakukan secara paralel.

Tampaknya berfungsi dengan baik di jaringan IPV4, dan ketika saya tidak dapat mengujinya di jaringan IPV6 (saya tidak memiliki akses ke salah satunya), saya pikir itu masih harus berfungsi. Ini juga berfungsi pada build mode rilis, tetapi saya belum harus mengirimkan aplikasi saya ke Apple untuk melihat apakah mereka menemukan masalah dengan solusi ini.

Ini juga harus berfungsi di sebagian besar negara (termasuk Cina), jika tidak berfungsi di salah satu, Anda dapat menambahkan DNS ke daftar yang dapat diakses dari negara target Anda.


1

Saya akhirnya ( meskipun dengan enggan ) menyelesaikan solusi yang diberikan oleh @abernee dalam jawaban sebelumnya untuk pertanyaan ini. Saya selalu mencoba dan menggunakan sesedikit mungkin paket eksternal dalam proyek saya - karena saya tahu paket eksternal adalah satu-satunya titik kegagalan [potensial] dalam perangkat lunak yang saya buat. Jadi untuk menautkan ke DUA paket eksternal hanya untuk implementasi sederhana seperti ini tidak mudah bagi saya .

Namun demikian, saya mengambil kode abernee dan memodifikasinya agar lebih ramping dan lebih masuk akal. Maksud saya, dia menggunakan kekuatan paket Konektivitas dalam fungsinya tetapi kemudian membuangnya secara internal dengan tidak mengembalikan keluaran yang paling berharga dari paket ini (yaitu identifikasi jaringan). Jadi berikut adalah versi modifikasi dari solusi abernee:

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

}

Kemudian Anda akan menggunakan fungsi statis ini melalui panggilan sederhana dari mana saja dalam kode Anda sebagai berikut:

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

Sayang sekali Anda harus menautkan ke DUA PAKET EKSTERNAL untuk mendapatkan fungsionalitas yang sangat mendasar ini dalam proyek Flutter Anda - tetapi saya rasa untuk saat ini ini adalah yang terbaik yang kami miliki. Saya sebenarnya lebih suka paket Pemeriksa Sambungan Data daripada paket Konektivitas - tetapi (pada saat posting ini) yang pertama tidak ada fitur identifikasi jaringan yang sangat penting yang saya perlukan dari paket Konektivitas. Inilah alasan mengapa saya gagal menggunakan pendekatan ini [untuk sementara].


0

Hanya mencoba menyederhanakan kode menggunakan Connectivity Package di Flutter.

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
}

Masalah dengan ini di Android adalah bahwa hanya karena Anda terhubung melalui wifi atau seluler, itu tidak berarti Anda terhubung ke internet.
Megadec

1
@Megadec sayangnya ya itu satu-satunya masalah :(
devDeejay

0

jawaban terlambat, tetapi gunakan paket ini untuk memeriksa. Nama Paket: data_connection_checker

di file pubspec.yuml Anda:

dependencies:
    data_connection_checker: ^0.3.4

buat file bernama connection.dart atau nama apa pun yang Anda inginkan. impor paket:

import 'package:data_connection_checker/data_connection_checker.dart';

periksa apakah ada koneksi internet atau tidak:

print(await DataConnectionChecker().hasConnection);

0

Saya menggunakan paket data_connection_checker untuk memeriksa akses internet meskipun koneksi tersedia oleh wifi atau seluler, ini berfungsi dengan baik: berikut adalah kode untuk memeriksa koneksi:

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

buka paket jika Anda ingin informasi lebih lanjut. Paket Pemeriksa Koneksi Data


Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.