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

enter image description here Я хочу использовать диспетчер подключений, который предоставляет метод activeNetworkInfo.type для проверки типа сети в Android. Этот метод устарел на уровне API 28. Итак, что такое решение для проверки типа сети в API 28. мой код:

/**
 * 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
}

Мой Gradle это как:

compileSdkVersion 28
buildToolsVersion '28.0.3'
defaultConfig {
        minSdkVersion 21
        targetSdkVersion 28
    }

Ответы

Ответ 1

Да getType() устарело в уровне API 28

Теперь нам нужно использовать Use Callers, чтобы переключиться на проверку NetworkCapabilities.hasTransport(int)

Также getAllNetworkInfo() устарело на уровне API 29

Теперь нам нужно использовать getAllNetworks() вместо getNetworkInfo(android.net.Network).

getNetworkInfo()

  • Возвращает информацию о состоянии соединения для определенной сети.

getAllNetworks()

  • Возвращает массив всей сети, отслеживаемой в настоящее время платформой.

ОБРАЗЕЦ КОДА

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
    }
}

ПОЛНЫЙ КОД

@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
}

Ответ 2

Нет, как видно здесь: https://developer.android.com/reference/android/net/ConnectivityManager.html#getActiveNetworkInfo()

getActiveNetworkInfo() по-прежнему доступна в Android API 28, и нигде не говорится, что она устарела.

Но не рекомендуется использовать getType() класса NetworkInfo.

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

Этот метод устарел на уровне API 28.

Вызывающие абоненты должны переключиться на проверку NetworkCapabilities.hasTransport(int) вместо этого с одной из NetworkCapabilities#TRANSPORT_* constants: getType() и getTypeName() не могут учитывать сети, использующие несколько транспортов. Обратите внимание, что обычно приложения не должны заботиться о транспорте; NetworkCapabilities.NET_CAPABILITY_NOT_METERED и NetworkCapabilities.getLinkDownstreamBandwidthKbps() - это вызовы, на которые должны смотреть приложения, связанные с измерением или пропускной способностью, поскольку они предоставляют эту информацию с гораздо большей точностью.

Ответ 3

Я адаптировал ответ Nilesh Rathod для своих нужд:

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
}

Затем я проверяю соединение с 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
        }
    }
    ....

Ответ 4

Если вы используете минимальный уровень API 23, вы можете использовать эту сокращенную версию Kotlin.

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
    }
}