Code Monkey home page Code Monkey logo

data_connection_checker's Introduction

data_connection_checker

Pub

A pure Dart utility library that checks for an internet connection by opening a socket to a list of specified addresses, each with individual port and timeout. Defaults are provided for convenience.

Note that this plugin is in beta and may still have a few issues. Feedback is welcome.

Table of contents

Description

Checks for an internet (data) connection, by opening a socket to a list of addresses.

The defaults of the plugin should be sufficient to reliably determine if the device is currently connected to the global network, e.i. has access to the Internet.

Note that you should not be using the current network status for deciding whether you can reliably make a network connection. Always guard your app code against timeouts and errors that might come from the network layer.

Quick start

DataConnectionChecker() is actually a Singleton. Calling DataConnectionChecker() is guaranteed to always return the same instance.

You can supply a new list to DataConnectionChecker().addresses if you need to check different destinations, ports and timeouts. Also, each address can have its own port and timeout. See InternetAddressCheckOptions in the docs for more info.

First you need to install it (this is the preferred way)

Then you can start using the library:

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

Purpose

The reason this package exists is that connectivity package cannot reliably determine if a data connection is actually available. More info on its page here: https://pub.dev/packages/connectivity

More info on the issue in general:

You can use this package in combination with connectivity in the following way:

var isDeviceConnected = false;

var subscription = Connectivity().onConnectivityChanged.listen((ConnectivityResult result) async {
  if(result != ConnectivityResult.none) {
    isDeviceConnected = await DataConnectionChecker().hasConnection;
  }
});

Note: remember to properly cancel the subscription when it's no longer needed. See connectivity package docs for more info.

How it works

All addresses are pinged simultaneously. On successful result (socket connection to address/port succeeds) a true boolean is pushed to a list, on failure (usually on timeout, default 10 sec) a false boolean is pushed to the same list.

When all the requests complete with either success or failure, a check is made to see if the list contains at least one true boolean. If it does, then an external address is available, so we have data connection. If all the values in this list are false, then we have no connection to the outside world of cute cat and dog pictures, so hasConnection also returns false too.

This all happens at the same time for all addresses, so the maximum waiting time is the address with the highest specified timeout, in case it's unreachable.

I believe this is a reliable and fast method to check if a data connection is available to a device, but I may be wrong. I suggest you open an issue on the Github repository page if you have a better way of.

Defaults

The defaults are based on data collected from https://perfops.net/, https://www.dnsperf.com/#!dns-resolvers

Here's some more info about the defaults:

DEFAULT_ADDRESSES

... includes the top 3 globally available free DNS resolvers.

Address Provider Info
1.1.1.1 CloudFlare https://1.1.1.1
1.0.0.1 CloudFlare https://1.1.1.1
8.8.8.8 Google https://developers.google.com/speed/public-dns/
8.8.4.4 Google https://developers.google.com/speed/public-dns/
208.67.222.222 OpenDNS https://use.opendns.com/
208.67.220.220 OpenDNS https://use.opendns.com/
static final List<AddressCheckOptions> DEFAULT_ADDRESSES = List.unmodifiable([
  AddressCheckOptions(
    InternetAddress('1.1.1.1'),
    port: DEFAULT_PORT,
    timeout: DEFAULT_TIMEOUT,
  ),
  AddressCheckOptions(
    InternetAddress('8.8.4.4'),
    port: DEFAULT_PORT,
    timeout: DEFAULT_TIMEOUT,
  ),
  AddressCheckOptions(
    InternetAddress('208.67.222.222'),
    port: DEFAULT_PORT,
    timeout: DEFAULT_TIMEOUT,
  ),
]);

DEFAULT_PORT

... is 53.

A DNS server listens for requests on port 53 (both UDP and TCP). So all DNS requests are sent to port 53 ...

More info:

static const int DEFAULT_PORT = 53;

DEFAULT_TIMEOUT

... is 10 seconds.

static const Duration DEFAULT_TIMEOUT = Duration(seconds: 10);

DEFAULT_INTERVAL

... is 10 seconds. Interval is the time between automatic checks. Automatic checks start if there's a listener attached to onStatusChange, thus remember to cancel unneeded subscriptions.

checkInterval (which controls how often a check is made) defaults to this value. You can change it if you need to perform checks more often or otherwise.

static const Duration DEFAULT_INTERVAL = const Duration(seconds: 10);
...
Duration checkInterval = DEFAULT_INTERVAL;

Usage

Example:

import 'package:data_connection_checker/data_connection_checker.dart';

main() 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 value 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
  // this will cause DataConnectionChecker to check periodically
  // with the interval specified in DataConnectionChecker().checkInterval
  // until listener.cancel() is called
  var listener = DataConnectionChecker().onStatusChange.listen((status) {
    switch (status) {
      case DataConnectionStatus.connected:
        print('Data connection is available.');
        break;
      case DataConnectionStatus.disconnected:
        print('You are disconnected from the internet.');
        break;
    }
  });

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

Note: Remember to dispose of any listeners, when they're not needed to prevent memory leaks, e.g. in a StatefulWidget's dispose() method:

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

See example folder for more examples.

License

MIT

Copyright 2019 Kristiyan Mitev and Spirit Navigator

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Features and bugs

Please file feature requests and bugs at the issue tracker.

data_connection_checker's People

Contributors

komapeb avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

data_connection_checker's Issues

SocketException when device is offline

A SocketException is thrown whenever I call the hasConnection method when the device is offline.

class NetworkInfoImpl implements NetworkInfo{
  final DataConnectionChecker connectionChecker;

  NetworkInfoImpl(this.connectionChecker);
  @override

  Future<bool> get isConnected => connectionChecker.hasConnection;

}

SocketException (SocketException: Connection failed (OS Error: Network is unreachable, errno = 101), address = 1.1.1.1, port = 53)
SocketException (SocketException: Connection failed (OS Error: Network is unreachable, errno = 101), address = 8.8.4.4, port = 53)
SocketException (SocketException: Connection failed (OS Error: Network is unreachable, errno = 101), address = 208.67.222.222, port = 53)

No internet connection even though I have internet connection.

flutter: No internet :( Reason:
flutter: [AddressCheckResult(AddressCheckOptions(InternetAddress('1.1.1.1', IPv4), 53, 0:00:10.000000), false), AddressCheckResult(AddressCheckOptions(InternetAddress('8.8.4.4', IPv4), 53, 0:00:10.000000), false), AddressCheckResult(AddressCheckOptions(InternetAddress('208.67.222.222', IPv4), 53, 0:00:10.000000), false)]

I am using a school wifi connection and data_connection_checker is failing when tries to connect internet. I tried a different wifi (my phone's), it worked.

I am hoping this can be fixed because the app I am developing is focusing on students and they will be at school most of the time :)

Apple rejected my update due to data connection checker

Hello,
please check the screenshot, it's from my app https://well-spoken.app .

Apple is mysterious in their review process, I haven't changed anything in networking for 20 updates, and now they came up with this when rolling new features.

As you see on the screenshot, they were testing my app on iPad, and there is an additional layer of complexity - VPN, maybe it affects querying DNSes? I saw some other comments, perhaps we should use IPV6? Perhaps if all DNSes fail I should do additional request to my own server to verify the status of the network?

attachment Screenshot-0920-095247

I'm using most recent version of data_connection_checker.

I managed to convenience them to accept it without changes, but I'm afraid it's not a sustainable solution.

Don't use it on production for iOS!

In current version it will never pass Apple AppStore app approval process, because it does not work in IPv6 network. I wasted few days because of it.

can't add the package (Version Failure)

The current Dart SDK version is 3.2.3.
Project depends on data_connection_checker any which doesn't support null safety, version solving failed.
The lower bound of "sdk: '>=2.2.0 <3.0.0'" must be 2.12.0 or higher to enable null safety.

Modify testing logic to immediately return if any of the simultaneous pings succeed

Currently the logic is "All addresses are pinged simultaneously. ... When all the requests complete with either success or failure, a check is made to see if the list contains at least one true boolean.". However if any of the hosts slow to respond (for example for some reason CloudFlare DNSes don't respond (#10 (comment)) then we have to wait a timeout (10 seconds). In my opinion if any of the pings succeed then the test could already cut short any other pings and return immediately.

Null-safety

Will this library be upgraded to null-safety?

web support

I see the error below when targeting web. Not sure if this is just a limitation of flutter for web at this point or a problem with this library.

errors.dart:145 Uncaught (in promise) Error: Unsupported operation: InternetAddress
    at Object.throw_ [as throw] (errors.dart:191)
    at Function.new (io_patch.dart:408)
    at get DEFAULT_ADDRESSES (data_connection_checker.dart:61)
    at Function.desc.get [as DEFAULT_ADDRESSES] (utils.dart:75)
    at new data_connection_checker.DataConnectionChecker.__ (data_connection_checker.dart:89)
    at get _instance (data_connection_checker.dart:109)
    at Function.desc.get [as _instance] (utils.dart:75)
    at Function.new (data_connection_checker.dart:93)
    at network_info.NetworkInfoImpl.new._checkConnection (network_info.dart:39)
    at _checkConnection.next (<anonymous>)
    at runBody (async_patch.dart:84)
    at Object._async [as async] (async_patch.dart:123)
    at network_info.NetworkInfoImpl.new.[_checkConnection] (network_info.dart:38)
    at new network_info.NetworkInfoImpl.new (network_info.dart:16)
    at main$ (main.dart:62)
    at main$.next (<anonymous>)
    at onValue (async_patch.dart:45)
    at _RootZone.runUnary (zone.dart:1379)
    at _FutureListener.thenAwait.handleValue (future_impl.dart:137)
    at handleValueCallback (future_impl.dart:678)
    at Function._propagateToListeners (future_impl.dart:707)
    at _Future.new.[_completeWithValue] (future_impl.dart:522)
    at future.dart:400
    at _RootZone.runUnary (zone.dart:1379)
    at _FutureListener.then.handleValue (future_impl.dart:137)
    at handleValueCallback (future_impl.dart:678)
    at Function._propagateToListeners (future_impl.dart:707)
    at _Future.new.[_completeWithValue] (future_impl.dart:522)
    at async._AsyncCallbackEntry.new.callback (future_impl.dart:552)
    at Object._microtaskLoop (schedule_microtask.dart:41)
    at _startMicrotaskLoop (schedule_microtask.dart:50)
    at async_patch.dart:166

Also seeing warnings during build:

Skipping compiling my_proj|lib/main_web_entrypoint.dart with ddc because some of its
transitive libraries have sdk dependencies that not supported on this platform:

data_connection_checker|lib/data_connection_checker.dart

Add network check

The connectivity package does not support native dart.

Can you add the option to check if the device have network? (internet DataConnectionChecker will stay the same).

It will be very helpful to have something like DataConnectionChecker().onStatusChange.listen( but for the network connection only.

Adding custom addresses to check for connection

It would be a great enhancement if you could add a property to add custom addresses instead of the default ones.
example code would be:

DataConnectionChecker(ipAddresses:<ipAddress>[]);

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.