2011-02-18 81 views
10

我试图使用BroadcastReceiver来检测手机从WiFi接入点断开连接。要做到这一点,我登记我的清单中的广播接收器:检测从WiFi接入点断开连接

<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 

它也没有电话徘徊在进出无线网络范围内的问题,因为我的“连接”回调不是“断开连接”回调之间称为。两者之间也没有其他国家被触发。只是一个快速的6个回调系列,每个回调都有一个详细的DISCONNECTED状态。

有没有更好的方式让我检测手机何时失去了WiFi连接,以便我的回调只在每次断开连接时被调用一次?或者通过任何方式来检测我看到的6个回调中的哪一个是“最终”回调?

+0

问题到底是什么?当你说手机在第一次广播后没有重新连接时,是不是与其他6一样好? – 2011-02-18 17:04:13

+0

问题是我不希望我的广播接收器执行六次相同的断开连接处理逻辑。 – eshayne 2011-02-18 17:43:04

回答

2

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

抛出一个默认情况下,提醒您任何更改在WiFi状态,不只是“连接”和“断开”。你可能会发现手机正在几个不同的状态之间转动,而不只是六次向你射出同一个手机。希望从那里,如何在你的代码中进行将会更清楚一点。

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; 
    // ... 
    } 
} 

这种逻辑的一个更好的抽象是写广播接收机谁的唯一工作就是规范网络状态变为一致的事件,并顺利出真实世界的怪癖,然后重新播放自己的行动。这使您可以将原始更新简化为对您的应用程序有意义的内容。例如,它可以记住它是最后一次广播,只是广播更改(类似于上面的代码)。在发生网络改变意图爆发的情况下,它可能会等待几秒钟,然后广播最后收到的状态。