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

10

我正在尝试使用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个回调中的哪一个是“最后一个”?


这里到底是什么问题?当你说手机在第一次广播后没有重新连接,难道6个中没有一个和其他的一样好吗? - Heiko Rupp
问题是我不想让我的广播接收器执行六次相同的断开处理逻辑。 - eshayne
2个回答

2
你说这是一系列“6个不相关的回调函数”,但是你的if / else-if语句仅检查了DISCONNECTED和CONNECTED,看起来没有默认块处理所有其他情况。从NetworkInfo.DetailedState api页面可以看到,NetworkInfo.getDetailedState()可能返回10种可能的状态,包括“连接中”、“扫描中”、“断开连接”,所有这些都是手机刚从网络断开的可能行为。
添加一个默认情况的代码块,以警报您任何wifi状态的更改,而不仅仅是“连接”和“断开连接”。您可能会发现手机在几个不同的状态之间旋转,而不仅仅是向您发射相同的状态六次。从那里开始,您的代码如何继续将变得更加清晰易懂。

谢谢。我应该澄清一下 - 实际上,我在检查连接或断开之前记录了每个完整的NetworkInfo。它们都是断开的。我已经更新了原始帖子以展示所有日志条目的样子。如果您能想到其他要检查的内容以尝试区分它们,请告诉我,我会尝试一下。 - eshayne

0
一个解决方法是在某个地方(全局状态、共享偏好等)维护您的最后一个回调操作,并仅在操作发生更改时运行回调函数。
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;
    // ...
  }
}

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

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