Skip to content

Instantly share code, notes, and snippets.

@gianpaolof
Created April 1, 2022 09:21
Show Gist options
  • Save gianpaolof/017f462cca2bd9d8a29d052b5e1712ce to your computer and use it in GitHub Desktop.
Save gianpaolof/017f462cca2bd9d8a29d052b5e1712ce to your computer and use it in GitHub Desktop.
Class to check the Connectivity and Internet Access of an Android device.
/*
* Copyright (c) 2014 str4d
*
* 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.
*
* Copyright (c) 2020 Rodrigo Sambade
*
* 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.
* License: MIT
* http://opensource.org/licenses/MIT
* Forked from https://gist.github.com/str4d/22cac7a3f70bc227cdca, which was forked
* from https://gist.github.com/emil2k/5130324
*
*
*/
@file: Suppress("DEPRECATION", "UNUSED", "WeakerAccess")
package net.i2p.android.router.util
import android.annotation.SuppressLint
import android.annotation.TargetApi
import android.content.Context
import android.net.ConnectivityManager
import android.net.Network
import android.net.NetworkCapabilities
import android.net.NetworkInfo
import android.os.AsyncTask
import android.os.Build.VERSION.SDK_INT
import android.os.Build.VERSION_CODES
import android.provider.Settings
import android.telephony.TelephonyManager
import android.util.Log
import java.io.IOException
import java.net.*
import java.nio.channels.IllegalBlockingModeException
import java.util.concurrent.CancellationException
/**
* Check device's network connectivity and speed. Check Internet access
* @author Rodrigo Sambade rodrigo.sambade.saa@protonmail.com https://stackoverflow
* .com/users/5520417/rodrigo https://github.com/rodrigosambadesaa https://gitlab
* .com/rodrigosambadesaa
* @author str4d https://gist.github.com/str4d
*/
class ConnectivityAndInternetAccess(hosts: ArrayList<String>) {
/**
* Adjusts the value of the hosts
*/
private
var hosts: ArrayList<String> = hosts
private set(hosts) {
Companion.hosts = hosts
field = hosts
}
/**
* Checks that Internet is available. Network calls shouldn't be called from main
* thread otherwise it will throw @link{NetworkOnMainThreadException}
*/
private class InternetConnectionCheck(context: Context?) : AsyncTask<Void?, Void?, Boolean>() {
/**
* The context
*/
@SuppressLint("StaticFieldLeak")
var context: Context? = null
/**
* Cancels the activity if the device is not connected to a network.
*/
override fun onPreExecute() {
if (!isConnected(context)) {
cancel(true)
}
}
/**
* Creates an instance of this class
*/
init {
this.context = context
}
/**
* Tells whether there is Internet access
* @param voids The list of arguments
* @return @code{true} if Internet can be accessed
*/
override fun doInBackground(vararg voids: Void?): Boolean {
return isConnectedToInternet(context)
}
}
companion object {
//------------------------------------------- Connectivity --------------------------------------------------------------------------
/**
* The minimum speed for the connection to be considered fast
*
*/
private
const val minimumSpeedForFastConnection = 3072
/**
* Get the active network's information.
*
* @param context The Context.
* @return The active NetworkInfo.
* @throws UnsupportedOperationException If the method cannot be used
*/
@Throws(UnsupportedOperationException::class)
private fun getNetworkInformation(context: Context): NetworkInfo? {
if (SDK_INT < VERSION_CODES.LOLLIPOP) {
val networkInformation: NetworkInfo?
val connectivityManager = context
.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
networkInformation = connectivityManager.activeNetworkInfo
return networkInformation
}
Log.e("UnusableMethod", "Cannot use this method for the current API Level")
throw UnsupportedOperationException("Cannot use this method for the " +
"current API level")
}
/**
* Tells whether there is an active network connection
* @param context The context
* @return @code{true} If there is an active network connection, @code{false}
* otherwise
*/
private fun isThereAnActiveNetworkConnection(context: Context): Boolean {
val isThereAnActiveNetworkConnection: Boolean
if(SDK_INT >= VERSION_CODES.LOLLIPOP ) {
isThereAnActiveNetworkConnection = getActiveNetwork(context) != null
} else {
Log.e("UnusableMethod", "Cannot use this method for the current API Level")
throw UnsupportedOperationException("Cannot use this method for the" +
" current API Level")
}
return isThereAnActiveNetworkConnection
}
/**
* Get active network.
*
* @param context The Context.
* @return The active NetworkInfo.
* @throws UnsupportedOperationException in case this function is running on
* an Android version lower than Marshmallow *
*/
private fun getActiveNetwork(context: Context): Network? {
val networkInformation: Network?
val connectivityManager = context
.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
if (SDK_INT >= VERSION_CODES.M) {
networkInformation = connectivityManager.activeNetwork
} else {
Log.e("UnusableMethod", "Cannot use this method for the current API Level")
throw UnsupportedOperationException("Cannot use this method for the" +
" current API Level")
}
return networkInformation
}
/**
* Delivers the information of a specific network.
* @param context The Context.
* @return The active NetworkInfo.
* @throws IllegalArgumentException If the network is @code{null}
*/
@Throws(IllegalArgumentException::class)
private fun getNetworkInformation(context: Context, network: Network?): NetworkInfo? {
if (network != null) {
val networkInformation: NetworkInfo?
val connectivityManager = context
.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
if (SDK_INT >= VERSION_CODES.LOLLIPOP) {
networkInformation = connectivityManager.getNetworkInfo(network)
} else {
Log.e("UnusableMethod", "Cannot use this method for the current API Level")
throw UnsupportedOperationException("Cannot use this method for the current API Level")
}
return networkInformation
}
throw IllegalArgumentException("Null value for any parameter is illegal")
}
/**
* Gets the info of all networks
* @param context The context
* @return An array of @link {NetworkInfo}
* @throws UnsupportedOperationException if this function is running on an
* Android version higher than or equal to Marshmallow
* @throws IllegalArgumentException If the value for the context is @code{null}
*/
private fun getAllNetworkInfo(context: Context?): Array<NetworkInfo?> {
if (context != null) {
val connectivityManager = context
.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
var networkInformation = arrayOfNulls<NetworkInfo>(0)
if (SDK_INT < VERSION_CODES.M) {
networkInformation = connectivityManager.allNetworkInfo
} else {
Log.e("UnusableMethod", "Cannot use this method for the current API Level")
}
return networkInformation
}
throw IllegalArgumentException("Null value for the context is illegal")
}
/**
* Gives the connectivity manager
* @param context The context
* @return the @code{[ConnectivityManager]}
* @throws IllegalArgumentException If the value of the context is @ code{null}
*/
@Throws(IllegalArgumentException::class)
private fun getConnectivityManager(context: Context?): ConnectivityManager {
if (context != null) {
return context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
}
throw IllegalArgumentException("Null value for the context is illegal")
}
/**
* Tells whether the network is facilitating fast network switching
* @param context The context.
* @param network The network.
* @return @code{true} if the network is facilitating fast network switching
* @throws UnsupportedOperationException if this function is running on an
* Android version lower than Pie
*/
private fun isNetworkFacilitatingFastNetworkSwitching(context: Context,
network: Network): Boolean {
var isNetworkFacilitatingFastNetworkSwitching = false
val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
if (SDK_INT >= VERSION_CODES.P) {
val networkCapabilities = connectivityManager.getNetworkCapabilities(network)
if (networkCapabilities != null && !networkCapabilities.hasCapability
(NetworkCapabilities
.NET_CAPABILITY_FOREGROUND)) {
isNetworkFacilitatingFastNetworkSwitching = true
}
} else {
Log.e("UnusableMethod", String())
}
return isNetworkFacilitatingFastNetworkSwitching
}
/**
* Tells whether the network can be used by apps
* @param context The context.
* @param network The network.
* @return @code{true} if the network can by used by apps
* @throws UnsupportedOperationException if this function is running on an
* Android version lower than Pie
* @throws IllegalArgumentException If the value of any parameter is @code{null}
*/
@Throws(IllegalArgumentException::class)
private fun isNetworkUsableByApps(context: Context, network: Network): Boolean {
var isNetworkUsableByApps = false
val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
if (SDK_INT >= VERSION_CODES.P) {
val networkCapabilities = connectivityManager.getNetworkCapabilities(network)
if (networkCapabilities != null && networkCapabilities.hasCapability
(NetworkCapabilities
.NET_CAPABILITY_FOREGROUND)) {
isNetworkUsableByApps = true
}
} else {
Log.e("UnusableMethod", String())
throw UnsupportedOperationException("Cannot use this method for the" +
" current API Level")
}
return isNetworkUsableByApps
}
/**
* Tells whether the specified network is suspended
* @param context The context
* @param network The network
* @throws UnsupportedOperationException If this function is running on an
* Android version lower than Pie
* @throws IllegalArgumentException If the value of any parameter is @code{null}
* @return @code{true} if the network is suspended, @code{false} otherwise
*/
@Throws(IllegalArgumentException::class)
private fun isNetworkSuspended(context: Context, network: Network): Boolean {
var isNetworkSuspended = false
val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
if (SDK_INT >= VERSION_CODES.P) {
val networkCapabilities = connectivityManager.getNetworkCapabilities(network)
if (networkCapabilities != null && !networkCapabilities.hasCapability
(NetworkCapabilities
.NET_CAPABILITY_NOT_SUSPENDED)) {
isNetworkSuspended = true
}
} else {
Log.e("UnusableMethod", String())
throw UnsupportedOperationException("Cannot use this method for the" +
" current API Level")
}
return isNetworkSuspended
}
/**
* Check if there is any connectivity at all to a specific network.
*
* @param context The Context.
* @return @code{true} if we are connected to a network, @code{false} otherwise.
* @link{NetworkCapabilities} or @link{Network} object is found
* @throws IllegalArgumentException If the value of the context is @code{null}
*/
@Throws(IllegalArgumentException::class)
fun isActiveNetworkConnected(context: Context): Boolean {
var isConnected = false
val connectivityManager = getConnectivityManager(context)
if (SDK_INT >= VERSION_CODES.LOLLIPOP) {
val network = getActiveNetwork(context)
if (network != null) {
val networkCapabilities = connectivityManager
.getNetworkCapabilities(network)
if (networkCapabilities != null) {
if (SDK_INT >= VERSION_CODES.P) {
if (networkCapabilities.hasCapability(
NetworkCapabilities.NET_CAPABILITY_INTERNET) /* API >= 21*/ &&
networkCapabilities.hasCapability(
NetworkCapabilities.NET_CAPABILITY_VALIDATED) /*API >= 23*/ &&
networkCapabilities.hasCapability(
NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED) /*API >= 28*/ &&
networkCapabilities.hasCapability(
NetworkCapabilities.NET_CAPABILITY_FOREGROUND)) /*API >= 28*/ {
isConnected = true
}
} else {
if (SDK_INT >= VERSION_CODES.M) {
if (networkCapabilities.hasCapability(
NetworkCapabilities.NET_CAPABILITY_INTERNET) /*API >= 21*/ &&
networkCapabilities.hasCapability(
NetworkCapabilities.NET_CAPABILITY_VALIDATED) /*API >= 23*/) {
isConnected = true
}
} else {
if (networkCapabilities.hasCapability(
NetworkCapabilities.NET_CAPABILITY_INTERNET) /*API >= 21*/) {
isConnected = true
}
}
}
} else {
Log.e("NullNetworkCapabilities", String())
}
} else {
Log.e("NullNetwork", String())
}
} else {
val info = getNetworkInformation(context)
/*
Works on emulator and devices. Note the use of @link{NetworkInfo
.isAvailable} - without this, @link{NetworkInfo.isConnected} can return
@code{true} when Wi-Fi is disabled (http://stackoverflow.com/a/2937915)
*/
isConnected = info != null && info.isAvailable && info.isConnected
}
if (isConnected) {
Log.v("NetworkInfo", "Connected State")
} else {
Log.v("NetworkInfo", "Not Connected State")
}
return isConnected
}
/**
* Check if there is any connectivity at all to a specific network.
*
* @param context The Context.
* @param network The network
* @return @code{true} if we are connected to a network, @code{false} otherwise.
* @throws IllegalArgumentException If the value of the context is @code{null}
*/
@Throws(IllegalArgumentException::class)
fun isConnected(context: Context, network: Network?): Boolean {
if (network != null) {
var isConnected = false
val connectivityManager = getConnectivityManager(context)
if (SDK_INT >= VERSION_CODES.LOLLIPOP) {
val networkCapabilities = connectivityManager
.getNetworkCapabilities(network)
if (SDK_INT >= VERSION_CODES.P) {
if (networkCapabilities != null) {
if (networkCapabilities
.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) /* API >= 21*/ &&
networkCapabilities.hasCapability(
NetworkCapabilities.NET_CAPABILITY_VALIDATED) /*API >= 23*/ &&
networkCapabilities.hasCapability(
NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED) /*API >= 28*/ &&
networkCapabilities.hasCapability(
NetworkCapabilities.NET_CAPABILITY_FOREGROUND)) /*API >= 28*/ {
isConnected = true
}
} else {
Log.e("UnusableMethod", "null NetworkCapabilities")
}
} else {
if (SDK_INT >= VERSION_CODES.M) {
if (networkCapabilities != null && networkCapabilities
.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) /*API >= 21*/ &&
networkCapabilities.hasCapability(
NetworkCapabilities.NET_CAPABILITY_VALIDATED) /*API >= 23*/) {
isConnected = true
}
} else if (networkCapabilities != null && networkCapabilities
.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) /*API >= 21*/) {
isConnected = true
}
}
} else {
val networksInformation = getAllNetworkInfo(context)
for (information in networksInformation) {
/*
Works on emulator and devices. Note the use of @link{NetworkInfo
.isAvailable} - without this, @link{NetworkInfo.isConnected} can return
@code{true} when Wi-Fi is disabled (http://stackoverflow.com/a/2937915)
*/
isConnected = information != null && information.isAvailable && information.isConnected
if (isConnected) {
break
}
}
}
if (isConnected) {
Log.v("NetworkInfo", "Connected State")
} else {
Log.v("NetworkInfo", "Not Connected State")
}
return isConnected
}
throw IllegalArgumentException("Null value for the context is illegal")
}
/**
* Check if the device is connecting to a network.
*
* @param context the Context.
* @return @code{true} if we are connected to a network, false otherwise.
*/
@JvmStatic
fun isConnecting(context: Context?): Boolean {
var isConnecting = false
getConnectivityManager(context)
if (SDK_INT >= VERSION_CODES.LOLLIPOP) {
throw UnsupportedOperationException("Cannot use this method for the " +
"current API level")
} else {
val networksInformation = getAllNetworkInfo(context)
for (info in networksInformation) {
if (info != null) {
isConnecting = !isConnected(context) && info.isConnectedOrConnecting
if (isConnecting) {
break
}
}
}
}
if (isConnecting) {
Log.v("NetworkInfo", "Connecting State")
} else {
Log.v("NetworkInfo", "Not Connecting State")
}
return isConnecting
}
/**
* Check if the device is connected or connecting.
*
* @param context the Context.
* @return @code{true} if we are connected to a network, false otherwise.
*/
@JvmStatic
fun isConnectedOrConnecting(context: Context?): Boolean {
var isConnectedOrConnecting = false
getConnectivityManager(context)
if (SDK_INT >= VERSION_CODES.LOLLIPOP) {
throw UnsupportedOperationException("Cannot use this method for the " +
"current API level")
} else {
val networksInformation = getAllNetworkInfo(context)
for (info in networksInformation) {
if (info != null) {
isConnectedOrConnecting = isConnected(context).xor(!isConnected
(context) && info.isConnectedOrConnecting)
if (isConnectedOrConnecting) {
break
}
}
}
}
if (isConnectedOrConnecting) {
Log.v("NetworkInfo", "Connected State")
} else {
Log.v("NetworkInfo", "Not Connected State")
}
return isConnectedOrConnecting
}
/**
* Check if there is any connectivity at all.
*
* @param context the Context.
* @return @code{true} if we are connected to a network, false otherwise.
*/
@JvmStatic
fun isConnected(context: Context?): Boolean {
var isConnected = false
if(context != null) {
val connectivityManager = getConnectivityManager(context)
if (SDK_INT >= VERSION_CODES.LOLLIPOP) {
if(isThereAnActiveNetworkConnection(context)) {
isConnected = isActiveNetworkConnected(context)
} else {
val networks = connectivityManager.allNetworks
for (network in networks) {
if (network != null) {
val networkCapabilities = connectivityManager
.getNetworkCapabilities(network)
if (networkCapabilities != null) {
if (SDK_INT >= VERSION_CODES.P) {
if ((networkCapabilities
.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) /* API >= 21*/ &&
networkCapabilities.hasCapability(
NetworkCapabilities.NET_CAPABILITY_VALIDATED) /* API >= 23*/ &&
networkCapabilities.hasCapability(
NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED)) /* API >= 28*/ &&
networkCapabilities.hasCapability(
NetworkCapabilities.NET_CAPABILITY_FOREGROUND)) /* API >= 28*/ {
isConnected = true
break
}
} else {
if (SDK_INT >= VERSION_CODES.M) {
if (networkCapabilities
.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) /*API >= 21*/ &&
networkCapabilities.hasCapability(
NetworkCapabilities.NET_CAPABILITY_VALIDATED) /*API >= 23*/) {
isConnected = true
break
}
} else {
if (networkCapabilities
.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) /*API >= 21*/) {
isConnected = true
break
}
}
}
} else {
Log.e("NullNetworkCapabilities", String())
}
} else {
Log.e("NullNetwork", String())
}
}
}
} else {
val networksInformation = getAllNetworkInfo(context)
for (info in networksInformation) {
/*
Works on emulator and devices. Note the use of @link{NetworkInfo
.isAvailable} - without this, @link{NetworkInfo.isConnected} can
return @code{true} when Wi-Fi is disabled (http://stackoverflow
.com/a/2937915)
*/
isConnected = info != null && info.isAvailable && info.isConnected
if (isConnected) {
break
}
}
}
if (isConnected) {
Log.v("NetworkInfo", "Connected State")
} else {
Log.v("NetworkInfo", "Not Connected State")
}
return isConnected
}
throw IllegalArgumentException("Null value for the context is illegal")
}
/**
* Check if there is any connectivity to a Wifi network.
*
* @param context the Context.
* @return @code{true} if we are connected to a Wifi network, false otherwise.
*/
@Suppress("WeakerAccess")
fun isConnectedWifi(context: Context?): Boolean {
var isConnectedWifi = false
val connectivityManager = getConnectivityManager(context)
if (SDK_INT >= VERSION_CODES.LOLLIPOP) {
val networks = connectivityManager.allNetworks
for (network in networks) {
if (network != null) {
val networkCapabilities = connectivityManager
.getNetworkCapabilities(network)
if (networkCapabilities != null) {
if (SDK_INT >= VERSION_CODES.P) {
if ((networkCapabilities.hasCapability(
NetworkCapabilities.NET_CAPABILITY_INTERNET) /* API >= 21*/ &&
networkCapabilities
.hasCapability(
NetworkCapabilities.NET_CAPABILITY_VALIDATED) /*API>=23*/ &&
networkCapabilities.hasCapability(
NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED)) /*API>=28*/ &&
networkCapabilities.hasCapability(
NetworkCapabilities.NET_CAPABILITY_FOREGROUND)) /*API>=28*/ {
if (networkCapabilities.hasTransport(
NetworkCapabilities.TRANSPORT_WIFI)) {
isConnectedWifi = true
break
}
}
} else {
if (SDK_INT >= VERSION_CODES.M) {
if (networkCapabilities.hasCapability(
NetworkCapabilities.NET_CAPABILITY_INTERNET) /*API >= 21*/ &&
networkCapabilities.hasCapability(
NetworkCapabilities.NET_CAPABILITY_VALIDATED) /*API >= 23*/) {
if (networkCapabilities.hasTransport(
NetworkCapabilities.TRANSPORT_WIFI)) {
isConnectedWifi = true
break
}
}
} else {
if (networkCapabilities.hasCapability(
NetworkCapabilities.NET_CAPABILITY_INTERNET) /*API >= 21*/) {
if (networkCapabilities.hasTransport(
NetworkCapabilities.TRANSPORT_WIFI)) {
isConnectedWifi = true
break
}
}
}
}
} else {
Log.e("NullNetworkCapabilities", String())
}
} else {
Log.e("NullNetwork", String())
}
}
} else {
val networksInformation = getAllNetworkInfo(context)
for (info in networksInformation) {
/*
Works on emulator and devices. Note the use of @link{NetworkInfo
.isAvailable} - without this, @link{NetworkInfo.isConnected} can
return @code{true} when Wi-Fi is disabled (http://stackoverflow
.com/a/2937915)
*/
isConnectedWifi = (info != null && info.isAvailable && info.isConnected &&
info.type == ConnectivityManager.TYPE_WIFI)
if (isConnectedWifi) {
break
}
}
}
if (isConnectedWifi) {
Log.v("NetworkInfo", "Connected Wi-Fi State")
} else {
Log.v("NetworkInfo", "Not Connected Wi-Fi State")
}
return isConnectedWifi
}
/**
* Check if there is any connectivity to a Wifi network on a specific network.
*
* @param context The context.
* @param network The network
* @return @code{true} if we are connected to a Wifi network, @code{false}
* otherwise
*/
@Suppress("WeakerAccess")
fun isConnectedWifi(context: Context, network: Network?): Boolean {
var isConnectedWifi = false
val connectivityManager = getConnectivityManager(context)
if (SDK_INT >= VERSION_CODES.LOLLIPOP) {
val networkCapabilities = connectivityManager
.getNetworkCapabilities(network)
if (SDK_INT >= VERSION_CODES.P) {
if (network != null) {
if (networkCapabilities != null) {
if ((networkCapabilities
.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) /* API >= 21*/ &&
networkCapabilities.hasCapability(
NetworkCapabilities.NET_CAPABILITY_VALIDATED) /*API>=23*/ &&
networkCapabilities.hasCapability(
NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED)) /*API>=28*/ &&
networkCapabilities.hasCapability(
NetworkCapabilities.NET_CAPABILITY_FOREGROUND)) /*API>=28*/ {
if (networkCapabilities
.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
isConnectedWifi = true
}
}
} else {
Log.e("NullNetworkCapabilities", "a null " +
"NetworkCapabilities object was found")
}
} else {
Log.e("NullNetwork", "a null Network object was found")
}
} else {
if (network != null) {
if (networkCapabilities != null) {
if (SDK_INT >= VERSION_CODES.M) {
if (networkCapabilities
.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) /*API >= 21*/ &&
networkCapabilities.hasCapability(
NetworkCapabilities.NET_CAPABILITY_VALIDATED) /*API >= 23*/) {
if (networkCapabilities
.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
isConnectedWifi = true
}
}
} else {
if (networkCapabilities
.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) /*API >= 21*/) {
if (networkCapabilities
.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
isConnectedWifi = true
}
}
}
} else {
Log.e("NullNetwordCapabilities", "a null " +
"NetworkCapabilities object was found")
}
} else {
Log.e("NullNetwork", "a null Network object was found")
}
}
} else {
val networksInformation = getAllNetworkInfo(context)
for (information in networksInformation) {
/*
Works on emulator and devices. Note the use of @link{NetworkInfo
.isAvailable} - without this, @link{NetworkInfo.isConnected} can return
@code{true} when Wi-Fi is disabled (http://stackoverflow.com/a/2937915)
*/
isConnectedWifi = (information != null && information.isAvailable && information.isConnected &&
information.type == ConnectivityManager.TYPE_WIFI)
if (isConnectedWifi) {
break
}
}
}
if (isConnectedWifi) {
Log.v("NetworkInfo", "Connected Wi-Fi State")
} else {
Log.v("NetworkInfo", "Not Connected Wi-Fi State")
}
return isConnectedWifi
}
/**
* Check if there is any connectivity to a Wifi network with airplane mode on.
*
* @param context The context.
* @return @code{true} if we are connected to a Wifi network over airplane mode
*/
fun isConnectedWifiOverAirplaneMode(context: Context): Boolean {
return isConnectedWifi(context) && isAirplaneModeOn(context)
}
/**
* Check if there is any connectivity to a Wifi network on a specific network with airplane mode on.
*
* @param context The context.
* @param network The network
* @return @code{true} if we are connected to a specific Wifi network over
* airplane mode.
*/
fun isConnectedWifiOverAirplaneMode(context: Context, network: Network?): Boolean {
return isConnectedWifi(context, network) && isAirplaneModeOn(context)
}
/**
* Checks via @link{TelephonyManager} if there is mobile data connection
* @return @code{true} if the device has mobile data connection
* @param context the context
*/
fun isConnectedMobileTelephonyManager(context: Context): Boolean {
val tm = context
.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
val state = tm.dataState
return state == TelephonyManager.DATA_CONNECTED
}
/**
* Check if there is any connectivity to a mobile network.
*
* @param context The Context.
* @param network The network
* @return @code{true} if we are connected to a mobile network.
*/
fun isConnectedMobile(context: Context, network: Network?): Boolean {
var isConnectedMobile = false
val connectivityManager = getConnectivityManager(context)
if (SDK_INT >= VERSION_CODES.LOLLIPOP) {
val networkCapabilities = connectivityManager
.getNetworkCapabilities(network)
if (SDK_INT >= VERSION_CODES.P) {
if (network != null) {
if (networkCapabilities != null) {
if ((networkCapabilities
.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) /* API >= 21*/ &&
networkCapabilities.hasCapability(
NetworkCapabilities.NET_CAPABILITY_VALIDATED) /*API>=23*/ &&
networkCapabilities.hasCapability(
NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED)) /*API>=28*/ &&
networkCapabilities.hasCapability(
NetworkCapabilities.NET_CAPABILITY_FOREGROUND)) /*API>=28*/ {
if (networkCapabilities
.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
isConnectedMobile = true
}
}
} else {
Log.e("NullNetworkCapabilities", "A null " +
"NetworkCapabilities object was found")
}
} else {
Log.e("NullNetwork", "A null Network object was found")
}
} else {
if (network != null) {
if (networkCapabilities != null) {
if (SDK_INT >= VERSION_CODES.M) {
if (networkCapabilities
.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) /*API >= 21*/ &&
networkCapabilities.hasCapability(
NetworkCapabilities.NET_CAPABILITY_VALIDATED) /*API >= 23*/) {
if (networkCapabilities
.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
isConnectedMobile = true
}
}
} else {
if (networkCapabilities
.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) /*API >= 21*/) {
if (networkCapabilities
.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
isConnectedMobile = true
}
}
}
} else {
Log.e("NullNetworkCapabilities", "a null " +
"NetworkCapabilities object was found")
}
} else {
Log.e("NullNetwork", "a null Network object was found")
}
}
} else {
val networksInformation = getAllNetworkInfo(context)
for (networkInformation in networksInformation) {
/*
Works on emulator and devices. Note the use of @link{NetworkInfo
.isAvailable} - without this, @link{NetworkInfo.isConnected} can return
@code{true} when Wi-Fi is disabled (http://stackoverflow.com/a/2937915)
*/
isConnectedMobile = (networkInformation != null && networkInformation.isAvailable && networkInformation.isConnected &&
networkInformation.type == ConnectivityManager.TYPE_MOBILE)
if (isConnectedMobile) {
break
}
}
}
if (isConnectedMobile) {
Log.v("NetworkInfo", "Connected Mobile State")
} else {
Log.v("NetworkInfo", "Not Connected Mobile State")
}
return isConnectedMobile
}
/**
* Check if there is any connectivity to a mobile network.
*
* @param context the context.
* @return @code{true} if we are connected to a mobile network.
*/
fun isConnectedMobile(context: Context?): Boolean {
var isConnectedMobile = false
val connectivityManager = getConnectivityManager(context)
if (SDK_INT >= VERSION_CODES.LOLLIPOP) {
val networks = connectivityManager.allNetworks
for (network in networks) {
val networkCapabilities = connectivityManager
.getNetworkCapabilities(network)
if (SDK_INT >= VERSION_CODES.P) {
if (network != null) {
if (networkCapabilities != null) {
if ((networkCapabilities
.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) /* API >= 21*/ &&
networkCapabilities.hasCapability(
NetworkCapabilities.NET_CAPABILITY_VALIDATED) /*API >= 23*/ &&
networkCapabilities.hasCapability(
NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED)) /*API >= 28*/ &&
networkCapabilities.hasCapability(
NetworkCapabilities.NET_CAPABILITY_FOREGROUND)) /*API >= 28*/ {
if (networkCapabilities.hasTransport(
NetworkCapabilities.TRANSPORT_CELLULAR)) {
isConnectedMobile = true
break
}
}
} else {
Log.e("NullNetworkCapabilities", "a null " +
"NetworkCapabilities object was found")
}
} else {
Log.e("NullNetwork", "a null Network object was found")
}
} else {
if (network != null) {
if (networkCapabilities != null) {
if (SDK_INT >= VERSION_CODES.M) {
if (networkCapabilities
.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) /*API >= 21*/ &&
networkCapabilities.hasCapability(
NetworkCapabilities.NET_CAPABILITY_VALIDATED) /*API >= 23*/) {
if (networkCapabilities.hasTransport(
NetworkCapabilities.TRANSPORT_CELLULAR)) {
isConnectedMobile = true
break
}
}
} else {
if (networkCapabilities
.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) /*API >= 21*/) {
if (networkCapabilities.hasTransport(
NetworkCapabilities.TRANSPORT_CELLULAR)) {
isConnectedMobile = true
break
}
}
}
} else {
Log.e("NullNetworkCapabilities", "a null " +
"NetworkCapabilities object was found")
}
} else {
Log.e("NullNetwork", "a null Network object was found")
}
}
}
} else {
val networksInformation = getAllNetworkInfo(context)
for (info in networksInformation) {
/*
Works on emulator and devices. Note the use of @link{NetworkInfo
.isAvailable} - without this, @link{NetworkInfo.isConnected} can
return @code{true} when Wi-Fi is disabled (http://stackoverflow
.com/a/2937915)
*/
isConnectedMobile = (info != null && info.isAvailable && info.isConnected &&
info.type == ConnectivityManager.TYPE_MOBILE)
if (isConnectedMobile) {
break
}
}
}
if (isConnectedMobile) {
Log.v("NetworkInfo", "Connected Mobile State")
} else {
Log.v("NetworkInfo", "Not Connected Mobile State")
}
return isConnectedMobile
}
/**
* Check if there is any connectivity to a ethernet network.
*
* @param context the context.
* @return @code{true} if we are connected to a ethernet network.
*/
fun isConnectedEthernet(context: Context?): Boolean {
var isConnectedEthernet = false
val connectivityManager = getConnectivityManager(context)
if (SDK_INT >= VERSION_CODES.LOLLIPOP) {
val networks = connectivityManager.allNetworks
for (network in networks) {
val networkCapabilities = connectivityManager
.getNetworkCapabilities(network)
if (SDK_INT >= VERSION_CODES.P) {
if (network != null) {
if (networkCapabilities != null) {
if ((networkCapabilities
.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) /* API >= 21*/ &&
networkCapabilities.hasCapability(
NetworkCapabilities.NET_CAPABILITY_VALIDATED) /*API >= 23*/ &&
networkCapabilities.hasCapability(
NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED)) /*API >= 28*/ &&
networkCapabilities.hasCapability(
NetworkCapabilities.NET_CAPABILITY_FOREGROUND)) /*API >= 28*/ {
if (networkCapabilities.hasTransport(
NetworkCapabilities.TRANSPORT_ETHERNET)) {
isConnectedEthernet = true
break
}
}
} else {
Log.e("NullNetworkCapabilities", "a null " +
"NetworkCapabilities object was found")
}
} else {
Log.e("NullNetwork", "a null Network object was found")
}
} else {
if (network != null) {
if (networkCapabilities != null) {
if (SDK_INT >= VERSION_CODES.M) {
if (networkCapabilities
.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) /*API >= 21*/ &&
networkCapabilities.hasCapability(
NetworkCapabilities.NET_CAPABILITY_VALIDATED) /*API >= 23*/) {
if (networkCapabilities.hasTransport(
NetworkCapabilities.TRANSPORT_ETHERNET)) {
isConnectedEthernet = true
break
}
}
} else {
if (networkCapabilities
.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) /*API >= 21*/) {
if (networkCapabilities.hasTransport(
NetworkCapabilities.TRANSPORT_ETHERNET)) {
isConnectedEthernet = true
break
}
}
}
} else {
Log.e("NullNetworkCapabilities", "a null " +
"NetworkCapabilities object was found")
}
} else {
Log.e("NullNetwork", "a null Network object was found")
}
}
}
} else {
val networksInformation = getAllNetworkInfo(context)
for (info in networksInformation) {
/*
Works on emulator and devices. Note the use of @link{NetworkInfo
.isAvailable} - without this, @link{NetworkInfo.isConnected} can
return @code{true} when Wi-Fi is disabled (http://stackoverflow
.com/a/2937915)
*/
isConnectedEthernet = (info != null && info.isAvailable && info.isConnected &&
info.type == ConnectivityManager.TYPE_ETHERNET)
if (isConnectedEthernet) {
break
}
}
}
if (isConnectedEthernet) {
Log.v("NetworkInfo", "Connected Ethernet State")
} else {
Log.v("NetworkInfo", "Not Connected Ethernet State")
}
return isConnectedEthernet
}
/**
* Check if a specific network has ethernet connectivity.
*
* @param context The context.
* @param network The network
* @return @code{true} if we are connected to a ethernet network.
*/
fun isConnectedEthernet(context: Context, network: Network?): Boolean {
var isConnectedEthernet = false
val connectivityManager = getConnectivityManager(context)
if (SDK_INT >= VERSION_CODES.LOLLIPOP) {
val networkCapabilities = connectivityManager
.getNetworkCapabilities(network)
if (SDK_INT >= VERSION_CODES.P) {
if (network != null) {
if (networkCapabilities != null) {
if ((networkCapabilities
.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) /* API >= 21*/ &&
networkCapabilities.hasCapability(
NetworkCapabilities.NET_CAPABILITY_VALIDATED) /*API >= 23*/ &&
networkCapabilities.hasCapability(
NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED)) /*API >= 28*/ &&
networkCapabilities.hasCapability(
NetworkCapabilities.NET_CAPABILITY_FOREGROUND)) /*API >= 28*/ {
if (networkCapabilities
.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET)) {
isConnectedEthernet = true
}
}
} else {
Log.e("NullNetworkCapabilities", "a null " +
"NetworkCapabilities object was found")
}
} else {
Log.e("NullNetwork", "a null Network object was found")
}
} else {
if (network != null) {
if (networkCapabilities != null) {
if (SDK_INT >= VERSION_CODES.M) {
if (networkCapabilities
.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) /*API >= 21*/ &&
networkCapabilities.hasCapability(
NetworkCapabilities.NET_CAPABILITY_VALIDATED) /*API >= 23*/) {
if (networkCapabilities
.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET)) {
isConnectedEthernet = true
}
}
} else {
if (networkCapabilities
.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) /*API >= 21*/) {
if (networkCapabilities
.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET)) {
isConnectedEthernet = true
}
}
}
} else {
Log.e("NullNetworkCapabilities", "a null " +
"NetworkCapabilities object was found")
}
} else {
Log.e("NullNetwork", "a null Network object was found")
}
}
} else {
val networksInformation = getAllNetworkInfo(context)
for (networkInformation in networksInformation) {
/*
Works on emulator and devices. Note the use of @link{NetworkInfo
.isAvailable} - without this, @link{NetworkInfo.isConnected} can return
@code{true} when Wi-Fi is disabled (http://stackoverflow.com/a/2937915)
*/
isConnectedEthernet = (networkInformation != null && networkInformation.isAvailable && networkInformation.isConnected &&
networkInformation.type == ConnectivityManager.TYPE_ETHERNET)
if (isConnectedEthernet) {
break
}
}
}
if (isConnectedEthernet) {
Log.v("NetworkInfo", "Connected Ethernet State")
} else {
Log.v("NetworkInfo", "Not Connected Ethernet State")
}
return isConnectedEthernet
}
/**
* Check if there is fast connectivity.
*
* @param context the Context.
* @return @code{true} if we have "fast" connectivity.
*/
fun isConnectedFast(context: Context): Boolean {
var isConnectedFast = false
if (SDK_INT < VERSION_CODES.LOLLIPOP) {
val networksInformation = getAllNetworkInfo(context)
for (networkInfo in networksInformation) {
isConnectedFast = (networkInfo != null && networkInfo.isAvailable &&
networkInfo.isConnected &&
isConnectionFast(networkInfo.type, networkInfo.subtype))
if (isConnectedFast) {
break
}
}
} else {
val connectivityManager = getConnectivityManager(context)
val allNetworks = connectivityManager.allNetworks
for (network in allNetworks) {
if (network != null && isConnected(context, network)) {
val networkCapabilities = connectivityManager
.getNetworkCapabilities(network)
if (networkCapabilities != null) {
val linkDownstreamBandwidthKbps = networkCapabilities
.linkDownstreamBandwidthKbps
val linkUpstreamBandwidthKbps = networkCapabilities
.linkUpstreamBandwidthKbps
if (linkDownstreamBandwidthKbps >= minimumSpeedForFastConnection &&
linkUpstreamBandwidthKbps >= minimumSpeedForFastConnection) {
isConnectedFast = true
break
}
}
}
}
}
if (isConnectedFast) {
Log.v("NetworkInfo", "Connected Fast State")
} else {
Log.v("NetworkInfo", "Not Connected Fast State")
}
return isConnectedFast
}
/**
* Check if there is fast connectivity over a specific network.
*
* @param context The Context.
* @param network The network
* @return @code{true} if we have "fast" connectivity.
*/
fun isConnectedFast(context: Context, network: Network?): Boolean {
var isConnectedFast = false
if (SDK_INT < VERSION_CODES.LOLLIPOP) {
val networkInformation = getNetworkInformation(context)
isConnectedFast = (networkInformation != null && networkInformation.isAvailable &&
networkInformation.isConnected &&
isConnectionFast(networkInformation.type, networkInformation.subtype))
} else {
val connectivityManager = getConnectivityManager(context)
if (network != null && isConnected(context, network)) {
val networkCapabilities = connectivityManager
.getNetworkCapabilities(network)
if (networkCapabilities != null) {
val linkDownstreamBandwidthKbps = networkCapabilities
.linkDownstreamBandwidthKbps
val linkUpstreamBandwidthKbps = networkCapabilities
.linkUpstreamBandwidthKbps
if (linkDownstreamBandwidthKbps >= minimumSpeedForFastConnection &&
linkUpstreamBandwidthKbps >= minimumSpeedForFastConnection) {
isConnectedFast = true
}
}
}
}
if (isConnectedFast) {
Log.v("NetworkInfo", "Connected Fast State")
} else {
Log.v("NetworkInfo", "Not Connected Fast State")
}
return isConnectedFast
}
/**
* Determines if the airplane mode is on
* @param context The context
* @return @code{true} if the airplane mode is on
*/
// Source: https://stackoverflow.com/a/59415354/5520417
@TargetApi(VERSION_CODES.JELLY_BEAN_MR1)
fun isAirplaneModeOn(context: Context): Boolean {
val isAirplaneModeOn: Boolean =
if (SDK_INT < VERSION_CODES.JELLY_BEAN_MR1) {
Settings.System.getInt(context.contentResolver,
Settings.System.AIRPLANE_MODE_ON, 0) != 0
} else {
Settings.Global.getInt(context.contentResolver,
Settings.Global.AIRPLANE_MODE_ON, 0) != 0
}
if (isAirplaneModeOn) {
Log.v("NetworkInfo", "Airplane Mode is On")
} else {
Log.v("NetworkInfo", "Airplane Mode is Off")
}
return isAirplaneModeOn
}
/**
* Checks whether a VPN connection is active
* @param context The context
* @return @code{true} if a VPN connection is active, @code{false} otherwise
* @throws UnsupportedOperationException If the Android version is not
* compatible with this method
*/
//Source: https://stackoverflow.com/a/58892241/5520417
@Throws(UnsupportedOperationException::class)
fun vpnActive(context: Context): Boolean {
//This method doesn't work below API 21
if (SDK_INT < VERSION_CODES.LOLLIPOP) {
throw UnsupportedOperationException("Cannot use this method for the" +
" current API Level")
}
var vpnInUse: Boolean
vpnInUse = false
val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
if (SDK_INT >= VERSION_CODES.M) {
val activeNetwork = getActiveNetwork(context)
val activeNetworksCapabilities = connectivityManager.getNetworkCapabilities(activeNetwork)
vpnInUse = activeNetworksCapabilities != null &&
activeNetworksCapabilities.hasTransport(NetworkCapabilities
.TRANSPORT_VPN)
} else {
val networks = connectivityManager.allNetworks
for (i in networks.indices) {
val caps = connectivityManager.getNetworkCapabilities(networks[i])
if (caps != null && caps.hasTransport(NetworkCapabilities
.TRANSPORT_VPN)) {
vpnInUse = true
break
}
}
}
return vpnInUse
}
/**
* Check if the connection is fast
* @param type The network type
* @param subType The network subtype
* @return @code {true} if the connection is fast
*/
private fun isConnectionFast(type: Int, subType: Int): Boolean {
return if (type == ConnectivityManager.TYPE_WIFI ||
type == ConnectivityManager.TYPE_ETHERNET) {
true
} else
if (type == ConnectivityManager.TYPE_MOBILE) {
when (subType) {
TelephonyManager.NETWORK_TYPE_EVDO_0 /* ~ 400-1000 kbps
*/,
TelephonyManager.NETWORK_TYPE_EVDO_A /* ~ 600-1400 kbps
*/,
TelephonyManager.NETWORK_TYPE_HSDPA /* ~ 2-14 Mbps */,
TelephonyManager.NETWORK_TYPE_HSPA /* ~ 700-1700 kbps
*/, TelephonyManager
.NETWORK_TYPE_HSUPA /* ~ 1-23 Mbps */, TelephonyManager
.NETWORK_TYPE_UMTS /* ~ 400-7000 kbps */,
TelephonyManager
.NETWORK_TYPE_EHRPD /* ~ 1-2 Mbps */,
TelephonyManager
.NETWORK_TYPE_EVDO_B /* ~ 5 Mbps */,
TelephonyManager
.NETWORK_TYPE_HSPAP /* ~ 10-20 Mbps */,
TelephonyManager
.NETWORK_TYPE_LTE /* ~ 10+ Mbps */ -> true
TelephonyManager.NETWORK_TYPE_1xRTT /* ~ 50-100
kbps */,
TelephonyManager.NETWORK_TYPE_CDMA /* ~ 14-64 kbps
*/,
TelephonyManager.NETWORK_TYPE_EDGE /* ~ 50-100 kbps
*/,
TelephonyManager.NETWORK_TYPE_GPRS /* ~ 100 kbps */,
TelephonyManager.NETWORK_TYPE_IDEN /* ~25 kbps */,
TelephonyManager.NETWORK_TYPE_UNKNOWN -> false
else -> false
}
} else {
false
}
}
//-------------------------------------- Internet Reachability Verification ----------------------------------------------------
/**
* A list of hosts to verify Internet access
*/
private
var hosts: ArrayList<String> = object : ArrayList<String>() {
init {
add("wolfram.com")
add("wolframalpha.com")
add("google.com")
add("facebook.com")
add("apple.com")
add("amazon.com")
add("twitter.com")
add("linkedin.com")
add("microsoft.com")
}
}
/**
* Tells whether Internet is reachable
* @return @code{true} if Internet is reachable, false otherwise
* @param context The context
*/
fun isInternetReachable(context: Context?): Boolean {
val isInternetReachable: Boolean
try {
InternetConnectionCheck(context).also {
isInternetReachable = it.execute()
.get()
}
return isInternetReachable
} catch (e: CancellationException) {
e.printStackTrace()
} catch (e: Exception) {
e.printStackTrace()
}
return false
}
/**
* Tells whether Internet is reachable
* @return @code{true} if Internet is reachable, false otherwise
* @param context The context
* @param hosts The hosts
*/
fun isInternetReachable(context: Context?, hosts: ArrayList<String>): Boolean {
var isInternetReachable: Boolean
isInternetReachable = false
try {
val internetConnectionCheckAsync = InternetConnectionCheck(
context)
val connectivityAndInternetAccessCheck = ConnectivityAndInternetAccess(hosts)
connectivityAndInternetAccessCheck.hosts = hosts
isInternetReachable = internetConnectionCheckAsync.execute().get()
} catch (e: CancellationException) {
e.printStackTrace()
} catch (e: Exception) {
e.printStackTrace()
}
return isInternetReachable
}
/**
* Tells whether there is Internet connection
* @param context The context
* @return @code {true} if there is Internet connection
*/
private fun isConnectedToInternet(context: Context?): Boolean {
var isConnectedToInternet = false
while (isConnected(context)) {
try {
for (h in hosts) {
if (isHostAvailable(h, context)) {
isConnectedToInternet = true
break
}
}
} catch (e: IOException) {
e.printStackTrace()
}
}
return isConnectedToInternet
}
/**
* Tells whether there is Internet connection
* @param context The context
* @param hosts The hosts
* @return @code {true} if there is Internet connection
*/
private fun isConnectedToInternet(context: Context, hosts: ArrayList<String>):
Boolean {
var isConnectedToInternet = false
while (isConnected(context)) {
try {
for (h in hosts) {
if (isHostAvailable(h, context)) {
isConnectedToInternet = true
break
}
}
} catch (e: IOException) {
e.printStackTrace()
}
}
return isConnectedToInternet
}
/**
* Validates the URL.
* @param url The URL to validate
* @throws IllegalArgumentException In case the URL is @code{null}
*/
// Source: https://stackoverflow.com/a/17894617/5520417
private fun isValidURL(url: String?): Boolean {
if (url != null) {
return try {
URL(url).toURI()
true
} catch (e: MalformedURLException) {
false
} catch (e: URISyntaxException) {
false
}
}
throw IllegalArgumentException("The URL cannot be null")
}
/**
* Validates the URL list.
* @param url The URL to validate
* @throws IllegalArgumentException In case the URL is @code{null}
*/
// Source: https://stackoverflow.com/a/17894617/5520417
private fun isValidURL(url: ArrayList<String>?): Boolean {
if (url != null) {
for (u in url) {
if (!isValidURL(u)) {
return false
}
}
return true
}
throw IllegalArgumentException("The URL cannot be null")
}
/**
* Checks if the host is available
* @param hostName The name of the host
* @param context The context
* @return @code{true} if the host is available
* @throws IOException In case an error happens during the connection
* @throws IllegalArgumentException If a parameter has @code{null} value
* @throws MalformedURLException If the URL is invalid
*/
@Throws(IOException::class, IllegalBlockingModeException::class, IllegalArgumentException::class)
private fun isHostAvailable(hostName: String, context: Context?): Boolean {
if (context != null) {
var isHostAvailable: Boolean
isHostAvailable = false
if (SDK_INT >= VERSION_CODES.KITKAT) {
while (isConnected(context)) {
try {
Socket().use { socket ->
if (isValidURL("http:/$hostName") || isValidURL
("http://$hostName") || isValidURL
("ftp://@$hostName")) {
val port = 80
val socketAddress = InetSocketAddress(hostName, port)
socket.connect(socketAddress, 3000)
isHostAvailable = true
} else {
throw MalformedURLException("The URL is invalid")
}
}
} catch (exception: Exception) {
return when (exception) {
is IOException,
is SocketTimeoutException, is IllegalBlockingModeException,
is IllegalArgumentException -> false
else -> {
if (exception is UnknownHostException) {
exception.printStackTrace()
Log.e("Internet Access", "Unknown host: $hostName")
isHostAvailable = false
} else if (exception is SecurityException) {
exception.printStackTrace()
Log.e("Internet Access", "A security manager exists and its " +
"checkConnect method does not allow the operation")
isHostAvailable = false
}
exception.printStackTrace()
Log.e("Internet Access", "An non-ordinary exception" +
" ocurred when verifying Internet Access")
throw UnsupportedOperationException("The current " +
"operation is not supported because an " +
"uncommon exception occurred")
}
}
}
}
Log.e("Internet Access", "Could not verify Internet access because " +
"the device lost the network connectivity")
if (isHostAvailable) {
Log.v("Internet Access", "Host reached: $hostName")
} else {
Log.v("Internet Access", "Host not available: $hostName")
}
return isHostAvailable
}
while (isConnected(context)) {
// Source: https://stackoverflow.com/a/54250438/5520417
try {
if (InetAddress.getByName(hostName) != null) {
isHostAvailable = true
}
isHostAvailable = false
} catch (e: UnknownHostException) {
e.printStackTrace()
isHostAvailable = false
} catch (e: SecurityException) {
e.printStackTrace()
Log.e("Internet Access", "A security manager exists and its " +
"checkConnect method does not allow the operation")
isHostAvailable = false
}
}
if (isHostAvailable) {
Log.v("Internet Access", "Host reached: $hostName")
} else {
Log.v("Internet Access", "Host not available: $hostName")
}
return isHostAvailable
}
throw IllegalArgumentException("Parameters cannot take null value")
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment