检测与 WiFi 接入点的断开连接

发布于 2024-10-18 05:32:43 字数 1582 浏览 7 评论 0原文

我正在尝试使用 BroadcastReceiver 来检测手机何时与 WiFi 接入点断开连接。为此,我在清单中注册了 BroadcastReceiver:

<receiver android:name="com.eshayne.android.WiFiBroadcastReceiver">
    <intent-filter>
        <action android:name="android.net.wifi.STATE_CHANGE" />
    </intent-filter>
</receiver>

在我的 WiFiBroadcastReceiver 类中,我正在检查 NETWORK_STATE_CHANGED_ACTION 操作并查看 NetworkInfo 的详细状态:

if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
    NetworkInfo info = (NetworkInfo)intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
    android.util.Log.d("com.eshayne.android.WiFiBroadcastReceiver", "network state change - detailedState=" + info.getDetailedState() + ": " + info.toString());
    if (info.getDetailedState() == DetailedState.DISCONNECTED) {
        ...
    }
    else if (info.getDetailedState() == DetailedState.CONNECTED) {
        ...
    }

我看到的问题是,当手机离开 WiFi 接入点的范围时,我的“断开连接”回调被调用 6 次 - 非常有规律地大约每 15 秒一次 - 在它停止之前。到目前为止,我还没有找到每个回调的 NetworkInfo 之间的任何区别特征。写入日志的每个 NetworkInfo 对象如下所示:

02-18 10:16:51.918 D/com.eshayne.android.WiFiBroadcastReceiver( 1511): network state change - detailedState=DISCONNECTED: NetworkInfo: type: WIFI[], state: DISCONNECTED/DISCONNECTED, reason: (unspecified), extra: (none), roaming: false, failover: false, isAvailable: true

这也不是手机在 WiFi 范围内徘徊的问题,因为我的“已连接”回调不会在“断开连接”回调之间调用。其间也没有触发任何其他状态。只是一系列快速的 6 个回调,每个回调都有详细的 DISCONNECTED 状态。

有没有更好的方法让我检测手机何时失去 WiFi 连接,以便每次断开连接时只调用一次回调?或者有什么方法可以检测我看到的 6 个回调中哪一个是“最终”回调?

I am trying to use a BroadcastReceiver to detect when the phone has disconnected from a WiFi access point. To do this, I registered my BroadcastReceiver in the manifest:

<receiver android:name="com.eshayne.android.WiFiBroadcastReceiver">
    <intent-filter>
        <action android:name="android.net.wifi.STATE_CHANGE" />
    </intent-filter>
</receiver>

In my WiFiBroadcastReceiver class, I am checking for a NETWORK_STATE_CHANGED_ACTION action and looking at the NetworkInfo's detailed state:

if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
    NetworkInfo info = (NetworkInfo)intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
    android.util.Log.d("com.eshayne.android.WiFiBroadcastReceiver", "network state change - detailedState=" + info.getDetailedState() + ": " + info.toString());
    if (info.getDetailedState() == DetailedState.DISCONNECTED) {
        ...
    }
    else if (info.getDetailedState() == DetailedState.CONNECTED) {
        ...
    }

The problem I'm seeing is that when the phone leaves the WiFi access point's range, my "disconnected" callback gets called 6 times - pretty regularly at about once every 15 seconds - before it stops. So far I haven't been able to find any distinguishing characteristics between each callback's NetworkInfo. Each NetworkInfo object being written to the log looks like this:

02-18 10:16:51.918 D/com.eshayne.android.WiFiBroadcastReceiver( 1511): network state change - detailedState=DISCONNECTED: NetworkInfo: type: WIFI[], state: DISCONNECTED/DISCONNECTED, reason: (unspecified), extra: (none), roaming: false, failover: false, isAvailable: true

It's also not an issue of the phone wandering in and out of WiFi range, as my "connected" callback is not called in between "disconnected" callbacks. Nor are any other states being triggered in between. Just a rapid series of 6 callbacks each with a detailedState of DISCONNECTED.

Is there a better way for me to detect when the phone has lost its WiFi connection, so that my callback only gets called once per disconnect? Or any way to detect which of the 6 callbacks I'm seeing is the "final" one?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

走走停停 2024-10-25 05:32:43

你说它是“6 个断开连接的回调的快速系列”,但你的 if/else-if 只检查 DISCONNECTED 和 CONNECTED,看起来没有默认块来处理所有其他情况。从 NetworkInfo.DetailedState api 页面,有 10 种可能的状态NetworkInfo.getDetailedState() 可以返回,包括“连接”、“扫描”、“断开连接”,对于刚刚与网络断开连接的手机来说,所有这些都是合理的行为。

放弃默认情况,提醒您 wifi 状态的任何变化,而不仅仅是“已连接”和“已断开连接”。您可能会发现手机在几种不同的状态之间旋转,而不仅仅是向您发射同一个状态六次。希望从这里开始,如何继续编写代码将会更加清晰。

You say it's a "rapid series of 6 disconnected callbacks", but your if/else-if only checks for DISCONNECTED and CONNECTED, with what looks like no default block to handle all other cases. From the NetworkInfo.DetailedState api page, there's 10 possible states that could be returned by NetworkInfo.getDetailedState(), including "connecting", "scanning", "disconnecting", all of which would be plausible behavior for a phone that just got disconnected from a network.

Throw down a default case that alerts you to any change in wifi state, not just "CONNECTED" and "DISCONNECTED". You might find that the phone is rotating between several different states, and not just shotgunning the same one at you six times. Hopefully from there, how to proceed in your code will be a little clearer.

倾城泪 2024-10-25 05:32:43

您可以使用的一种解决方法是在某处维护最后一个回调操作(全局状态、共享首选项等),并且仅在操作发生更改时才运行回调。

enum NetworkCallbackAction { None, Disconnected, Connected };
NetworkCallbackAction lastHandledAction = NetworkCallbackAction.None;

// ...

if (info.getDetailedState() == DetailedState.DISCONNECTED) {
  if (lastHandledAction != NetworkCallbackAction.Disconnected) {
    lastHandledAction = NetworkCallbackAction.Disconnected;
    // ...
  }
}
else if (info.getDetailedState() == DetailedState.CONNECTED) {
  if (lastHandledAction != NetworkCallbackAction.Connected) {
    lastHandledAction = NetworkCallbackAction.Connected;
    // ...
  }
}

这种逻辑的更好抽象是编写一个广播接收器,其唯一的工作是将网络状态变化规范化为一致的事件并消除现实世界的怪癖,然后重新广播其自己的操作。这使您可以将原始更新简化为对您的应用程序有意义的内容。例如,它可以记住它的最后一次广播并且仅广播更改(类似于上面的代码所做的)。如果出现突发的网络更改意图,它可以等待几秒钟,然后再广播其收到的最后状态。

One workaround you could use is to maintain your last callback action somewhere (global state, shared preferences, etc.) and only run your callbacks if the action has changed.

enum NetworkCallbackAction { None, Disconnected, Connected };
NetworkCallbackAction lastHandledAction = NetworkCallbackAction.None;

// ...

if (info.getDetailedState() == DetailedState.DISCONNECTED) {
  if (lastHandledAction != NetworkCallbackAction.Disconnected) {
    lastHandledAction = NetworkCallbackAction.Disconnected;
    // ...
  }
}
else if (info.getDetailedState() == DetailedState.CONNECTED) {
  if (lastHandledAction != NetworkCallbackAction.Connected) {
    lastHandledAction = NetworkCallbackAction.Connected;
    // ...
  }
}

A nicer abstraction of this logic would be to write a broadcast receiver who's only job is to normalize the network state changes into consistent events and smooth out the real-world quirks, and then re-broadcast its own actions. This allows you to simplify the raw updates into something that makes sense for your application. It could, for example, remember it's last broadcasts and only broadcast changes (similar to what the code above does). In case of bursts of network change intents it could wait a few seconds before broadcasting the last state it received.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文