如何在Wi-Fi Direct范围内不再提供对等设备时收到通知?

时间:2014-01-12 06:50:15

标签: android android-wifi wifi-direct wifimanager wifip2p

我正在开发基于 Wifi Direct API的Android应用程序。我已在Activity BroadcastReceiver注册,以便收到有关以下Wifi Direct活动的通知:

WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION 
WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION 
WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION  
WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION

我相信对等列表中的任何更改(包含或排除Wifi Direct范围内的对等方)都可能触发BroadcastReceiver。在我的应用中,当找到新的对等体时,其名称正确地包含在ListView中,但如果对等体离开无线范围(或者如果我关闭其Wi-Fi接口),则{{1}没有被调用(更具体地说,

BroadcastReceiver

事件未被触发),对等名称仍保留在WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION

我想知道是否有任何方式来处理这个问题,因为对等名称包含在ListView中,但从未被排除。我已经考虑重新初始化Channel和ListView实例,但我相信这会断开所有同行。

1 个答案:

答案 0 :(得分:25)

  

我相信对等列表中的任何更改(包含或排除Wifi Direct范围内的对等方)都可能触发BroadcastReceiver。

是的,我认为这应该发生。

  

在我的应用中,当找到新的对等体时,其名称正确包含在ListView中,但如果对等体离开无线范围(或者如果我关闭其Wi-Fi接口),则不会调用BroadcastReceiver(更具体地说,未触发WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION事件),并且对等名称仍保留在ListView中。

我们可以尝试挖掘源代码,看看我们是否可以解释这种行为。

注意:我没有提供解决方案。但是,以下研究可能会帮助您理解“问题”。更好。

我们将从这里开始:WifiP2pSettings Link

这是您转到设置>时看到的片段Wifi> WiFi直。如果您浏览代码,您会注意到实现与WifiDirectDemo项目非常相似 - BroadcastReceiver侦听相同的四个操作(还有两个 - 用于UI更新)。我们查看此片段的原因是检查演示本身是否存在缺陷。但是,看起来演示没问题。

继续 - 让我们看看谁在广播这个动作WIFI_P2P_PEERS_CHANGED_ACTION - 最终,我们有兴趣找出为什么不是一旦设备离线/超出范围,就会发生这种情况。这会将我们带到WifiP2pService Link

方法WifiP2pService # sendPeersChangedBroadcast()发布广播:

private void sendPeersChangedBroadcast() {
    final Intent intent = new Intent(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION);
    intent.putExtra(WifiP2pManager.EXTRA_P2P_DEVICE_LIST, new WifiP2pDeviceList(mPeers));
    intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
    mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
}

通过查看WifiP2pService,您可以确定调用了sendPeersChangedBroadcast()以响应多个事件。我们对此感兴趣:WifiMonitor.P2P_DEVICE_LOST_EVENT Link

....
case WifiMonitor.P2P_DEVICE_LOST_EVENT:
    device = (WifiP2pDevice) message.obj;
    // Gets current details for the one removed
    device = mPeers.remove(device.deviceAddress);
    if (device != null) {
        sendPeersChangedBroadcast();
    }
    break;
....

WifiMonitor # handleP2pEvents(String)负责发送上述case中的消息。上链查找MonitorThread - WifiMonitor中的静态内部类。 MonitorThread # dispatchEvent(String)调用handleP2pEvents(String)方法。

最后,有趣的事情。查看run()的{​​{1}}方法:

MonitorThread
  • 首先,我们进入无限循环。
  • 第二,private static class MonitorThread extends Thread { .... public void run() { //noinspection InfiniteLoopStatement for (;;) { String eventStr = mWifiNative.waitForEvent(); .... } } .... } 告诉我,可能阻止来电。

这两点合起来向我表明,我不会得到一个明确的反应 - 好吧,绝对没有什么'瞬间般的'。我们通过上升链到达的方法 - mWifiNative.waitForEvent() - 从这个无限循环内部调用。

让我们检查一下是否可以支持我们有根据的猜测:

查看MonitorThread # dispatchEvent(String)班级Link,尤其是方法WifiNative。从类setScanInterval(int) Link调用此方法。完成方法WifiStateMachine

processMessage(Message)

请注意第一个.... case WifiP2pService.P2P_CONNECTION_CHANGED: NetworkInfo info = (NetworkInfo) message.obj; mP2pConnected.set(info.isConnected()); if (mP2pConnected.get()) { int defaultInterval = mContext.getResources().getInteger( R.integer.config_wifi_scan_interval_p2p_connected); long scanIntervalMs = Settings.Global.getLong(mContext.getContentResolver(), Settings.Global.WIFI_SCAN_INTERVAL_WHEN_P2P_CONNECTED_MS, defaultInterval); // ====>> Interval defined here mWifiNative.setScanInterval((int) scanIntervalMs/1000); } else if (mWifiConfigStore.getConfiguredNetworks().size() == 0) { if (DBG) log("Turn on scanning after p2p disconnected"); sendMessageDelayed(obtainMessage(CMD_NO_NETWORKS_PERIODIC_SCAN, ++mPeriodicScanToken, 0), mSupplicantScanIntervalMs); } .... 中的defaultInterval。它要求if block R.integer.config_wifi_scan_interval_p2p_connected中定义的config.xml为:

<!-- Integer indicating wpa_supplicant scan interval when p2p is connected in milliseconds -->
<integer translatable="false" name="config_wifi_scan_interval_p2p_connected">60000</integer>

60000毫秒。那是1分钟。因此,如果未设置Settings.Global.WIFI_SCAN_INTERVAL_WHEN_P2P_CONNECTED_MS,则扫描间隔1分钟。

由于WIFI_SCAN_INTERVAL_WHEN_P2P_CONNECTED_MS位于全局设置下,因此我们无法对其进行更改。事实上,它甚至无法被阅读。这意味着,我们在这里唯一的保证是在一分钟内刷新对等列表。间隔当然可以因品牌而异。

为了验证这一点,我在华硕平板电脑和戴尔平板电脑上运行了演示。就像你说的那样,设备上线的速度相当快(在发现阶段)。在关闭wifi时,我响应了响应。离线设备已自动从列表中删除 - 会有很长的延迟。 dell平板电脑接近60 seconds,注意到asus处于脱机状态。另一方面,华硕采用了45 seconds

对我而言,这似乎是由android强制执行的限制。我不知道为什么。我希望这里有人可以为您提供解决方案 - 可能会进行此项研究并进一步探索。但如果不存在解决方案(目前),我不会感到惊讶。