Android:网络连接变化监听器

100

我已经有了监听网络连接变化的代码 -

public class NetworkStateReceiver extends BroadcastReceiver
{
  public void onReceive(Context context, Intent intent)
  {
    Log.d("app","Network connectivity change");

    if(intent.getExtras() != null)
    {
      NetworkInfo ni = (NetworkInfo) intent.getExtras().get(ConnectivityManager.EXTRA_NETWORK_INFO);
      if(ni != null && ni.getState() == NetworkInfo.State.CONNECTED)
      {
        Log.i("app", "Network " + ni.getTypeName() + " connected");
      }
    }

    if(intent.getExtras().getBoolean(ConnectivityManager.EXTRA_NO_CONNECTIVITY, Boolean.FALSE))
    {
      Log.d("app", "There's no network connectivity");
    }
  }
}

我使用这段代码检查互联网连接 - Internet Check

但问题是,如果网络突然失去互联网连接而没有任何连接更改,这段代码就无用了。是否有办法创建广播接收器以侦听互联网连接性的更改? 我有一个Web应用程序,突然的互联网连接变化可能会引起问题。


请参考以下链接:https://dev59.com/U2Uo5IYBdhLWcg3w3yqi - lenhuy2106
13个回答

3

因为有更好的实现方式可用,所以在2023年回答此问题

NetworkObserver.kt

/**
 * This class is in charge of listening to the state of the network connection and notifying the
 * activity if the state of the connection changes.
 * */
class NetworkObserver constructor(
    private val context: Context,
    private val lifecycle: Lifecycle
  ) : DefaultLifecycleObserver {

  private lateinit var networkCallback: ConnectivityManager.NetworkCallback
  private var connectivityManager: ConnectivityManager? = null
  private val validNetworks = HashSet<Network>()

  private lateinit var job: Job
  private lateinit var coroutineScope: CoroutineScope

  // State Holder: Indicating either the network is available or not-available
  private val _networkAvailableStateFlow: MutableStateFlow<NetworkState> = MutableStateFlow(NetworkState.Available)

  val networkAvailableStateFlow
    get() = _networkAvailableStateFlow

  // ---> This variable can be accessed anytime to get the current state of the network
  val isConnected: Boolean
    get() = _isConnected.get()

  private val _isConnected = AtomicBoolean(false)

  override fun onCreate(owner: LifecycleOwner) {
    super.onCreate(owner)
    init()
  }

  override fun onStart(owner: LifecycleOwner) {
    super.onStart(owner)
    registerNetworkCallback()
    checkValidNetworks()
  }

  override fun onStop(owner: LifecycleOwner) {
    super.onStop(owner)
    unregisterNetworkCallback()
  }

  private fun init() {
    // Initialize the connectivity manager instance
    connectivityManager = context.getSystemService(CONNECTIVITY_SERVICE) as ConnectivityManager
  }

  private fun registerNetworkCallback() {
    if (lifecycle.currentState.isAtLeast(Lifecycle.State.STARTED)) {
      // Observing the network should happen only when the life-cycle is in started state
      initCoroutine()
      initNetworkMonitoring()
    }
  }

  private fun unregisterNetworkCallback() {
    validNetworks.clear()
    connectivityManager?.unregisterNetworkCallback(networkCallback)
    job.cancel()
  }

  /**
   * Co-Routine used to monitor the connectivity
   */
  private fun initCoroutine() {
    // Create a job instance
    job = Job()
    // Provide a co-routine scope
    coroutineScope = CoroutineScope(Dispatchers.Default + job)
  }

  private fun initNetworkMonitoring() {
    networkCallback = createNetworkCallback()

    val networkRequest = NetworkRequest.Builder()
        .addCapability(NET_CAPABILITY_INTERNET)
        .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
        .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
        .build()
    connectivityManager?.registerNetworkCallback(networkRequest, networkCallback)
  }

  private fun createNetworkCallback() = object : ConnectivityManager.NetworkCallback() {
    override fun onAvailable(network: Network) {
      connectivityManager?.getNetworkCapabilities(network).also {
        if (it?.hasCapability(NET_CAPABILITY_INTERNET) == true) {
          validNetworks.add(network)
        }
      }
      checkValidNetworks()
    }

    override fun onLost(network: Network) {
      validNetworks.remove(network)
      checkValidNetworks()
    }
  }

  private fun checkValidNetworks() {
    coroutineScope.launch {
      _networkAvailableStateFlow.emit(
          if (validNetworks.size > 0){
            _isConnected.set(true)
            NetworkState.Available
          } else {
            _isConnected.set(false)
            NetworkState.Unavailable
          }
      )
    }
  }
}

sealed class NetworkState {
  object Unavailable : NetworkState()
  object Available : NetworkState()
}

使用方法

    // --> Initialize the network observer in your activity or fragment
    networkObserver = NetworkObserver(this, lifecycle)
    lifecycle.addObserver(networkObserver)

    // --> Use live data to observe the network changes
    networkObserver.networkAvailableStateFlow.asLiveData().observe(this, Observer { networkState ->
      when (networkState) {
        NetworkState.Unavailable -> SnackBarDisplay.showNetworkUnavailableAlert(binding.root)
        NetworkState.Available -> SnackBarDisplay.removeNetworkUnavailableAlert()
      }
    })

我已经在我的GitHub上发布了完整解决方案


1

参考 https://developer.android.com/training/monitoring-device-state/connectivity-status-type

要指定网络的传输类型,例如 Wi-Fi 或蜂窝连接,以及当前已连接网络的功能(例如互联网连接),您必须配置一个网络请求。

声明描述应用程序网络连接需求的 NetworkRequest。以下代码创建了一个请求,该请求连接到互联网并使用 Wi-Fi 或蜂窝连接作为传输类型。

将此添加到 onCreate 中

NetworkRequest networkRequest = new NetworkRequest.Builder()
    .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
    .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
    .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
    .build();

配置网络回调:当您使用ConnectivityManager注册NetworkRequest时,必须实现一个NetworkCallback来接收有关连接状态和网络功能变化的通知。在NetworkCallback中最常实现的函数包括以下几个:onAvailable()表示设备已连接到满足NetworkRequest中指定的能力和传输类型要求的新网络;onLost()表示设备已失去与网络的连接;onCapabilitiesChanged()表示网络的功能已更改,NetworkCapabilities对象提供有关网络当前功能的信息。
添加监听器。
private ConnectivityManager.NetworkCallback networkCallback = new ConnectivityManager.NetworkCallback() {
@Override
public void onAvailable(@NonNull Network network) {
    super.onAvailable(network);
}

@Override
public void onLost(@NonNull Network network) {
    super.onLost(network);
}

@Override
public void onCapabilitiesChanged(@NonNull Network network, @NonNull NetworkCapabilities networkCapabilities) {
    super.onCapabilitiesChanged(network, networkCapabilities);
    final boolean unmetered = networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
}};

注册网络更新

声明NetworkRequest和NetworkCallback后,使用requestNetwork()或registerNetworkCallback()函数来搜索设备连接的满足NetworkRequest的网络。然后将状态报告给NetworkCallback。

在onCreate中注册

ConnectivityManager connectivityManager =
    (ConnectivityManager) getSystemService(ConnectivityManager.class);
connectivityManager.requestNetwork(networkRequest, networkCallback);

-3

实现 'com.treebo:internetavailabilitychecker:1.0.1'

public class MyApp extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        InternetAvailabilityChecker.init(this);
    }

    @Override
    public void onLowMemory() {
        super.onLowMemory();
        InternetAvailabilityChecker.getInstance().removeAllInternetConnectivityChangeListeners();
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接