LAN, WIFI, Mobile Network Check

753
0
06-19-2018 02:09 PM
StephenQuan1
Esri Contributor
4 0 753

1. Introduction

This AppStudio blog describes how we can use the Networking component to detect for network connectivity and classify the type of network (LAN, WIFI, Mobile Data). This allows you to build apps that can react differently dependent on what type of network they're on, e.g. ask the user whether they want to download content whilst on an expensive mobile data network.

2. Minimal App - All Network Configurations

Let's start with a minimal app that shows all Network connections whether active or inactive:

import QtQuick 2.7
import QtQuick.Controls 2.1
import ArcGIS.AppFramework 1.0
import ArcGIS.AppFramework.Networking 1.0

App {
    width: 640 * AppFramework.displayScaleFactor
    height: 480 * AppFramework.displayScaleFactor

    Flickable {
        anchors.fill: parent
        contentWidth: textArea.width
        contentHeight: textArea.height
        TextArea {
            id: textArea
            text: JSON.stringify(Networking.configurations, undefined, 2)
        }
    }
}‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

On my Windows machine, I get:

{
  "0": {
    "objectName": "",
    "valid": true,
    "name": "vEthernet (Internal Ethernet Port Windows Phone Emulator Internal Switch) 2",
    "identifier": "312537767",
    "bearerType": 1,
    "bearerTypeFamily": 1,
    "bearerTypeName": "Ethernet",
    "configurationType": 0,
    "connectTimeout": 30000,
    "purpose": 0,
    "roamingAvailable": false,
    "state": 14
  },
  "1": {
    "objectName": "",
    "valid": true,
    "name": "vEthernet (VMware Virtual Ethernet Adapter for VMnet8 Virtual Switch)",
    "identifier": "287176532",
    "bearerType": 1,
    "bearerTypeFamily": 1,
    "bearerTypeName": "Ethernet",
    "configurationType": 0,
    "connectTimeout": 30000,
    "purpose": 0,
    "roamingAvailable": false,
    "state": 14
  },
  "2": {
    "objectName": "",
    "valid": true,
    "name": "vEthernet (Default Switch)",
    "identifier": "287176527",
    "bearerType": 1,
    "bearerTypeFamily": 1,
    "bearerTypeName": "Ethernet",
    "configurationType": 0,
    "connectTimeout": 30000,
    "purpose": 0,
    "roamingAvailable": false,
    "state": 14
  },
  "3": {
    "objectName": "",
    "valid": true,
    "name": "vEthernet (VMware Virtual Ethernet Adapter for VMnet1 Virtual Switch)",
    "identifier": "312537825",
    "bearerType": 1,
    "bearerTypeFamily": 1,
    "bearerTypeName": "Ethernet",
    "configurationType": 0,
    "connectTimeout": 30000,
    "purpose": 0,
    "roamingAvailable": false,
    "state": 14
  },
  "4": {
    "objectName": "",
    "valid": true,
    "name": "Bluetooth Network Connection",
    "identifier": "312537798",
    "bearerType": 1,
    "bearerTypeFamily": 1,
    "bearerTypeName": "Ethernet",
    "configurationType": 0,
    "connectTimeout": 30000,
    "purpose": 0,
    "roamingAvailable": false,
    "state": 2
  },
  "5": {
    "objectName": "",
    "valid": true,
    "name": "vEthernet (Intel(R) 82579LM Gigabit Network Connection Virtual Switch)",
    "identifier": "312537802",
    "bearerType": 1,
    "bearerTypeFamily": 1,
    "bearerTypeName": "Ethernet",
    "configurationType": 0,
    "connectTimeout": 30000,
    "purpose": 0,
    "roamingAvailable": false,
    "state": 14
  }
}‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

The things we observed about Networking.configurations are:

  1. it's an object, not an array,
  2. every connection is listed (both active and inactive)
  3. there are signals on Network.configurations so you can use it in property binding scenarios (i.e. the moment the network changes, e.g. device is put in airplane mode, your app automatically updates)

3. Active Network Configurations

In order to filter the list down quickly, we transform the object to an array, then filter the results using Array.prototype.filter:

import QtQuick 2.7
import QtQuick.Controls 2.1
import ArcGIS.AppFramework 1.0
import ArcGIS.AppFramework.Networking 1.0

App {
    width: 640 * AppFramework.displayScaleFactor
    height: 480 * AppFramework.displayScaleFactor

    Flickable {
        anchors.fill: parent
        contentWidth: textArea.width
        contentHeight: textArea.height
        TextArea {
            id: textArea
            text: JSON.stringify(
                toArray(Networking.configurations)
                    .filter(isConfigActive)
                    .map(summary),
            undefined, 2)
        }
    }

    function toArray(o) {
        return Object.keys(o).map(function (e) { return o[e]; } );
    }

    function isConfigActive(c) {
        return (c.state & NetworkConfiguration.StateActive) === NetworkConfiguration.StateActive;
    }

    function summary(c) {
        return {
            name: c.name,
            bearerType: c.bearerType
        };
    }
}
‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

On my Windows machine, this reduces to an easier to read list:

[
  {
    "bearerType": 1,
    "name": "vEthernet (Internal Ethernet Port Windows Phone Emulator Internal Switch) 2"
  },
  {
    "bearerType": 1,
    "name": "vEthernet (VMware Virtual Ethernet Adapter for VMnet1 Virtual Switch)"
  },
  {
    "bearerType": 1,
    "name": "vEthernet (Default Switch)"
  },
  {
    "bearerType": 1,
    "name": "vEthernet (Intel(R) 82579LM Gigabit Network Connection Virtual Switch)"
  },
  {
    "bearerType": 1,
    "name": "vEthernet (VMware Virtual Ethernet Adapter for VMnet8 Virtual Switch)"
  }
]‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

On my Android device, when WIFI is enabled:

[
  {
    "bearerType": 2,
    "name": "WIFI"
  }
]‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

or, when Mobile Data is enabled:

[
  {
    "bearerType": 10,
    "name": "Mobile"
  }
]‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

On my iOS device, when WIFI is enabled:

[
  {
    "bearerType": 0,
    "name": "en0"
  },
  {
    "bearerType": 0,
    "name": "awdl0"
  },
  {
    "bearerType": 0,
    "name": "utun0"
  }
]‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

4. Determining if the Network is LAN, WIFI or MobileData

On Windows, Android and Linux the bearerType can be used to classify the network connection, e.g.

  • NetworkConfiguration.BearerEthernet
  • NetworkConfiguration.BearerWLAN
  • NetworkConfiguraiton.Bearer3G

Whilst on iOS and macOS, the bearerType may not be provided by the operating system resulting in NetworkConfiguration.BearerUnknown. To cover iOS and macOS, we note that the name of the configuration instead:

  • en0
  • awdl0
  • pdp_ip0

    function isConfigLAN(c) {
        if (c.bearerType === NetworkConfiguration.BearerEthernet) {
            return true;
        }

        if (Qt.platform.os === "osx") {
            return c.name === "en0";
        }

        return false;
    }
    
    function isConfigWIFI(c) {
        if (c.bearerType === NetworkConfiguration.BearerWLAN) {
            return true;
        }

        if (Qt.platform.os === "ios") {
            return c.name === "en0";
        }
        
        if (Qt.platform.os === "osx") {
            return c.name === "awdl0";
        }

        return false;
    }

    function isConfigMobileData(c) {
        switch (c.bearerType) {
        case NetworkConfiguration.Bearer2G:
        case NetworkConfiguration.BearerCDMA2000:
        case NetworkConfiguration.BearerWCDMA:
        case NetworkConfiguration.BearerHSPA:
        case NetworkConfiguration.BearerWiMAX:
        case NetworkConfiguration.BearerEVDO:
        case NetworkConfiguration.BearerLTE:
        case NetworkConfiguration.Bearer3G:
        case NetworkConfiguration.Bearer4G:
            return true;
        }

        if (Qt.platform.os === "ios") {
            return c.name === "pdp_ip0";
        }

        return false;
    }‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

    function isConfigActiveLAN(c) {
        return isConfigActive(c) && isConfigLAN(c);
    }

    function isConfigActiveWIFI(c) {
        return isConfigActive(c) && isConfigWIFI(c);
    }

    function isConfigActiveMobileData(c) {
        return isConfigActive(c) && isConfigMobileData(c);
    }
‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

Now that we have these useful functions, we can quickly chain them together to determine whether we're on WIFI or MobileData. Because we convert the object to an array, we can make use of Array.prototype.some to quickly lookup a network configuration of a particular type:

    property var config: toArray(Networking.configurations)
    property bool isOnline: isLAN || isWIFI || isMobileData
    property bool isLAN: config.some(isConfigActiveLAN)
    property bool isWIFI: config.some(isConfigActiveWIFI)
    property bool isMobileData: config.some(isConfigActiveMobileData)
    property bool isMobileDataOnly: isMobileData && !isWIFI && !isLAN‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

5. Network Check Sample

The "Network Check" app is available for you to try which demonstrates all of the above points. You can find "Network Check" app in AppStudio.

  1. Launch AppStudio
  2. Select New App
  3. Click Search Icon
  4. Type: Network Check

Network Check

The "Network Check" source code is also avilable at arcgis-appstudio-samples GitHub.