为何通过Android WifiManager获取到的ScanResult数量为0?
解决Android WiFi扫描结果获取失败的问题
看起来你在Android WiFi扫描这块卡壳了,我之前也踩过不少坑,帮你梳理下关键问题和解决方案:
1. 权限必须配全且动态申请
Android 6.0之后,WiFi扫描的权限要求变得严格,位置权限是硬性前提(因为扫描结果可能关联地理位置),而且光在Manifest里声明没用,必须动态申请。
首先在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" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <!-- Android 12 及以上版本额外需要 --> <uses-permission android:name="android.permission.ACCESS_WIFI_SCAN_RESULTS" />
然后你的getWifiPermissions()方法要正确处理动态权限请求,比如:
private static final int WIFI_PERM_REQUEST_CODE = 1001; private void getWifiPermissions() { String[] permissions; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { permissions = new String[]{ Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_WIFI_SCAN_RESULTS }; } else { permissions = new String[]{ Manifest.permission.ACCESS_FINE_LOCATION }; } if (ContextCompat.checkSelfPermission(this, permissions[0]) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, permissions, WIFI_PERM_REQUEST_CODE); } else { // 权限已获取,直接启动扫描 initWifi(); } }
2. 扫描流程要异步处理,靠广播接收结果
WiFi扫描是异步操作,不能调用startScan()后立刻去拿结果,必须注册广播接收器监听扫描完成的通知(Android 8.0之后静态广播失效,必须动态注册):
private WifiManager wifiManager; private BroadcastReceiver wifiScanReceiver; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE); initWifiSpinner(); // 注册扫描结果广播接收器 wifiScanReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { boolean isScanSuccess = intent.getBooleanExtra(WifiManager.EXTRA_RESULTS_UPDATED, false); if (isScanSuccess) { handleScanResults(); } else { Toast.makeText(MainActivity.this, "WiFi扫描失败", Toast.LENGTH_SHORT).show(); } } }; IntentFilter filter = new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION); registerReceiver(wifiScanReceiver, filter); } // 处理扫描结果 private void handleScanResults() { List<ScanResult> scanResults = wifiManager.getScanResults(); // 这里把结果填充到你的Spinner里 initWifiSpinner(scanResults); } // 启动扫描的方法 private void initWifi() { // 先检查WiFi是否开启 if (!wifiManager.isWifiEnabled()) { wifiManager.setWifiEnabled(true); // 可以加个延迟再扫描,避免WiFi刚开启就扫不到 new Handler(Looper.getMainLooper()).postDelayed(() -> { wifiManager.startScan(); }, 1000); } else { wifiManager.startScan(); } } // 别忘了在页面销毁时注销广播 @Override protected void onDestroy() { super.onDestroy(); if (wifiScanReceiver != null) { unregisterReceiver(wifiScanReceiver); } }
3. 权限申请结果的回调不能漏
你代码里的onPos...应该是onRequestPermissionsResult吧?必须在这个方法里处理用户的权限选择,只有同意后才能启动扫描:
@Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == WIFI_PERM_REQUEST_CODE) { boolean allPermissionsGranted = true; for (int result : grantResults) { if (result != PackageManager.PERMISSION_GRANTED) { allPermissionsGranted = false; break; } } if (allPermissionsGranted) { initWifi(); } else { Toast.makeText(this, "需要授予权限才能扫描WiFi", Toast.LENGTH_SHORT).show(); } } }
4. 高版本系统的特殊限制
- Android 10+:如果用户关闭了系统位置服务,即使授予了位置权限,也无法获取扫描结果,需要提示用户打开位置服务。
- Android 12+:系统会限制后台频繁扫描WiFi,所以尽量在前台执行扫描操作。
你可以对照上面的步骤检查你的代码,大概率是权限申请不完整、没注册广播接收器,或者没等扫描完成就去拿结果导致的问题。
内容的提问来源于stack exchange,提问作者user3668129
相关产品推荐
相关产品推荐

