我正在开发基于 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
实例,但我相信这会断开所有同行。
答案 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强制执行的限制。我不知道为什么。我希望这里有人可以为您提供解决方案 - 可能会进行此项研究并进一步探索。但如果不存在解决方案(目前),我不会感到惊讶。