You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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处理...
    }
}

五、传输会话结束后的完整切换流程

当一次传输完成后,严格执行以下步骤:

  1. 调用disconnect方法,等待断开完成回调
  2. 断开完成后,调用prepareForReconnection发起设备发现
  3. 从更新后的设备列表中选择目标设备,调用connectToPeer并传入新的isSender参数
  4. 在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 09:50:43