Проверьте подключение к Интернету на API29

Я использую следующий метод для проверки подключения к Интернету:

public boolean isInternetConnected() {
    ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo networkInfo = cm.getActiveNetworkInfo();
    return networkInfo != null && networkInfo.isConnected();
}

Однако я обнаружил, что NetworkInfo, getActiveNetworkInfo() и isConnected() теперь устарели. Я проверил несколько потоков на SO:

ConnectivityManager getNetworkInfo(int) устарел

activeNetworkInfo.type устарел на уровне API 28.

Тем не менее, все они предлагают ответы с устаревшими методами. Я безуспешно осматривался. Есть ли простой способ проверить подключение к Интернету или мне следует продолжать использовать мой метод и игнорировать устаревшие, поскольку он работает до API29?

Спасибо.

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
2
0
1 502
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Ответ принят как подходящий

Взгляните на .hasTransport

val networkAvailability = cm.getNetworkCapabilities(cm.activeNetwork)
if (networkAvailability !=null && networkAvailability.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) && networkAvailability.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED))
{
    //has network
    if (networkAvailability.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) { //wifi
    } else if (networkAvailability.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) { //cellular
    }
}

Большое спасибо за это отличное решение. Я очень ценю это.

user10476174 22.06.2019 09:12

есть больше способов быть на связи в реальном мире

Francis 19.02.2020 11:40

Вот мое решение для SDK 29: класс под названием NetworkWatcher, который наблюдает за изменениями в сети. Он предлагает примитивные переменные, такие как isWifiOn, и возможность наблюдать за изменениями сети с течением времени через Поток и 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) }
    }
}

Например, вы можете подписаться на обновления о состоянии сети телефона в своем приложении, например:

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

Или, чтобы ответить на ваш вопрос, просто прочитайте значение Wifi, например:

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

Примечание: вместо того, чтобы постоянно использовать getInstance(), я использую структуру DI, такую ​​как Коин, для внедрения NetworkWatcher там, где мне это нужно.

в AndroidManifest.xml добавить:

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

теперь для проверки состояния сети:

 @IntRange(from = 0, to = 3)
fun getConnectionType(context: Context): Int {
    var result = 0 // Returns connection type. 0: none; 1: mobile data; 2: wifi
    val cm = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {

        val capabilities =
            cm.getNetworkCapabilities(cm.activeNetwork)
        if (capabilities != null) {
            if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
                result = 2
            } else if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
                result = 1
            } else if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_VPN)) {
                result = 3
            }

        }
    } else {

        val activeNetwork = cm.activeNetworkInfo
        if (activeNetwork != null) {
            // connected to the internet
            if (activeNetwork.type === ConnectivityManager.TYPE_WIFI) {
                result = 2
            } else if (activeNetwork.type === ConnectivityManager.TYPE_MOBILE) {
                result = 1
            } else if (activeNetwork.type === ConnectivityManager.TYPE_VPN) {
                result = 3
            }
        }
    }
    return result
}

Мой ответ, который чист и написан на Котлине, а также обрабатывает разные уровни API.

fun isOnline(): Boolean {
        val connectivityManager =
            ContextCompat.getSystemService(DreamPad.appContext, ConnectivityManager::class.java)
        connectivityManager ?: return false
        return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            val nw = connectivityManager.activeNetwork ?: return false
            val actNw = connectivityManager.getNetworkCapabilities(nw) ?: return false
            when {
                actNw.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> true
                actNw.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> true
                //for other device how are able to connect with Ethernet
                actNw.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) -> true
                //for check internet over Bluetooth
                actNw.hasTransport(NetworkCapabilities.TRANSPORT_BLUETOOTH) -> true
                else -> false
            }
        } else {
            @Suppress("DEPRECATION")
            connectivityManager.activeNetworkInfo?.isConnected ?: false
        }
    }

Другие вопросы по теме