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 个回调中的哪一个是“最终”回调?

4

2 回答 2

2

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

抛出一个默认情况,提醒您wifi状态的任何变化,而不仅仅是“CONNECTED”和“DISCONNECTED”。您可能会发现手机在几种不同的状态之间旋转,而不仅仅是向您射击同一个状态六次。希望从那里开始,如何继续编写代码会更清楚一些。

于 2011-02-18T21:08:41.630 回答
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;
    // ...
  }
}

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

于 2012-02-20T21:56:32.077 回答