Created
April 1, 2022 09:21
-
-
Save gianpaolof/017f462cca2bd9d8a29d052b5e1712ce to your computer and use it in GitHub Desktop.
Class to check the Connectivity and Internet Access of an Android device.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* 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