Android Wi-Fi Direct应用无法切换收发角色及更新组所有者求助
解决Wi-Fi Direct收发角色切换及组所有者更新问题
针对你遇到的无法在不重启应用的情况下切换收发角色、组所有者未更新的问题,核心原因是断开流程不彻底、状态清理不到位,以及重新连接时未刷新设备状态。以下是具体解决方案:
一、完善断开连接流程,确保彻底清理状态
原断开操作是同步调用异步方法,未等待操作完成就执行后续步骤,导致残留组状态干扰新组创建。修改为带回调的异步链式操作,确保每一步完成后再执行下一项:
fun disconnect(onDisconnected: () -> Unit) { manager?.apply { // 先取消正在进行的连接尝试 cancelConnect(channel, object : WifiP2pManager.ActionListener { override fun onSuccess() { // 移除当前组 removeGroup(channel, object : WifiP2pManager.ActionListener { override fun onSuccess() { // 停止对等设备发现 stopPeerDiscovery(channel, object : WifiP2pManager.ActionListener { override fun onSuccess() { deletePersistentGroups() cleanupSockets() isDeviceConnected = false onDisconnected() } override fun onFailure(reasonCode: Int) { deletePersistentGroups() cleanupSockets() isDeviceConnected = false onDisconnected() } }) } override fun onFailure(reasonCode: Int) { stopPeerDiscovery(channel, null) deletePersistentGroups() cleanupSockets() isDeviceConnected = false onDisconnected() } }) } override fun onFailure(reasonCode: Int) { removeGroup(channel, null) stopPeerDiscovery(channel, null) deletePersistentGroups() cleanupSockets() isDeviceConnected = false onDisconnected() } }) } ?: run { cleanupSockets() isDeviceConnected = false onDisconnected() } } private fun cleanupSockets() { try { if (::serverSocket.isInitialized) serverSocket.close() if (::clientSocket.isInitialized) clientSocket.close() } catch (e: IOException) {} }
二、切换角色前重新发起对等设备发现
断开完成后,必须重新启动设备发现,获取最新的设备状态,避免依赖缓存的旧连接信息:
// 断开完成后调用,准备重新连接 fun prepareForReconnection() { manager?.discoverPeers(channel, object : WifiP2pManager.ActionListener { override fun onSuccess() { // 发现已启动,等待广播接收器更新设备列表 } override fun onFailure(reasonCode: Int) { onP2POperationFailed(reasonCode) } }) }
三、协同两端角色配置,确保组所有者意图生效
切换角色时,两端的groupOwnerIntent必须对应:
- 发送方(客户端)设为
WifiP2pConfig.GROUP_OWNER_INTENT_MIN - 接收方(组所有者/服务端)设为
WifiP2pConfig.GROUP_OWNER_INTENT_MAX
同时需确保两端同时使用新配置发起连接,或者由一端发起后,另一端接受时应用对应配置。
四、修正连接状态监听逻辑
在广播接收器中,收到连接状态变化时,必须重新拉取最新的连接信息,避免使用旧状态:
// 在P2pBroadcastReceiver的onReceive方法中 override fun onReceive(context: Context?, intent: Intent?) { when (intent?.action) { WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION -> { val networkInfo = intent.getParcelableExtra<NetworkInfo>(WifiP2pManager.EXTRA_NETWORK_INFO) isDeviceConnected = networkInfo?.isConnected ?: false if (isDeviceConnected) { // 主动拉取最新连接信息 manager?.requestConnectionInfo(channel, object : WifiP2pManager.ConnectionInfoListener { override fun onConnectionInfoAvailable(info: WifiP2pInfo?) { onConnectionInfoChanged(info) } }) } else { isDeviceConnected = false } } // 其他Action处理... } }
五、传输会话结束后的完整切换流程
当一次传输完成后,严格执行以下步骤:
- 调用
disconnect方法,等待断开完成回调 - 断开完成后,调用
prepareForReconnection发起设备发现 - 从更新后的设备列表中选择目标设备,调用
connectToPeer并传入新的isSender参数 - 在
onConnectionInfoChanged中,先清空旧socket引用,再启动对应服务/客户端:
private fun onConnectionInfoChanged(info: WifiP2pInfo?) { if (info == null || !isDeviceConnected) return // 清空旧socket,避免干扰新连接 cleanupSockets() if (info.isGroupOwner) { startReceiverServer() } else { startSenderClient(info.groupOwnerAddress) } }
内容的提问来源于stack exchange,提问作者Bebikananda Waikhom
相关产品推荐
相关产品推荐

