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

Android 6及以上系统获取可用WiFi列表失败的问题求助

解决Android 6+无法获取WiFi扫描列表的问题

首先,你的代码在Android 6以下设备正常,但高版本失效,核心原因是Android 6.0(API 23)开始的运行时权限模型,加上后续版本对WiFi扫描新增的位置服务强制要求和扫描限制。我来帮你一步步排查和修复:

1. 必须开启位置服务(关键!)

从Android 6.0开始,系统要求获取WiFi扫描结果时,不仅要有位置权限,还必须开启设备的位置服务(GPS或网络定位)。哪怕你申请了ACCESS_FINE_LOCATION/ACCESS_COARSE_LOCATION,如果用户关闭了位置服务,getScanResults()会返回空列表。

代码中添加位置服务检查

在权限授予后,先检查位置服务是否开启,如果没开启,引导用户去设置打开:

// 在onPermissionGranted方法中添加
LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
boolean isLocationEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) 
                            || locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
if (!isLocationEnabled) {
    // 引导用户开启位置服务
    Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
    startActivityForResult(intent, 1001);
} else {
    // 继续WiFi扫描流程
    startWifiScan();
}

然后在onActivityResult中处理用户返回后的逻辑:

@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == 1001) {
        // 用户返回后,重新检查位置服务并启动扫描
        LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
        boolean isLocationEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) 
                                    || locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
        if (isLocationEnabled) {
            startWifiScan();
        } else {
            Toast.makeText(this, "位置服务未开启,无法获取WiFi列表", Toast.LENGTH_SHORT).show();
        }
    }
}

// 把原来的WiFi扫描逻辑抽成方法
private void startWifiScan() {
    mainWifi = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
    if (!mainWifi.isWifiEnabled()) {
        Toast.makeText(getApplicationContext(), "wifi已关闭,正在开启...", Toast.LENGTH_LONG).show();
        mainWifi.setWifiEnabled(true);
    }
    receiverWifi = new WifiReceiver();
    registerReceiver(receiverWifi, new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
    // 主动触发扫描,并可以同步尝试获取结果(避免广播延迟)
    boolean scanStarted = mainWifi.startScan();
    if (scanStarted) {
        // 可以先尝试获取一次结果,可能之前的扫描缓存存在
        List<ScanResult> tempList = mainWifi.getScanResults();
        if (tempList != null && !tempList.isEmpty()) {
            updateWifiList(tempList);
        }
    } else {
        Toast.makeText(this, "扫描启动失败,请检查权限和WiFi状态", Toast.LENGTH_SHORT).show();
    }
}

// 抽离更新列表的方法,复用
private void updateWifiList(List<ScanResult> wifiList) {
    sb = new StringBuilder();
    sb.append("\n 可用WiFi数量:"+wifiList.size()+"\n\n");
    for(int i = 0; i < wifiList.size(); i++){
        sb.append((i+1) + ". ");
        sb.append(wifiList.get(i).toString());
        sb.append("\n\n");
        Log.i("LOGO_WIFI", sb.toString());
    }
    // 这里可以把sb的内容显示到UI上
}

2. 权限适配不同Android版本

  • Android 6-9:需要ACCESS_FINE_LOCATION或ACCESS_COARSE_LOCATION,同时要在运行时申请。
  • Android 10+(API 29):必须申请ACCESS_FINE_LOCATION,ACCESS_COARSE_LOCATION无法获取WiFi扫描结果。
  • Android 12+(API 31):新增ACCESS_WIFI_SCAN权限,需要在清单文件中声明,并且运行时申请(如果是targetSdkVersion 31+)。

清单文件补充权限

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<!-- Android 12+ 新增 -->
<uses-permission android:name="android.permission.ACCESS_WIFI_SCAN"
    android:minSdkVersion="31" />
<!-- 可选:如果需要网络定位 -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

3. 处理广播接收的可靠性问题

  • Android 8.0(API 26)开始,静态注册的广播接收器会受到限制,但你用的是动态注册,没问题,但要注意在onDestroy中注销接收器,避免内存泄漏:
@Override
protected void onDestroy() {
    super.onDestroy();
    if (receiverWifi != null) {
        unregisterReceiver(receiverWifi);
    }
}
  • 有时候SCAN_RESULTS_AVAILABLE_ACTION广播可能不会触发(比如系统限制扫描频率),可以考虑使用WifiManager.startScan()的返回值判断扫描是否启动,同时主动调用getScanResults()获取结果,不要完全依赖广播。

4. 后台扫描限制(Android 8+)

如果你的App在后台,Android 8+会限制WiFi扫描的频率(每分钟最多4次),如果是前台App则不受此限制。所以确保测试时App处于前台状态。


修改后的WifiReceiver可以简化,直接调用更新方法:

class WifiReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context c, Intent intent) {
        if (WifiManager.SCAN_RESULTS_AVAILABLE_ACTION.equals(intent.getAction())) {
            List<ScanResult> wifiList = mainWifi.getScanResults();
            if (wifiList != null) {
                updateWifiList(wifiList);
            }
        }
    }
}

最后,测试时记得:

  • 确认位置服务已开启
  • 确认App已授予位置权限
  • 确保App处于前台状态

内容的提问来源于stack exchange,提问作者Ehsan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 03:30:54