50

I tried the answer from this (the accepted answer). I can use the "PING" method but the UI went black since it says it will block the UI Thread. It didn't look good and was disturbing so I tried to use the second method "Connect to a Socket on the Internet" but I don't know how to use the class in Kotlin.

This is the result of converted Java to kotlin by android studio

package com.mockie.daikokuten.helpers

import android.os.AsyncTask.execute
import android.os.AsyncTask
import java.io.IOException
import java.net.InetSocketAddress
import java.net.Socket


internal class InternetCheck(private val mConsumer: Consumer) : AsyncTask<Void, Void, Boolean>() {
interface Consumer {
    fun accept(internet: Boolean?)
}

init {
    execute()
}

override fun doInBackground(vararg voids: Void): Boolean? {
    try {
        val sock = Socket()
        sock.connect(InetSocketAddress("8.8.8.8", 53), 1500)
        sock.close()
        return true
    } catch (e: IOException) {
        return false
    }

}

override fun onPostExecute(internet: Boolean?) {
    mConsumer.accept(internet)
}
}

but I DONT KNOW HOW TO USE IT. I tried this way:

InternetCheck{ internet-> Log.d("test", "asdasdas") }

It didnt work and results in an error. It says I have to pass "Consumer".

My question is How to use that class?

Kakashi
  • 3,329
  • 4
  • 26
  • 37

12 Answers12

76

Update: Since Android 10 the use of the NetWorkInfo class and its methods are obsolete, now you must use the ConectivityManager class and getNetworkCapabilities () method from NetworkCapabilities Class.

How to check connectivity in Android?

Kotlin :

fun isOnline(context: Context): Boolean {
    val connectivityManager =
        context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
    if (connectivityManager != null) {
        val capabilities =
            connectivityManager.getNetworkCapabilities(connectivityManager.activeNetwork)
        if (capabilities != null) {
            if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
                Log.i("Internet", "NetworkCapabilities.TRANSPORT_CELLULAR")
                return true
            } else if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
                Log.i("Internet", "NetworkCapabilities.TRANSPORT_WIFI")
                return true
            } else if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET)) {
                Log.i("Internet", "NetworkCapabilities.TRANSPORT_ETHERNET")
                return true
            }
        }
    }
    return false
}

Java:

public static boolean isOnline(Context context) {
    ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);

    if (connectivityManager != null) {
        NetworkCapabilities capabilities = connectivityManager.getNetworkCapabilities(connectivityManager.getActiveNetwork());
        if (capabilities != null) {
            if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
                Log.i("Internet", "NetworkCapabilities.TRANSPORT_CELLULAR");
                return true;
            } else if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
                Log.i("Internet", "NetworkCapabilities.TRANSPORT_WIFI");
                return true;
            } else if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET)) {
                Log.i("Internet", "NetworkCapabilities.TRANSPORT_ETHERNET");
                return true;
            }
        }
    }
    
    return false;
}

both methods require the permissions:

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET"/>
Jorgesys
  • 124,308
  • 23
  • 334
  • 268
  • 2
    Answer UPDATED, thank you! – Jorgesys Oct 13 '21 at 18:33
  • 2
    This only checks if a network is available but not if the connection is working. e.g. if you're connected to your WiFi router but the router is disconnected from the modem, this code will return `true` – Thanh Nguyen Oct 03 '22 at 18:49
31

Check internet connectivity in android kotlin

fun isNetworkAvailable(context: Context?): Boolean {
    if (context == null) return false
    val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
        val capabilities = connectivityManager.getNetworkCapabilities(connectivityManager.activeNetwork)
        if (capabilities != null) {
            when {
                capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> {
                    return true
                }
                capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> {
                    return true
                }
                capabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) -> {
                    return true
                }
            }
        }
    } else {
        val activeNetworkInfo = connectivityManager.activeNetworkInfo
        if (activeNetworkInfo != null && activeNetworkInfo.isConnected) {
            return true
        }
    }
    return false
}
Aftab Alam
  • 1,969
  • 17
  • 17
  • 4
    >= Build.VERSION_CODES.Q isn't Build.VERSION_CODES.M? This is what linter said in AndroidStudio – ejdrian313 Jul 06 '20 at 06:46
  • 1
    @ejdrian313 this means that your current Buildversion (M = Marshmallow, Android 5) is below Q (Android 10), which is required to run the code within the if-statement. – nyx69 Aug 14 '20 at 22:14
16

Call the AsyncTask this way, it should work. You don't need to change anything in your InternetCheck AsyncTask. Basically you need to pass in an object that implements the Consumer interface that's defined in the InternetCheck class.

InternetCheck(object : InternetCheck.Consumer {
    override fun accept(internet: Boolean?) {
        Log.d("test", "asdasdas")
    }
})
Vishnu M.
  • 971
  • 1
  • 10
  • 18
16

Monitoring Internet Connection in Realtime using LiveData - Kotlin

I came across this amazing tutorial on YouTube. We simply need to add a utility file which extends LiveData and can observe it in our Activity or Fragment.

Usage

    private lateinit var connectionLiveData: ConnectionLiveData

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityInternetConnectionTestBinding.inflate(layoutInflater)
        setContentView(binding.root)

        connectionLiveData = ConnectionLiveData(this)
        connectionLiveData.observe(this) { isNetworkAvailable ->
            isNetworkAvailable?.let {
                updateUI(it)
            }
        }
    }

Utility File

const val TAG = "MyTagConnectionManager"

class ConnectionLiveData(context: Context) : LiveData<Boolean>() {

    private lateinit var networkCallback: ConnectivityManager.NetworkCallback
    private val connectivityManager =
        context.getSystemService(CONNECTIVITY_SERVICE) as ConnectivityManager
    private val validNetworks: MutableSet<Network> = HashSet()

    private fun checkValidNetworks() {
        postValue(validNetworks.size > 0)
    }

    override fun onActive() {
        networkCallback = createNetworkCallback()
        val networkRequest = NetworkRequest.Builder()
            .addCapability(NET_CAPABILITY_INTERNET)
            .build()
        connectivityManager.registerNetworkCallback(networkRequest, networkCallback)
    }

    override fun onInactive() {
        connectivityManager.unregisterNetworkCallback(networkCallback)
    }

    private fun createNetworkCallback() = object : ConnectivityManager.NetworkCallback() {

        override fun onAvailable(network: Network) {
            Log.d(TAG, "onAvailable: $network")
            val networkCapabilities = connectivityManager.getNetworkCapabilities(network)
            val hasInternetCapability = networkCapabilities?.hasCapability(NET_CAPABILITY_INTERNET)
            Log.d(TAG, "onAvailable: ${network}, $hasInternetCapability")

            if (hasInternetCapability == true) {
                // Check if this network actually has internet
                CoroutineScope(Dispatchers.IO).launch {
                    val hasInternet = DoesNetworkHaveInternet.execute(network.socketFactory)
                    if (hasInternet) {
                        withContext(Dispatchers.Main) {
                            Log.d(TAG, "onAvailable: adding network. $network")
                            validNetworks.add(network)
                            checkValidNetworks()
                        }
                    }
                }
            }
        }

        override fun onLost(network: Network) {
            Log.d(TAG, "onLost: $network")
            validNetworks.remove(network)
            checkValidNetworks()
        }
    }

    object DoesNetworkHaveInternet {

        fun execute(socketFactory: SocketFactory): Boolean {
            // Make sure to execute this on a background thread.
            return try {
                Log.d(TAG, "PINGING Google...")
                val socket = socketFactory.createSocket() ?: throw IOException("Socket is null.")
                socket.connect(InetSocketAddress("8.8.8.8", 53), 1500)
                socket.close()
                Log.d(TAG, "PING success.")
                true
            } catch (e: IOException) {
                Log.e(TAG, "No Internet Connection. $e")
                false
            }
        }
    }
}

Shahzad Ansari
  • 317
  • 3
  • 10
13
 fun verifyAvailableNetwork(activity:AppCompatActivity):Boolean{
      val connectivityManager=activity.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
      val networkInfo=connectivityManager.activeNetworkInfo
      return  networkInfo!=null && networkInfo.isConnected
}
IramML
  • 306
  • 2
  • 6
10

Add these permission on top in Manifest

   <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
   <uses-permission android:name="android.permission.INTERNET"/>

and this function should do the trick. It will return boolean based on its connectivity

fun isOnline(context: Context): Boolean {
    val cm = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        val n = cm.activeNetwork
        if (n != null) {
            val nc = cm.getNetworkCapabilities(n)
    //It will check for both wifi and cellular network
            return nc!!.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) || nc.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)
        }
        return false
    } else {
        val netInfo = cm.activeNetworkInfo
        return netInfo != null && netInfo.isConnectedOrConnecting
    }
}

It has a deprecated method as well as a latest one based on your api version.

Syed Afeef
  • 140
  • 1
  • 9
7

Shortest version

val Context.isConnected: Boolean
    get() {
        return (getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager)
           .activeNetworkInfo?.isConnected == true
    }
Vlad
  • 7,997
  • 3
  • 56
  • 43
  • 2
    This only checks if we have network, not if we're "online" i.e. connected to the internet. – Lalle Jun 11 '19 at 15:21
6

Try this utility method to check for the availability of internet.

fun isNetworkAvailable(context: Context): Boolean {
        val cm = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
        var activeNetworkInfo: NetworkInfo? = null
        activeNetworkInfo = cm.activeNetworkInfo
        return activeNetworkInfo != null && activeNetworkInfo.isConnectedOrConnecting
    }

Hope this helps.

Naveen T P
  • 6,955
  • 2
  • 22
  • 29
4

I modified your class to this

internal class InternetCheck(private val onInternetChecked: (Boolean) -> Unit) : 
AsyncTask<Void, Void, Boolean>() {
 init {
     execute()
 }

 override fun doInBackground(vararg voids: Void): Boolean {
     return try {
         val sock = Socket()
         sock.connect(InetSocketAddress("8.8.8.8", 53), 1500)
         sock.close()
         true
     } catch (e: IOException) {
         false
     }

 }

 override fun onPostExecute(internet: Boolean) {
     onInternetChecked(internet)
 }
}

So you could use lambda function and you also dont have to deal with null check in there:

InternetCheck{ internet-> Log.d("Connection", "Is connection enabled? "+internet) }
Radim Janda
  • 333
  • 2
  • 10
  • I was required to add StrictMode in the MainActivity ```StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build(); StrictMode.setThreadPolicy(policy);``` Source: https://stackoverflow.com/a/22395546/2215337 – Wesley Abbenhuis Mar 03 '19 at 21:47
3

You can use it like this:

   InternetCheck(object : InternetCheck.Consumer {
      override fun accept(internet: Boolean?) {
         Log.d("test", "asdasdas")
      }
   })

For more infos you can see this thread: https://youtrack.jetbrains.com/issue/KT-7770

Renan Arceno
  • 590
  • 3
  • 12
1

Java

import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
import android.util.Log;

public class ConnectionManager {

public static boolean isConnected(Context context) {
    ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    try {
        if (connectivityManager != null) {
            NetworkCapabilities capabilities;
            if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
                capabilities = connectivityManager.getNetworkCapabilities(connectivityManager.getActiveNetwork());
                if (capabilities != null) {
                    if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
                        Log.i("Internet", "NetworkCapabilities.TRANSPORT_CELLULAR");
                        return true;
                    } else if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
                        Log.i("Internet", "NetworkCapabilities.TRANSPORT_WIFI");
                        return true;
                    } else if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET)) {
                        Log.i("Internet", "NetworkCapabilities.TRANSPORT_ETHERNET");
                        return true;
                    } else if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_VPN)) {
                        Log.i("Internet", "NetworkCapabilities.TRANSPORT_ETHERNET");
                        return true;
                    }
                }
            } else {
                NetworkInfo[] networkInfo = connectivityManager.getAllNetworkInfo();
                if (networkInfo != null) {
                    for (NetworkInfo info : networkInfo) {
                        if (info.getState() == NetworkInfo.State.CONNECTED) {
                            Log.i("Internet", "Internet is Connected.");
                            return true;
                        }
                    }
                }
            }
        }
    } catch (Throwable tr) {
        return false;
    }
    return false;
}

}

Kotlin

import android.content.Context
import android.net.ConnectivityManager
import android.net.NetworkCapabilities
import android.os.Build

val Context.isNetworkConnected: Boolean
get() {
    val manager = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
    return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
        manager.getNetworkCapabilities(manager.activeNetwork)?.let {
            it.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) ||
                    it.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) ||
                    it.hasTransport(NetworkCapabilities.TRANSPORT_BLUETOOTH) ||
                    it.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) ||
                    it.hasTransport(NetworkCapabilities.TRANSPORT_VPN)
        } ?: false
    else
        @Suppress("DEPRECATION")
        manager.activeNetworkInfo?.isConnectedOrConnecting == true
}
Hamid Zandi
  • 2,714
  • 24
  • 32
0

If your objective is to verify internet connectivity rather than checking whether the WIFI or Cellphone's mobile data is switched on/off, you can use the following method to determine if your device is connected to the internet:

Kotlin (API 23 or above)

fun isOnline(context: Context): Boolean {
    val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
    val network = connectivityManager.activeNetwork ?: return false
    val capabilities = connectivityManager.getNetworkCapabilities(network) ?: return false

    return capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)
}

Java (API 23 or above)

public static boolean isOnline(Context context) {
    ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    if (connectivityManager == null) {
        return false;
    }

    Network network = connectivityManager.getActiveNetwork();
    if (network == null) {
        return false;
    }
    NetworkCapabilities capabilities = connectivityManager.getNetworkCapabilities(network);
    return capabilities != null && capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED);
}