Android开发:Wifi扫描器扫描结果无法在ListView中展示问题求助
针对WiFi扫描结果无法显示在ListView的排查与修复
你的代码基础逻辑通顺,运行不报错、Toast正常弹出,问题全部出在系统版本适配的静默规则上,因为不会触发崩溃所以很难排查:
核心问题点
- 定位权限缺失导致扫描结果静默返回空
从Android 6.0(API 23)开始,WiFi扫描结果属于关联位置信息的敏感数据,未授予ACCESS_FINE_LOCATION动态权限的应用,调用wifiManager.getScanResults()会直接返回空列表,不会抛出任何异常。 - WiFi自动开关接口失效导致网络未实际开启
你代码里用的wifiManager.setWifiEnabled(true)从Android 10(API 29)开始完全被系统禁用,应用调用后只会静默失败,不会真的打开WiFi。如果你测试时WiFi本来是关闭状态,实际根本没进入可扫描的状态,自然拿不到任何结果。 - 广播回调的结果有效性未校验
从Android 10开始,系统返回的扫描广播会携带EXTRA_RESULTS_UPDATED标记,代表本次回调是否是新的扫描结果。如果因为频率限制返回了旧缓存的空数据,你没有做校验就直接读取,会拿到空列表。 - 刷新时机不合理
你在遍历每一条扫描结果时都调用arrayAdapter.notifyDataSetChanged(),虽然逻辑上能触发更新,但如果扫描列表加载慢,可能出现列表先显示空、再逐条加载的异常感,甚至部分机型因为多次重复触发刷新导致列表渲染异常。
可直接套用的修复方案
- 先在
AndroidManifest.xml中声明所需基础权限:<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> - 在Activity中增加动态权限申请逻辑,等用户授予定位权限之后,再触发扫描流程;如果权限被拒绝,直接弹出Toast提示,不要跳过权限校验直接调用扫描接口。
- 替换自动开WiFi的逻辑:删掉
wifiManager.setWifiEnabled(true)的代码,检测到WiFi关闭时,弹出引导框让用户手动跳转系统设置打开WiFi,适配高版本的权限限制。 - 优化广播接收器的处理逻辑:
BroadcastReceiver wifiReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { // 校验本次回调是否为新的扫描结果 boolean isScanSuccess = intent.getBooleanExtra(WifiManager.EXTRA_RESULTS_UPDATED, false); if (isScanSuccess) { results = wifiManager.getScanResults(); arrayList.clear(); for (ScanResult scanResult : results) { // 过滤无SSID的占位扫描项 if (scanResult.SSID != null && !scanResult.SSID.trim().isEmpty()) { arrayList.add(scanResult.SSID + " | 加密方式: " + scanResult.capabilities); } } // 所有数据加载完成后统一刷新一次列表 arrayAdapter.notifyDataSetChanged(); } // 扫描完成后立刻注销接收器,避免内存泄漏 unregisterReceiver(this); } }; - 调整扫描触发时机:不要在
onCreate刚执行完就立刻调用第一次扫描,等页面完全渲染完成、权限获取到位、广播接收器绑定稳定后,再触发startScan(),避免因为生命周期时序问题错过广播回调。
额外注意:Android从9.0开始对前台应用的扫描频率做了限制,每2分钟最多允许调用4次
startScan(),短时间内频繁点击扫描按钮会被系统静默拦截,不会返回结果,测试时注意控制点击间隔。
内容的提问来源于stack exchange,提问作者Dirk
相关产品推荐
相关产品推荐

