Android WiFi管理器应用自动扫描失效:多次扫描后返回旧列表
解决Android WiFi重复扫描后无法获取新网络的问题
问题分析
你的代码存在几个核心问题,导致扫描几次后无法获取新网络:
- 广播接收器生命周期混乱:每次扫描完成后在
onReceive中注销接收器,但后续扫描是通过Handler调度的,此时接收器已失效,无法接收新的扫描结果广播,只能获取系统缓存的旧列表。 - 重复创建Adapter:每次扫描都新建
WifiAdapter,不仅浪费资源,还可能引发列表刷新异常。 - 扫描频率触发系统限制:Android系统对WiFi扫描频率有管控,过于频繁的扫描(5秒间隔)会被系统限制,返回缓存结果。
修复方案
1. 统一管理广播接收器的注册/注销
在页面生命周期(onResume/onPause)中统一处理接收器的注册与注销,确保扫描时接收器始终处于活跃状态。
2. 优化扫描调度逻辑
避免重复调度扫描任务,同时调整扫描间隔至10秒以上(规避系统频率限制),并在页面销毁时停止扫描任务,防止内存泄漏。
3. 复用Adapter更新数据
每次获取新扫描结果后,直接更新Adapter的数据源并调用notifyDataSetChanged(),而非重建Adapter。
4. 确保权限完整性
除ACCESS_FINE_LOCATION外,Android 12+需额外申请ACCESS_COARSE_LOCATION;若需后台扫描,还需ACCESS_BACKGROUND_LOCATION权限,且必须动态申请。
修改后的完整代码示例
首先定义Activity成员变量:
private WifiManager wifiManager; private WifiScanReceiver wifiReceiver; private Handler scanningHandler = new Handler(Looper.getMainLooper()); private Runnable scanRunnable; private List<ScanResult> wifiScanList = new ArrayList<>(); private WifiAdapter wifiAdapter; private String connected_ssid; private ListView all_wifi; // 你的WiFi列表控件
实现生命周期与扫描逻辑:
@Override protected void onResume() { super.onResume(); // 注册广播接收器 if (wifiReceiver == null) { wifiReceiver = new WifiScanReceiver(); } registerReceiver(wifiReceiver, new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)); // 启动扫描任务 startWifiScanTask(); } @Override protected void onPause() { super.onPause(); // 停止扫描任务 stopWifiScanTask(); // 注销广播接收器 try { unregisterReceiver(wifiReceiver); } catch (Exception e) { e.printStackTrace(); } } private void startWifiScanTask() { if (scanRunnable == null) { scanRunnable = new Runnable() { @Override public void run() { // 检查权限 if (ActivityCompat.checkSelfPermission(WifiNetworkList.this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) { scanningHandler.postDelayed(this, 5000); return; } // 启动扫描 boolean scanStarted = wifiManager.startScan(); if (!scanStarted) { Log.e("WifiScan", "扫描启动失败,可能触发系统限制"); } // 10秒后调度下一次扫描 scanningHandler.postDelayed(this, 10000); } }; } // 首次延迟1秒启动扫描 scanningHandler.postDelayed(scanRunnable, 1000); } private void stopWifiScanTask() { if (scanRunnable != null) { scanningHandler.removeCallbacks(scanRunnable); scanRunnable = null; } } class WifiScanReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { if (!WifiManager.SCAN_RESULTS_AVAILABLE_ACTION.equals(intent.getAction())) { return; } // 检查权限 if (ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) { return; } // 获取最新扫描结果 List<ScanResult> newScanResults = wifiManager.getScanResults(); if (newScanResults != null) { wifiScanList.clear(); wifiScanList.addAll(newScanResults); // 排序处理 List<ScanResult> sortedList = sortedwifilist(wifiScanList); // 更新Adapter if (wifiAdapter == null) { wifiAdapter = new WifiAdapter(WifiNetworkList.this, sortedList, connected_ssid); all_wifi.setAdapter(wifiAdapter); } else { wifiAdapter.updateData(sortedList, connected_ssid); wifiAdapter.notifyDataSetChanged(); } } } }
在WifiAdapter中添加数据更新方法:
public void updateData(List<ScanResult> newList, String connectedSsid) { this.wifiList = newList; this.connected_ssid = connectedSsid; }
额外注意事项
- 系统扫描限制:Android 10+后台应用每2分钟最多允许4次扫描,前台应用也有频率管控,建议扫描间隔不低于10秒。
- 结果去重:系统返回的扫描结果可能包含重复SSID,可在
sortedwifilist方法中保留每个SSID信号最强的条目。
内容的提问来源于stack exchange,提问作者Qasim Malik
相关产品推荐
相关产品推荐

