#android #android-connectivitymanager
#Android #android-connectivitymanager
Вопрос:
Мы используем Android ConnectivityManager
для прослушивания изменений подключения к Интернету внутри нашего приложения следующим образом.
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
...
ConnectionStateMonitor().enable(this)
}
class ConnectionStateMonitor : NetworkCallback() {
private val networkRequest: NetworkRequest = NetworkRequest.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI).build()
fun enable(context: Context) {
val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
connectivityManager.registerNetworkCallback(networkRequest, this)
}
override fun onAvailable(network: Network) {
Log.i(TAG, "onAvailable ")
}
override fun onLost(network: Network?) {
super.onLost(network)
Log.i(TAG, "onLost ")
}
}
}
Эта реализация работает хорошо, за исключением двух проблем, с которыми мы столкнулись
-
Если мы подключаемся к Интернету, используя как Wi-Fi, так и мобильные данные, и отключаем Wi-Fi, иногда запускается
onLost()
обратный вызов, за которым следуетonAvailable()
, как и ожидалось, но в других случаях запускается толькоonLost()
, что неверно. -
Если у нас нет подключения к Интернету и мы открываем приложение,
onLost()
оно не запускается, однако, если у нас есть подключение к Интернету и мы открываем приложение,onAvailable()
оно запускается.
Любая помощь, предложения, обходные пути или другие подходы для надежного обнаружения изменений подключения к Интернету действительно были бы оценены.
Протестировано на Xioami A2 (Android 9), OnePlus (Android 9)
ДЕМОНСТРАЦИОННЫЙ проект
https://github.com/PhanVanLinh/AndroidNetworkChangeReceiver
Комментарии:
1. Вы нашли подход к решению вашей второй проблемы?
2. Нет, я не могу найти ответ, поэтому я удаляю эту функцию из своего приложения. я все еще ищу решение
Ответ №1:
Я использовал ваш проект и добавил другой метод: onCapabilitiesChanged
. Я начал с того, что режим полета был включен по электронной почте, а затем выключен, а затем снова включен. Это журналы:
Доступно 632
onCapabilitiesChanged 632 [Транспорт: СОТОВАЯ СВЯЗЬ …]
Доступно 632
onCapabilitiesChanged 632 [Транспорт: СОТОВАЯ СВЯЗЬ …]
Доступно 632
onCapabilitiesChanged 632 [Транспорт: СОТОВАЯ СВЯЗЬ …]
onCapabilitiesChanged 632 [Транспорт: СОТОВАЯ СВЯЗЬ …]
onCapabilitiesChanged 632 [Транспорт: СОТОВАЯ СВЯЗЬ …]
Доступно 633
onCapabilitiesChanged 633 [Транспорт: WIFI …] onAvailable 633 onCapabilitiesChanged 633 [Транспорт: WIFI …]
Доступно 633
onCapabilitiesChanged 633 [Транспорт: WIFI …]
onCapabilitiesChanged 633 [Транспорт: WIFI …]
onCapabilitiesChanged 633 [Транспорт: WIFI …]
onCapabilitiesChanged 633 [Транспорт: WIFI …]
onCapabilitiesChanged 633 [Транспорт: WIFI …]
onCapabilitiesChanged 633 [Транспорт: WIFI …]
onLost 632
onLost 632
onLost 632
onLost 633
onLost 633
onLost 633
Доступно 634
onCapabilitiesChanged 634 [Транспорт: СОТОВАЯ СВЯЗЬ …]
Доступно 634
onCapabilitiesChanged 634 [Транспорт: СОТОВАЯ СВЯЗЬ …]
Доступно 634
onCapabilitiesChanged 634 [Транспорт: СОТОВАЯ СВЯЗЬ …]
onCapabilitiesChanged 634 [Транспорт: СОТОВАЯ СВЯЗЬ …]
onCapabilitiesChanged 634 [Транспорт: СОТОВАЯ СВЯЗЬ …]
onCapabilitiesChanged 634 [Транспорт: СОТОВАЯ СВЯЗЬ …]
Доступно 635
onCapabilitiesChanged 635 [Транспорт: WIFI …]
Доступно 635
onCapabilitiesChanged 635 [Транспорт: WIFI …]
Доступно 635
onCapabilitiesChanged 635 [Транспорт: WIFI …]
onCapabilitiesChanged 635 [Транспорт: WIFI …]
onCapabilitiesChanged 635 [Транспорт: WIFI …]
onCapabilitiesChanged 635 [Транспорт: WIFI …]
onLost 634
onLost 634
onLost 634
onCapabilitiesChanged 635 [Транспорт: WIFI …]
onCapabilitiesChanged 635 [Транспорт: WIFI …]
Как вы можете видеть, LOST
предназначен для сотовой передачи, в то время как AVAILABLE
предназначен для WiFi
Следуя вашему варианту использования (включить Wi-Fi, включить mobiledata, отключить данные Wi-Fi, включить Wi-Fi, отключить Wi-Fi), это то, что я получаю.
Доступно 640
onCapabilitiesChanged 640 [Транспорт: WIFI … ]
Доступно 640
onCapabilitiesChanged 640 [Транспорт: WIFI … ]
onCapabilitiesChanged 640 [Транспорт: WIFI … ]
onCapabilitiesChanged 640 [Транспорт: WIFI … ]
onCapabilitiesChanged 640 [Транспорт: WIFI … ]
onCapabilitiesChanged 640 [Транспорт: WIFI … ]
Загрузка 640
Загрузка 640
Доступно 641
onCapabilitiesChanged 641 [Транспорт: СОТОВАЯ СВЯЗЬ … ]
Доступно 641
onCapabilitiesChanged 641 [Транспорт: СОТОВАЯ СВЯЗЬ … ]
onCapabilitiesChanged 641 [Транспорт: СОТОВАЯ СВЯЗЬ … ]
onCapabilitiesChanged 641 [Транспорт: СОТОВАЯ СВЯЗЬ … ]
Доступно 642
onCapabilitiesChanged 642 [Транспорт: WIFI … ]
Доступно 642
onCapabilitiesChanged 642 [Транспорт: WIFI … ]
onCapabilitiesChanged 642 [Транспорт: WIFI … ]
onCapabilitiesChanged 642 [Транспорт: WIFI … ]
onCapabilitiesChanged 642 [Транспорт: WIFI … ]
onCapabilitiesChanged 642 [Транспорт: WIFI … ]
onLost 641
onLost 641
onLost 642
onLost 642
Доступно 643
onCapabilitiesChanged 643 [Транспорт: СОТОВАЯ СВЯЗЬ … ]
Доступно 643
onCapabilitiesChanged 643 [Транспорт: СОТОВАЯ СВЯЗЬ … ]
onCapabilitiesChanged 643 [Транспорт: СОТОВАЯ СВЯЗЬ … ]
onCapabilitiesChanged 643 [Транспорт: СОТОВАЯ СВЯЗЬ … ]
Комментарии:
1. Спасибо за ваше тестирование. Я прочитал ваш журнал 3 раза, но все еще не могу понять. В настоящее время, если у вас есть устройство Android 9, вы можете еще раз протестировать несколько раз, как это `включить Wi-Fi, включить mobiledata, отключить данные Wi-Fi, включить Wi-Fi, отключить Wi-Fi // обычно onAvaiable здесь не вызывается). Вы можете попробовать это несколько раз, и вы увидите проблему. На моем устройстве Android 8 все работает хорошо, но я не уверен, что все Android 8 работают хорошо или нет
2. Он вызывал onAvailable для сотовой сети для меня: каждый раз, когда я отключал Wi-Fi (даже в последний раз). Я использую Samsung Note 8 с Android 9.
3. При повторной попытке я не получил onLost для сотовой связи, когда я включил Wi-Fi, а затем я не получил onAvailable, когда я его выключил.
4.
onCapabilitiesChanged
должно сработать. У меня также была похожая проблема, и добавление проверки на наличие действительного ИнтернетаnetworkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) amp;amp; networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)
помогло
Ответ №2:
Определение широковещательного приемника на AndroidManifest немного изменилось. Вы можете найти соответствующее описание здесь.
Вы уже реализовали этот способ, но в любом случае я хотел бы добавить ссылки на классы сетевого обратного вызова в качестве контрольной точки.
Комментарии:
1. Я прочитал ваш источник на github и обнаружил, что ваша основная идея — проверять состояние Интернета каждые 5 секунд. Если это правильно, я чувствую, что это не очень хорошо для производительности. Есть ли какой-либо способ оптимизации? Поправьте меня, если я ошибаюсь.
2. Привет, я могу понять ваши опасения, хорошо, тогда я обновлю контекст ответа, может быть, вы сможете найти другое решение на developer.android.com .
3. Да, на самом деле изменение подключения к Интернету для прослушивания является лишь небольшим улучшением для моего приложения. Если он потребляет слишком много батареи, я думаю, мне не нужно помещать его внутрь, потому что от него не слишком много пользы. Теперь я уже удаляю эту функцию из своего приложения: D, просто когда вызываю API и интернета нет, я показываю ошибку: v
Ответ №3:
Может быть, вы можете попробовать использовать requestNetwork
вместо registerNetworkCallback
.
Комментарии:
1. Это не изменило бы ничего, связанного с onAvailable. Единственная разница в поведении между ними заключается в том, что
requestNetwork
они будут поддерживать сеть для вашего приложения, аregisterNetworkCallback
нет. Т. е., если ни у каких приложений нет открытыхrequestNetwork
запросов для определенной сети,ConnectivityService
это приведет к ее отключению. Однако для этого не требуется никакихregisterNetworkCallback
запросов типа.
Ответ №4:
Обратный вызов должен выглядеть следующим образом:
val callback = object : ConnectivityManager.NetworkCallback() {
private val availableNetworks: MutableSet<Network> = HashSet()
override fun onAvailable(network: Network) {
val networkCapabilities = connectivityManager.getNetworkCapabilities(network)
val hasInternetCapability =
networkCapabilities?.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
if (hasInternetCapability == true) {
availableNetworks.add(network)
sendNetworkState()
}
}
override fun onLost(network: Network) {
availableNetworks.remove(network)
sendNetworkState()
}
private fun sendNetworkState() {
if (availableNetworks.isNotEmpty()) {
// TODO: Notify the Internet connection is available
} else {
// TODO: Notify the Internet connection is unavailable
}
}
}
Регистрация обратного вызова:
val request = NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
.build()
connectivityManager.registerNetworkCallback(networkRequest, callback)
Объяснение
onLost
вызывается для каждой сети, которая была ранее передана onAvailable
, согласно документации:
Если обратный вызов был зарегистрирован с помощью registerNetworkCallback(), он будет вызываться для каждой сети, которая больше не удовлетворяет критериям обратного вызова.
Также возможно, что onAvailable
будет вызван дважды перед onLost
Первоначально код был найден здесь:https://www.youtube.com/watch?v=To9aHYD5OVk