I хочет использовать диспетчер подключений, который предоставляет метод 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
}
connectivityManager.activeNetworkInfo также устарел на уровне API 29.
Теперь нам нужно использовать 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
}
Да getType() не рекомендуется на уровне API 28
Теперь нам нужно использовать Callers, чтобы переключиться на проверку NetworkCapabilities.hasTransport (число)
Также 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
}
@kkarakk Ты в этом уверен? Никаких признаков устаревания в документы
Как теперь проверить, есть ли у устройства подключение к Интернету? Пока это был просто connectivityManager.activeNetworkInfo?.isConnected == true. Что нам теперь делать? Просто connectivityManager.activeNetwork != null?
Код не работает. У меня нет SIM-карты, но я подключен через Wi-Fi к Интернету. isInternetAvailable() и hasTransport(NetworkCapabilities.TRANSPORT_WIFI) возвращают false.
@ranasaha извините за поздний ответ, теперь нам нужно использовать ConnectivityManager#getNetworkCapabilities, пожалуйста, проверьте обновленный ответ, я добавил образец кода, используя ConnectivityManager#getNetworkCapabilities
@NileshRathod после того, как вы создадите экземпляр переменной actNw, и перед тем, как вы проверите сетевые возможности, вы должны добавить нулевую проверку. getNetworkCapabilities допускает значение NULL.
@Francis да, вам нужно использовать NetworkCapabilities.TRANSPORT_BLUETOOTH и NetworkCapabilities.TRANSPORT_ETHERNET для получения дополнительной информации, пожалуйста, проверьте Возможности сети
@NileshRathod Так есть ли общее решение? А как насчет hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)?
Но нам все еще нужно использовать activeNetworkInfo для старых версий. Есть ли для этого какая-нибудь библиотека поддержки?
Могу ли я узнать, зачем проверять M (M - это API 23)
@CheokYanCheng May I know why checking for M, потому что connectivityManager.activeNetwork добавлен в API уровня 23
Поскольку большинство методов в NetworkInfo устарели только после 28. Мы все еще можем использовать старый добрый NetworkInfo до 28
Текущие новые методы подвержены ошибкам. networkInfo.isConnectedOrConnecting намного лучше и надежнее. Кто знает, нужно ли проверять и TRANSPORT_VPN?
Нет, как видно отсюда: 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 ()
This method was deprecated in API level 28.
Callers should switch to checking
NetworkCapabilities.hasTransport(int)instead with one of theNetworkCapabilities#TRANSPORT_* constants : getType()andgetTypeName()cannot account for networks using multiple transports. Note that generally apps should not care about transport;NetworkCapabilities.NET_CAPABILITY_NOT_METEREDandNetworkCapabilities.getLinkDownstreamBandwidthKbps()are calls that apps concerned with meteredness or bandwidth should be looking at, as they offer this information with much better accuracy.
метод замены устаревшего API находится в официальном документе API, который я приложил выше.
getActiveNetworkInfo() устарел в API 29. Я думаю, вам следует обновить свой ответ.
Я не понимаю, что использовать, если все, что мне нужно знать, - есть ли подключение к Интернету или нет. Пока я просто использую это: connectivityManager.activeNetworkInfo?.isConnected == true. Следует ли нам использовать сейчас: connectivityManager.activeNetwork != null?
Я адаптировал ответ 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
}
}
....
Если вы используете минимальный уровень 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
}
}
Недавно мне пришлось написать небольшую функцию для проверки сетевого подключения внутри моего единственного WebView. Я также заметил, что API сильно эволюционировал, особенно когда появился Kotlin, поэтому поиск действительной ссылки занял несколько минут.
Вот мой небольшой класс NetworkConnectivityManager с простой функцией проверки доступности сети.
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
}
}
Вот мое решение для 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")
}
}
Или, чтобы ответить на ваш вопрос, просто прочтите значение Wi-Fi, например:
if (NetworkWatcher.getInstance(this@BaseApp).isOverWifi) {
// do stuff
}
Боковое примечание: вместо того, чтобы постоянно использовать getInstance(), я использую структуру DI, такую как Коин, для внедрения NetworkWatcher там, где он мне нужен.
Замечательно !!
Код Java:
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;
}
Я просто хотел узнать, подключено ли устройство к Интернету, независимо от типа подключения:
@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
}
Я использую эту функцию Kotlin для проверки интернет-соединения:
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
}
}
Чуть более простая версия (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
}
отличный ответ!
Это лучший ответ
Надеюсь, это сработает для вас! этот код работает в API 21 и далее
// создаем новый класс и добавляем следующие
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;
}
}
// в MainActivity
CheckNetwork myNetwork = new CheckNetwork(this);
// в 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();
}
Единственное, что у меня сработало, так как я работаю над целевым API 30 и потому, что метод NetworkInfo устарел в API 28.
\\ Вы сэкономили мне время .. большое спасибо :)
Вот реализация Kotlin для двух методов 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
}
и общий метод:
fun isConnected(context: Context): Boolean {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
isConnectedNewApi(context)
} else{
isConnectedOld(context)
}
}
Полное решение Создайте этот класс в пакете, скажем, для подключения
импортировать android.content.Context импортировать android.content.Context.CONNECTIVITY_SERVICE импортировать 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)
}
}
}
}
абстрактный класс 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()
}
класс 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)
}
}
}
@Suppress ("УСТАРЕНИЕ")
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)
}
}
}
Использование: - Домашняя активность
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
}
}
при нажатии кнопки или любом вызове API
if (provider.getNetworkState().hasInternet()){
// do work
}
}
если вы хотите использовать проверочный интернет во фрагментах домашних дел
if ((activity as HomeActivity).provider.getNetworkState().hasInternet()) {
// api call
}
Для версий >= 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)
}
В Kotlin вы можете проверить версию Android и в соответствии с версией проверить диспетчер подключения.
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
}
Вызовите функцию расширения в своей деятельности
if (applicationContext.isInternetAvailable()) { }