activeNetworkInfo.type is deprecated in API level 28
Asked Answered
G

18

94

enter image description hereI want to use the Connectivity manager which provide the method activeNetworkInfo.type for checking the type of network in Android. This method was deprecated in API level 28. so what is the solution to check network type in API 28. my code is :

/**
 * Check Wi Fi connectivity
 */
fun isWiFiConnected(context: Context): Boolean {
    val connManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
    return connManager.activeNetworkInfo.type == ConnectivityManager.TYPE_WIFI
}

My Gradle is like :

compileSdkVersion 28
buildToolsVersion '28.0.3'
defaultConfig {
        minSdkVersion 21
        targetSdkVersion 28
    }
Guardrail answered 29/11, 2018 at 5:27 Comment(0)
S
181

UPDATE

The connectivityManager.activeNetworkInfo is also deprecated in API level 29

Now we need to use ConnectivityManager.NetworkCallback API or ConnectivityManager#getNetworkCapabilities or ConnectivityManager#getLinkProperties

SAMPLE CODE USING ConnectivityManager#getNetworkCapabilities

private fun isInternetAvailable(context: Context): Boolean {
        var result = false
        val connectivityManager =
            context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            val networkCapabilities = connectivityManager.activeNetwork ?: return false
            val actNw =
                connectivityManager.getNetworkCapabilities(networkCapabilities) ?: return false
            result = when {
                actNw.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> true
                actNw.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> true
                actNw.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) -> true
                else -> false
            }
        } else {
            connectivityManager.run {
                connectivityManager.activeNetworkInfo?.run {
                    result = when (type) {
                        ConnectivityManager.TYPE_WIFI -> true
                        ConnectivityManager.TYPE_MOBILE -> true
                        ConnectivityManager.TYPE_ETHERNET -> true
                        else -> false
                    }

                }
            }
        }

        return result
    }

OLD ANSWER

Yes getType() is deprecated in API level 28

Now we need to use Callers should switch to checking NetworkCapabilities.hasTransport(int)

Also getAllNetworkInfo() is deprecated in API level 29

Now we need to use getAllNetworks() instead of getNetworkInfo(android.net.Network) .

getNetworkInfo()

  • Returns connection status information about a particular Network.

getAllNetworks()

  • Returns an array of all Network currently tracked by the framework.

SAMPLE CODE

fun isWiFiConnected(context: Context): Boolean {
    val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
    return if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
        val network = connectivityManager.activeNetwork
        val capabilities = connectivityManager.getNetworkCapabilities(network)
        capabilities != null && capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)
    } else {
        connectivityManager.activeNetworkInfo.type == ConnectivityManager.TYPE_WIFI
    }
}

COMPLETE CODE

@Suppress("DEPRECATION")
fun isInternetAvailable(context: Context): Boolean {
    var result = false
    val cm = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager?
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        cm?.run {
            cm.getNetworkCapabilities(cm.activeNetwork)?.run {
                result = when {
                    hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> true
                    hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> true
                    hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) -> true
                    else -> false
                }
            }
        }
    } else {
        cm?.run {
            cm.activeNetworkInfo?.run {
                if (type == ConnectivityManager.TYPE_WIFI) {
                    result = true
                } else if (type == ConnectivityManager.TYPE_MOBILE) {
                    result = true
                }
            }
        }
    }
    return result
}
Sillimanite answered 29/11, 2018 at 5:32 Comment(13)
@kkarakk Are you sure about that? No signs of deprecation in the docsDissected
How do I check now if the device has Internet connection? So far it was just connectivityManager.activeNetworkInfo?.isConnected == true . What should we do now? Just connectivityManager.activeNetwork != null ?Coriss
The code doesn't work. I don't have a SIM Card, but I'm connected via Wifi with Internet. isInternetAvailable() and hasTransport(NetworkCapabilities.TRANSPORT_WIFI) return false.Nightrider
@ranasaha sorry for late reply, now we need to use ConnectivityManager#getNetworkCapabilities please check updated answer i have added sample code using ConnectivityManager#getNetworkCapabilitiesSillimanite
@NileshRathod after you instantiate you actNw variable, and before you check for network capabilities , you should add null check. getNetworkCapabilities is nullable.Undamped
@Milepost yes you need to use NetworkCapabilities.TRANSPORT_BLUETOOTH and NetworkCapabilities.TRANSPORT_ETHERNET for more information please check NetworkCapabilitiesSillimanite
@NileshRathod So is there a general solution? What about hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)?Milepost
But we still need to use activeNetworkInfo for old versions. Is there any support lib for this?Chapa
May I know why checking for M (M is API 23)Guesthouse
@CheokYanCheng May I know why checking for M because connectivityManager.activeNetwork is added in API level 23Sillimanite
Because most methods in NetworkInfo only deprecate since 28. We can still use the good old NetworkInfo before 28Guesthouse
Current new methods is error prone. networkInfo.isConnectedOrConnecting is way better and realiable. Who ever know whether we need to check TRANSPORT_VPN as well?Guesthouse
networkCapabilities and actNw names should be interchanged, as is it's wrong.Coniology
C
15

Slightly simpler version (minSdkVersion 23+)

fun isNetworkAvailable(context: Context) =
    (context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager).run {
        getNetworkCapabilities(activeNetwork)?.run {
            hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)
                || hasTransport(NetworkCapabilities.TRANSPORT_WIFI)
                || hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET)
        } ?: false
    }
Chibchan answered 11/4, 2020 at 5:7 Comment(0)
N
12

Here is my solution for SDK 29: A class called NetworkWatcher which observes the changes of the network. It offers primitive variables such as isWifiOn and the option to observe network changes over time via Flow and LiveData.

@ExperimentalCoroutinesApi
class NetworkWatcher
@RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
private constructor(
    application: Application
) {

    private val connectivityManager =
        application.applicationContext.getSystemService(Context.CONNECTIVITY_SERVICE)
                as ConnectivityManager

    // general availability of Internet over any type
    var isOnline = false
        get() {
            updateFields()
            return field
        }

    var isOverWifi = false
        get() {
            updateFields()
            return field
        }

    var isOverCellular = false
        get() {
            updateFields()
            return field
        }

    var isOverEthernet = false
        get() {
            updateFields()
            return field
        }

    companion object {
        @Volatile
        private var INSTANCE: NetworkWatcher? = null

        fun getInstance(application: Application): NetworkWatcher {
            synchronized(this) {
                if (INSTANCE == null) {
                    INSTANCE = NetworkWatcher(application)
                }
                return INSTANCE!!
            }
        }
    }

    @Suppress("DEPRECATION")
    private fun updateFields() {

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {

            val networkAvailability =
                connectivityManager.getNetworkCapabilities(connectivityManager.activeNetwork)

            if (networkAvailability != null &&
                networkAvailability.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) &&
                networkAvailability.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)
            ) {
                //has network
                isOnline = true

                // wifi
                isOverWifi =
                    networkAvailability.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)

                // cellular
                isOverCellular =
                    networkAvailability.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)

                // ethernet
                isOverEthernet =
                    networkAvailability.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET)
            } else {
                isOnline = false
                isOverWifi = false
                isOverCellular = false
                isOverEthernet = false
            }
        } else {

            val info = connectivityManager.activeNetworkInfo
            if (info != null && info.isConnected) {
                isOnline = true

                val wifi = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI)
                isOverWifi = wifi != null && wifi.isConnected

                val cellular = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE)
                isOverCellular = cellular != null && cellular.isConnected

                val ethernet = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_ETHERNET)
                isOverEthernet = ethernet != null && ethernet.isConnected

            } else {
                isOnline = false
                isOverWifi = false
                isOverCellular = false
                isOverEthernet = false
            }
        }
    }

    fun watchNetwork(): Flow<Boolean> = watchWifi()
        .combine(watchCellular()) { wifi, cellular -> wifi || cellular }
        .combine(watchEthernet()) { wifiAndCellular, ethernet -> wifiAndCellular || ethernet }

    fun watchNetworkAsLiveData(): LiveData<Boolean> = watchNetwork().asLiveData()

    fun watchWifi(): Flow<Boolean> = callbackFlowForType(NetworkCapabilities.TRANSPORT_WIFI)

    fun watchWifiAsLiveData() = watchWifi().asLiveData()

    fun watchCellular(): Flow<Boolean> = callbackFlowForType(NetworkCapabilities.TRANSPORT_CELLULAR)

    fun watchCellularAsLiveData() = watchCellular().asLiveData()

    fun watchEthernet(): Flow<Boolean> = callbackFlowForType(NetworkCapabilities.TRANSPORT_ETHERNET)

    fun watchEthernetAsLiveData() = watchEthernet().asLiveData()

    private fun callbackFlowForType(@IntRange(from = 0, to = 7) type: Int) = callbackFlow {

        offer(false)

        val networkRequest = NetworkRequest.Builder()
            .addTransportType(type)
            .build()

        val callback = object : ConnectivityManager.NetworkCallback() {
            override fun onLost(network: Network?) {
                offer(false)
            }

            override fun onUnavailable() {
                offer(false)
            }

            override fun onLosing(network: Network?, maxMsToLive: Int) {
                // do nothing
            }

            override fun onAvailable(network: Network?) {
                offer(true)
            }
        }

        connectivityManager.registerNetworkCallback(networkRequest, callback)

        awaitClose { connectivityManager.unregisterNetworkCallback(callback) }
    }
}

For instance, you could subscribe to updates about the network state of the phone in your Application such as:

GlobalScope.launch {
    NetworkWatcher.getInstance(this@MyApplication).watchNetwork().collect { connected ->
        Log.d("TAG", "Network In App: $connected")
    }
}

Or to answer your question, simply read the Wifi value such as:

if (NetworkWatcher.getInstance(this@BaseApp).isOverWifi) {
    // do stuff
}

Side note: Rather than using getInstance() all the time, I use a DI framework such as Koin to inject the NetworkWatcher where I need it.

Nightrider answered 20/11, 2019 at 18:13 Comment(0)
B
9

I just wanted to know, if the device is connected to the internet, regardless of the type of connection:

@Suppress("DEPRECATION")
fun isOnline(context: Context?): Boolean {
    var connected = false
    @Suppress("LiftReturnOrAssignment")
    context?.let {
        val cm = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            val networkCapabilities = cm.activeNetwork ?: return false
            val actNw = cm.getNetworkCapabilities(networkCapabilities) ?: return false
            connected = actNw.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
        } else {
            val netInfo = cm.activeNetworkInfo
            connected = netInfo?.isConnectedOrConnecting == true
        }
    }
    return connected
}
Bingle answered 8/1, 2020 at 10:23 Comment(0)
V
6

Here is Kotlin implementation for two methods old/new api:

@Suppress("DEPRECATION")
fun isConnectedOld(context: Context): Boolean {
    val connManager = context.getSystemService(CONNECTIVITY_SERVICE) as ConnectivityManager
    val networkInfo = connManager.activeNetworkInfo
    return networkInfo.isConnected

}


@RequiresApi(Build.VERSION_CODES.M)
fun isConnectedNewApi(context: Context): Boolean {
    val cm = context.getSystemService(CONNECTIVITY_SERVICE) as ConnectivityManager
    val capabilities = cm.getNetworkCapabilities(cm.activeNetwork)
    return capabilities?.hasCapability(NET_CAPABILITY_INTERNET) == true
}

and common method:

fun isConnected(context: Context): Boolean {
    return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        isConnectedNewApi(context)
    } else{
        isConnectedOld(context)
    }
}
Vagarious answered 2/12, 2020 at 10:29 Comment(1)
The best answer here reallyPenile
P
5

Java Code:

public static boolean isConnectingToInternet(Context mContext) {
    if (mContext == null) return false;

    ConnectivityManager connectivityManager = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
    if (connectivityManager != null) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            final Network network = connectivityManager.getActiveNetwork();
            if (network != null) {
                final NetworkCapabilities nc = connectivityManager.getNetworkCapabilities(network);

                return (nc.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) ||
                        nc.hasTransport(NetworkCapabilities.TRANSPORT_WIFI));
            }
        } else {
            NetworkInfo[] networkInfos = connectivityManager.getAllNetworkInfo();
            for (NetworkInfo tempNetworkInfo : networkInfos) {
                if (tempNetworkInfo.isConnected()) {
                    return true;
                }
            }
        }
    }
    return false;
}
Pessimist answered 16/12, 2019 at 16:7 Comment(0)
A
4

No, as seen from here: https://developer.android.com/reference/android/net/ConnectivityManager.html#getActiveNetworkInfo()

getActiveNetworkInfo() is still available in Android API 28, and nowhere says it is deprecated.

But the one deprecated is getType() of NetworkInfo class.

https://developer.android.com/reference/android/net/NetworkInfo#getType()

This method was deprecated in API level 28.

Callers should switch to checking NetworkCapabilities.hasTransport(int) instead with one of the NetworkCapabilities#TRANSPORT_* constants : getType() and getTypeName() cannot account for networks using multiple transports. Note that generally apps should not care about transport; NetworkCapabilities.NET_CAPABILITY_NOT_METERED and NetworkCapabilities.getLinkDownstreamBandwidthKbps() are calls that apps concerned with meteredness or bandwidth should be looking at, as they offer this information with much better accuracy.

An answered 29/11, 2018 at 5:39 Comment(3)
the replacement method for deprecated API is inside the official API document, which I have enclosed above.An
getActiveNetworkInfo() is deprecated in API 29. I think you should update your answerDissected
I don't understand what to use in case all I want to know is whether there is an Internet connection or not. So far I just use this: connectivityManager.activeNetworkInfo?.isConnected == true . Should we use now : connectivityManager.activeNetwork != null ?Coriss
F
4

I am using this Kotlin func to check internet connection:

Be careful about version checking (Version >= M)

private fun isInternetConnected():Boolean{

    val connectivityManager = this.getSystemService(android.content.Context.CONNECTIVITY_SERVICE)
            as ConnectivityManager

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        val networkCapabilities = connectivityManager.activeNetwork ?: return false
        val activeNetwork = connectivityManager.getNetworkCapabilities(networkCapabilities) ?: return false

        return when {

            activeNetwork.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) ||
                    activeNetwork.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) ||
                    activeNetwork.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> true
            else -> false
        }
    }
    else {
        return connectivityManager.activeNetworkInfo != null &&
                connectivityManager.activeNetworkInfo!!.isConnectedOrConnecting
    }
}
Foreland answered 18/2, 2020 at 14:59 Comment(0)
B
3

I have adapted Nilesh Rathod's answer for my needs:

enum class ConnectivityMode {
    NONE,
    WIFI,
    MOBILE,
    OTHER,
    MAYBE
}

var connectivityMode = ConnectivityMode.NONE

private fun checkConnectivity(context: Context): ConnectivityMode {

    val cm = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager

    cm?.run {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            getNetworkCapabilities(activeNetwork)?.run {
                return when {
                    hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> ConnectivityMode.WIFI
                    hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> ConnectivityMode.MOBILE
                    hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) -> ConnectivityMode.OTHER
                    hasTransport(NetworkCapabilities.TRANSPORT_BLUETOOTH) -> ConnectivityMode.MAYBE
                    else -> ConnectivityMode.NONE
                }
            }
        } else {
            @Suppress("DEPRECATION")
            activeNetworkInfo?.run {
                return when (type) {
                    ConnectivityManager.TYPE_WIFI -> ConnectivityMode.WIFI
                    ConnectivityManager.TYPE_MOBILE -> ConnectivityMode.MOBILE
                    ConnectivityManager.TYPE_ETHERNET -> ConnectivityMode.OTHER
                    ConnectivityManager.TYPE_BLUETOOTH -> ConnectivityMode.MAYBE
                    else -> ConnectivityMode.NONE
                }
            }
        }
    }
    return ConnectivityMode.NONE
}

Then I check the connection with okhttp:

fun updateData(manual: Boolean, windowContext: Context) = runBlocking {
    connectivityMode = checkConnectivity(MyApplication.context)
    if (connectivityMode != ConnectivityMode.NONE) {
        val conn : Boolean = GlobalScope.async {
            var retval = false
            try {
                val request = Request.Builder().url(WORK_URL).build()
                val response =  client.newCall(request).execute()
                Log.i(TAG, "code = ${response?.code}")
                if (response?.code == 200) {
                    // I use the response body since it is a small file and already downloaded
                    val input = response.body?.byteStream()
                    if (input != null) {
                        // do stuff
                        response.body?.close()
                        retval = true
                    }
                }
            }
            catch(exception: Exception) {
                Log.e(TAG, "error ${exception.message ?: ""}")
            }
            retval
        }.await()
        if (!conn) {
            connectivityMode = ConnectivityMode.NONE
        }
    }
    ....
Bromeosin answered 20/8, 2019 at 14:24 Comment(0)
S
2

I hope this would work for you! this code work in api 21 onwards

// create a new class and add following

public class CheckNetwork {

public static boolean isNetworkConnected;
private Context context;

public CheckNetwork(Context context) {
    this.context = context;
}

public boolean isOnline(){
    isNetworkConnected = false;
    ConnectivityManager connectivityMgr = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    Network[] allNetworks = connectivityMgr.getAllNetworks(); // added in API 21 (Lollipop)

    for (Network network : allNetworks) {
        NetworkCapabilities networkCapabilities = connectivityMgr.getNetworkCapabilities(network);
        if (networkCapabilities != null) {
            if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)
                    || networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)
                    || networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET))
                isNetworkConnected = true;
            }
        }
    return isNetworkConnected;
    }

}

// in MainActivity

CheckNetwork myNetwork = new CheckNetwork(this);

//in OnCreateMethod

myNetwork.isOnline();
    if (myNetwork.isNetworkConnected){
        Toast.makeText(this, "Please check your Internet Connection", Toast.LENGTH_SHORT).show();
    }else {
        Toast.makeText(this, "Your Internet Connction is Ok", Toast.LENGTH_SHORT).show();
    }
Spermatogonium answered 26/7, 2020 at 2:59 Comment(1)
The only thing that worked for me since I'm working on target API 30 and because the NetworkInfo method is deprecated in API 28.Jay
A
1

In Kotlin you can check the Android version and as per the version check the connectivity manager.

fun Context.isInternetAvailable(): Boolean {
    val cm = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
    when {
        Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q -> {
            val cap = cm.getNetworkCapabilities(cm.activeNetwork) ?: return false
            return cap.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
        }
        Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP -> {
            val networks = cm.allNetworks
            for (n in networks) {
                val nInfo = cm.getNetworkInfo(n)
                if (nInfo != null && nInfo.isConnected) return true
            }
        }
        else -> {
            val networks = cm.allNetworkInfo
            for (nInfo in networks) {
                if (nInfo != null && nInfo.isConnected) return true
            }
        }
    }
    return false
}

Call the extension function in your activity

if (applicationContext.isInternetAvailable()) { }
Arista answered 23/8, 2021 at 15:59 Comment(0)
S
0

If you use min API level 23, you can use this shortened Kotlin version.

fun isNetworkAvailable(context: Context): Boolean {
    (context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager).apply {
        return getNetworkCapabilities(activeNetwork)?.run {
            when {
                hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> true
                hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> true
                hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) -> true
                else -> false
            }
        } ?: false
    }
}
Slobber answered 3/10, 2019 at 9:44 Comment(0)
D
0

Recently I had to write a small function for checking the network connectivity inside my singular WebView. I've also noticed that the API much evolved and especially when Kotlin came in so to find valid reference took some minutes.

Here is my small NetworkConnectivityManager class with a simple function for checking network availability.

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

class NetworkConnectivityManager(context: Context) {
    private val connectivityManager =
        context.getSystemService(CONNECTIVITY_SERVICE) as ConnectivityManager

    @Suppress("DEPRECATION")
    fun isNetworkAvailable(): Boolean {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            val nc = connectivityManager.getNetworkCapabilities(connectivityManager.activeNetwork)

            nc != null 
                    && nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
                    && nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)
        }

        val networkInfo = connectivityManager.activeNetworkInfo
        return networkInfo != null && networkInfo.isConnected
    }
}
Diacaustic answered 12/11, 2019 at 11:8 Comment(0)
P
0

Complete solution Create these class in a package lets say connectivity

  1. interface ConnectivityProvider

import android.content.Context import android.content.Context.CONNECTIVITY_SERVICE import android.net.ConnectivityManager

import android.net.NetworkCapabilities
import android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET

import android.net.NetworkInfo
import android.os.Build

import androidx.annotation.RequiresApi

interface ConnectivityProvider {
    interface ConnectivityStateListener {
        fun onStateChange(state: NetworkState)
    }

fun addListener(listener: ConnectivityStateListener)
fun removeListener(listener: ConnectivityStateListener)

fun getNetworkState(): NetworkState

@Suppress("MemberVisibilityCanBePrivate", "CanBeParameter")
sealed class NetworkState {
    object NotConnectedState : NetworkState()

    sealed class ConnectedState(val hasInternet: Boolean) : NetworkState() {

        @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
        data class Connected(val capabilities: NetworkCapabilities) : ConnectedState(
            capabilities.hasCapability(NET_CAPABILITY_INTERNET)
        )

        @Suppress("DEPRECATION")
        data class ConnectedLegacy(val networkInfo: NetworkInfo) : ConnectedState(
            networkInfo.isConnectedOrConnecting
        )
    }
}

companion object {
    fun createProvider(context: Context): ConnectivityProvider {
        val cm = context.getSystemService(CONNECTIVITY_SERVICE) as ConnectivityManager
        return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            ConnectivityProviderImpl(cm)
        } else {
            ConnectivityProviderLegacyImpl(context, cm)
        }
    }
}

}

  1. abstract class ConnectivityProviderBaseImpl

     abstract class ConnectivityProviderBaseImpl : ConnectivityProvider {
     private val handler = Handler(Looper.getMainLooper())
     private val listeners = mutableSetOf<ConnectivityStateListener>()
     private var subscribed = false
    
     override fun addListener(listener: ConnectivityStateListener) {
         listeners.add(listener)
         listener.onStateChange(getNetworkState()) // propagate an initial state
         verifySubscription()
     }
    
     override fun removeListener(listener: ConnectivityStateListener) {
         listeners.remove(listener)
         verifySubscription()
     }
    
     private fun verifySubscription() {
         if (!subscribed && listeners.isNotEmpty()) {
             subscribe()
             subscribed = true
         } else if (subscribed && listeners.isEmpty()) {
             unsubscribe()
             subscribed = false
         }
     }
    
     protected fun dispatchChange(state: NetworkState) {
         handler.post {
             for (listener in listeners) {
                 listener.onStateChange(state)
             }
         }
     }
    
     protected abstract fun subscribe()
     protected abstract fun unsubscribe()
    

    }

  2. class ConnectivityProviderImpl

@RequiresApi(Build.VERSION_CODES.N)

class ConnectivityProviderImpl(private val cm: ConnectivityManager) :
    ConnectivityProviderBaseImpl() {

    private val networkCallback = ConnectivityCallback()

    override fun subscribe() {
        cm.registerDefaultNetworkCallback(networkCallback)
    }

    override fun unsubscribe() {
        cm.unregisterNetworkCallback(networkCallback)
    }

    override fun getNetworkState(): NetworkState {
        val capabilities = cm.getNetworkCapabilities(cm.activeNetwork)
        return if (capabilities != null) {
            Connected(capabilities)
        } else {
            NotConnectedState
        }
    }

    private inner class ConnectivityCallback : NetworkCallback() {

        override fun onCapabilitiesChanged(network: Network, capabilities: NetworkCapabilities) {
            dispatchChange(Connected(capabilities))
        }

        override fun onLost(network: Network) {
            dispatchChange(NotConnectedState)
        }
    }
}
  1. class ConnectivityProviderLegacyImpl

@Suppress("DEPRECATION")

class ConnectivityProviderLegacyImpl(
private val context: Context,
 private val cm: ConnectivityManager
) : ConnectivityProviderBaseImpl() {

    private val receiver = ConnectivityReceiver()

    override fun subscribe() {
        context.registerReceiver(receiver, IntentFilter(CONNECTIVITY_ACTION))
    }

    override fun unsubscribe() {
        context.unregisterReceiver(receiver)
    }

    override fun getNetworkState(): NetworkState {
        val activeNetworkInfo = cm.activeNetworkInfo
        return if (activeNetworkInfo != null) {
            ConnectedLegacy(activeNetworkInfo)
        } else {
            NotConnectedState
        }
    }

    private inner class ConnectivityReceiver : BroadcastReceiver() {
        override fun onReceive(c: Context, intent: Intent) {
            // on some devices ConnectivityManager.getActiveNetworkInfo() does not provide the correct network state
            // https://issuetracker.google.com/issues/37137911
            val networkInfo = cm.activeNetworkInfo
            val fallbackNetworkInfo: NetworkInfo? = intent.getParcelableExtra(EXTRA_NETWORK_INFO)
            // a set of dirty workarounds
            val state: NetworkState =
                if (networkInfo?.isConnectedOrConnecting == true) {
                    ConnectedLegacy(networkInfo)
                } else if (networkInfo != null && fallbackNetworkInfo != null &&
                    networkInfo.isConnectedOrConnecting != fallbackNetworkInfo.isConnectedOrConnecting
                ) {
                    ConnectedLegacy(fallbackNetworkInfo)
                } else {
                    val state = networkInfo ?: fallbackNetworkInfo
                    if (state != null) ConnectedLegacy(state) else NotConnectedState
                }
            dispatchChange(state)
        }
    }
}

Usage:- Home Activity

class HomeActivity : BaseActivity(), ConnectivityProvider.ConnectivityStateListener {
    val provider: ConnectivityProvider by lazy { ConnectivityProvider.createProvider(this@HomeActivity) }
 override fun onStart() {
        super.onStart()
        provider.addListener(this)
    }

override fun onStop() {
    super.onStop()
    provider.removeListener(this)
}

override fun onStateChange(state: ConnectivityProvider.NetworkState) {
    val hasInternet = state.hasInternet()
}

companion object {
    fun ConnectivityProvider.NetworkState.hasInternet(): Boolean {
        return (this as? ConnectivityProvider.NetworkState.ConnectedState)?.hasInternet == true
    }
}

on button click or any api call

 if(provider.getNetworkState().hasInternet()){
                // do work    
                }
}

if you want to use check internet in fragments of home activities

if ((activity as HomeActivity).provider.getNetworkState().hasInternet()) {
            // api call
        }
Photocompose answered 11/12, 2020 at 12:21 Comment(0)
E
0

For versions >= Build.VERSION_CODES.M:

private fun isConnected(context: Context): Boolean {
    val manager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as? ConnectivityManager
    val capabilities = manager?.getNetworkCapabilities(manager.activeNetwork) ?: return false

    return capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)
            || capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)
            || capabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET)
}
Eteocles answered 30/3, 2021 at 5:47 Comment(0)
K
0

this is what I do. In the first part of "if statement" I check whether the user is making use of the new verison of android, in second part I make use of AciveNetworkInfo for old Android SDK.

fun isNetworkAvailable(context: Context): Boolean {  

 val connectivityManager =
context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager

    //return depending on the version in the last version of API
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {

      val network = connectivityManager.activeNetwork ?: return false
               
val activeNetwork = 
                connectivityManager.getNetworkCapabilities(network) ?: return false
            return when {
                    activeNetwork.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> true
                    activeNetwork.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> true
                    activeNetwork.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) ->true

            else -> false
        }

    } else {
        //for the old version of android sdk we use follow code
        val networkInfo = connectivityManager.activeNetworkInfo
        return networkInfo != null && networkInfo.isConnectedOrConnecting
    }

}
Ked answered 9/4, 2022 at 14:36 Comment(0)
E
0

Due to Android Developers >Docs >Guides this way can be useful

Java

        boolean enabled;
        ConnectivityManager connectivityManager = (ConnectivityManager) this.getSystemService(Context.CONNECTIVITY_SERVICE);
        assert connectivityManager != null;
        NetworkInfo info = connectivityManager.getActiveNetworkInfo();

        ConnectivityManager cm = getSystemService(ConnectivityManager.class);

        if ((info == null ||  !cm.getActiveNetworkInfo().isConnectedOrConnecting() || !info.isAvailable())) {
           
            enabled = false;
        } else enabled = true;

for this getActiveNetworkInfo() you need permission ACCESS_NETWORK_STATE

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
Engud answered 26/4, 2023 at 15:38 Comment(0)
T
0

In kotlin i use this:

private fun isConnected(): Boolean {

val connectivityManager = applicationContext.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager

val network = connectivityManager.activeNetwork

val capabilities = connectivityManager.getNetworkCapabilities(network)

return (capabilities != null &&
    capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) &&
    capabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) &&
    capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) &&
    capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET))
}
Take answered 31/3 at 6:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.