Как синхронно получить состояние сети для определенных типов транспорта с Android 22? - PullRequest
2 голосов
/ 16 марта 2020

Я изменил название вопроса, так как Kiskae предоставил решение более широкой проблемы, которое делает вопрос об упаковке API обратного вызова ненужным для конкретной проблемы. Предыдущий заголовок вопроса был:

Как обернуть асинхронный обратный вызов в функцию приостановки с помощью сопрограмм?


Я пытаюсь обернуть ConnectivityManager.NetworkCallback API (> = уровень SDK 21) платформы Android в функцию приостановки для упрощения синхронного API:

private suspend fun ConnectivityManager.isNetworkAvailable(
    vararg transportType: /* android.net.NetworkCapabilities.Transport */ Int)
: Boolean {
    val isAvailable = suspendCancellableCoroutine<Boolean> { continuation ->
        val builder = NetworkRequest.Builder()
        transportType.forEach {
            builder.addCapability(it)
        }
        val networkRequest = builder.build()
        val networkCallback = object : ConnectivityManager.NetworkCallback() {
            override fun onAvailable(network: Network) {
                super.onAvailable(network)
                Log.d(javaClass.simpleName, "[${Thread.currentThread().name}] onAvailable")
                continuation.resume(true)
                unregisterNetworkCallback(this)
            }

            override fun onLost(network: Network) {
                super.onLost(network)
                Log.d(javaClass.simpleName, "[${Thread.currentThread().name}] onLost")
                continuation.resume(false)
                unregisterNetworkCallback(this)
            }
        }
        Log.d(javaClass.simpleName, "[${Thread.currentThread().name}] registerNetworkCallback BEFORE")
        registerNetworkCallback(networkRequest, networkCallback)
        Log.d(javaClass.simpleName, "[${Thread.currentThread().name}] registerNetworkCallback AFTER")
    }
    Log.d(javaClass.simpleName, "[${Thread.currentThread().name}] return isAvailable BEFORE")
    return isAvailable
}

Когда я вызываю isNetworkAvailable(NetworkCapabilities.TRANSPORT_WIFI), то следующее вывод:

[DefaultDispatcher-worker-1] registerNetworkCallback ПЕРЕД
[DefaultDispatcher-worker-1] registerNetworkCallback ПОСЛЕ

* onAvailable и onLost являются хотя никогда не звонил.

Ссылки

Связано

1 Ответ

3 голосов
/ 16 марта 2020

Получается, что соответствующий API для того, что вы хотите сделать, не является асинхронным c, поэтому сопрограммы не требуются:

private fun ConnectivityManager.isNetworkAvailable(
    vararg transportType: /* android.net.NetworkCapabilities.Transport */ Int)
: Boolean {
    val network = getActiveNetwork()
    val caps = getNetworkCapabilities(network)
    return caps != null && transportType.all(caps::hasTransport)
}

Для этого требуется только Manifest.permission.ACCESS_NETWORK_STATE.

Если вы хотите активно искать сеть с необходимыми возможностями, вам нужно будет использовать requestNetwork API. (и разрешение Manifest.permission.CHANGE_NETWORK_STATE)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...