Android Wifi-Direct刷新按钮触发discoverPeers始终进入onFailure问题
解决Wifi-Direct discoverPeers失败的问题
1. 补充必要权限
Wifi-Direct运行需要多组权限支持,先在AndroidManifest.xml中添加以下配置:
<!-- 基础Wifi控制权限 --> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /> <!-- 定位权限(Android 6+强制要求,Wifi-Direct扫描依赖定位服务) --> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <!-- Android 12+蓝牙权限(Wifi-Direct设备发现依赖蓝牙) --> <uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" /> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30" /> <uses-permission android:name="android.permission.BLUETOOTH_SCAN" /> <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" /> <!-- 声明设备支持Wifi-Direct --> <uses-feature android:name="android.hardware.wifi.direct" android:required="true" />
同时在代码中添加动态权限申请逻辑(适配Android 6及以上版本):
private static final int PERMISSIONS_REQUEST_CODE = 1001; private String[] requiredPermissions = { Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.CHANGE_WIFI_STATE, Manifest.permission.BLUETOOTH_SCAN }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_wifi_login_screen); // 先检查并申请必要权限 if (!hasAllPermissions()) { requestPermissions(requiredPermissions, PERMISSIONS_REQUEST_CODE); } // 原有的初始化代码... } // 检查是否所有权限已授予 private boolean hasAllPermissions() { for (String perm : requiredPermissions) { if (ContextCompat.checkSelfPermission(this, perm) != PackageManager.PERMISSION_GRANTED) { return false; } } return true; } // 权限申请结果回调 @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == PERMISSIONS_REQUEST_CODE) { boolean allGranted = true; for (int result : grantResults) { if (result != PackageManager.PERMISSION_GRANTED) { allGranted = false; break; } } if (!allGranted) { Toast.makeText(this, "需要授予所有权限才能使用Wifi-Direct功能", Toast.LENGTH_LONG).show(); finish(); } } }
2. 修复Channel初始化与状态监听
初始化WifiP2pManager.Channel时,不要传入null作为ChannelListener,添加通道断开监听以便及时重建:
mWifiP2pChannel = mWifiP2pManager.initialize(this, getMainLooper(), new WifiP2pManager.ChannelListener() { @Override public void onChannelDisconnected() { // 通道断开时重新初始化 mWifiP2pChannel = mWifiP2pManager.initialize(wifiLoginScreen.this, getMainLooper(), this); Toast.makeText(wifiLoginScreen.this, "Wifi-Direct通道已断开,正在重连", Toast.LENGTH_SHORT).show(); } });
3. 避免重复注册广播接收器
当前代码在onCreate和onResume重复注册广播接收器,会导致系统异常,修改为仅在onResume注册、onPause注销,并添加注册状态标记:
private boolean isReceiverRegistered = false; @Override protected void onResume() { super.onResume(); if (!isReceiverRegistered) { IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION); intentFilter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION); registerReceiver(mReceiver, intentFilter); isReceiverRegistered = true; } } @Override protected void onPause() { super.onPause(); if (isReceiverRegistered) { unregisterReceiver(mReceiver); isReceiverRegistered = false; } }
同时删除onCreate中的registerReceiver代码。
4. 优化discoverPeers调用逻辑
- 增加防抖机制,避免短时间内重复触发搜索;
- 在失败回调中根据错误码返回具体提示,方便排查问题:
private long lastDiscoverTime = 0; private static final long DISCOVER_DELAY = 5000; // 5秒冷却时间 refreshButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { long currentTime = System.currentTimeMillis(); if (currentTime - lastDiscoverTime < DISCOVER_DELAY) { Toast.makeText(wifiLoginScreen.this, "请稍后再尝试搜索", Toast.LENGTH_SHORT).show(); return; } lastDiscoverTime = currentTime; if (mWifiDirectEnabled) { mWifiP2pManager.discoverPeers(mWifiP2pChannel, new WifiP2pManager.ActionListener() { @Override public void onSuccess() { Toast.makeText(wifiLoginScreen.this, "正在搜索可用设备...", Toast.LENGTH_SHORT).show(); } @Override public void onFailure(int reason) { String errorMsg; switch (reason) { case WifiP2pManager.P2P_UNSUPPORTED: errorMsg = "当前设备不支持Wifi-Direct"; break; case WifiP2pManager.BUSY: errorMsg = "系统正忙,请稍后再试"; break; case WifiP2pManager.ERROR: errorMsg = "搜索失败:系统内部错误"; break; default: errorMsg = "搜索失败,未知原因"; } Toast.makeText(wifiLoginScreen.this, errorMsg, Toast.LENGTH_SHORT).show(); } }); } else { Toast.makeText(wifiLoginScreen.this, "Wifi-Direct未启用", Toast.LENGTH_SHORT).show(); } } });
5. 修正设备过滤逻辑(可选)
当前代码用device.deviceName.contains(ssid)过滤设备,但Wifi-Direct的设备名称不一定包含当前连接的SSID,这会导致即使发现设备也无法显示。建议先注释过滤逻辑,测试是否能正常获取设备列表,再根据需求调整:
@Override public void onPeersAvailable(WifiP2pDeviceList peers) { mPeersList.clear(); for (WifiP2pDevice device : peers.getDeviceList()) { // 先注释过滤逻辑,测试设备发现功能 // if (device.deviceName.contains(ssid)) { mPeersList.add(device.deviceName + " (" + device.deviceAddress + ")"); // } } mPeersAdapter.notifyDataSetChanged(); }
6. 设备环境检查
- 确保设备已开启Wifi(Wifi-Direct依赖Wifi硬件,但无需连接热点);
- 关闭省电模式(部分设备会在省电模式下禁用Wifi-Direct);
- 确保两台设备距离在Wifi信号覆盖范围内;
- 部分设备需开启蓝牙才能使用Wifi-Direct,检查蓝牙状态。
内容的提问来源于stack exchange,提问作者MORAN
相关产品推荐
相关产品推荐

