【问题标题】:Check for internet connectivity on API29检查 API 29 上的互联网连接
【发布时间】:2019-11-04 16:03:08
【问题描述】:

我使用以下方法检查互联网连接:

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

不过,我发现 NetworkInfogetActiveNetworkInfo()isConnected() 现在都已弃用。我在 SO 上检查了几个线程:

ConnectivityManager getNetworkInfo(int) deprecated

activeNetworkInfo.type is deprecated in API level 28

不过,它们都提供了不推荐使用的方法的答案。我一直在环顾四周,没有任何运气。是否有任何简单的方法来检查互联网连接,或者我应该继续使用我的方法并忽略已弃用的方法,因为它适用于 API29?

谢谢。

【问题讨论】:

    标签: java android


    【解决方案1】:

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

    【讨论】:

    • 非常感谢您提供这个出色的解决方案。我真的很感激。
    • 现实世界中有更多的连接方式
    【解决方案2】:

    这是我对 SDK 29 的解决方案:一个名为 NetworkWatcher 的类,它观察网络的变化。它提供了诸如isWifiOn 之类的原始变量,以及通过FlowLiveData 观察网络随时间变化的选项。

    @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(),而是使用Koin 等DI 框架将NetworkWatcher 注入到我需要的地方。

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        【解决方案4】:

        我的答案很干净,在 Kotlin 中,还可以处理不同的 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
                }
            }
        

        【讨论】:

          猜你喜欢
          • 2012-02-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-04-15
          • 2017-03-16
          • 2014-02-08
          • 2012-06-12
          • 1970-01-01
          相关资源
          最近更新 更多