Android新版本(10/12)WiFi扫描失败问题求助
解决Android WiFi扫描失败问题
针对你遇到的WiFi扫描始终失败的问题,结合Android 10和12的权限及系统限制,从以下几个关键方向排查修复:
1. 确保权限配置完整
在AndroidManifest.xml中添加必要权限:
<!-- 基础WiFi权限 --> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /> <!-- 位置权限(WiFi扫描依赖位置服务) --> <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.NEARBY_WIFI_DEVICES" />
注意:
NEARBY_WIFI_DEVICES是Android 12新增权限,若需获取WiFi热点的SSID和BSSID,仍需配合位置权限使用。
2. 动态申请危险权限
位置权限属于危险权限,必须在运行时动态申请,不能仅依赖Manifest配置。调用扫描前先完成权限校验:
// 定义适配不同版本的权限数组 val requiredPermissions = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { arrayOf( Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.NEARBY_WIFI_DEVICES ) } else { arrayOf(Manifest.permission.ACCESS_FINE_LOCATION) } // 检查并申请权限 if (ContextCompat.checkSelfPermission( localContext, requiredPermissions[0] ) != PackageManager.PERMISSION_GRANTED ) { ActivityResultContracts.RequestMultiplePermissions().launch(requiredPermissions) } else { // 权限已授予,执行扫描 checkWifiChannels(localContext) }
3. 强制检查位置服务状态
Android 10及以上,即使授予位置权限,若系统位置服务未开启,WiFi扫描也会失败。添加检查逻辑:
private fun isLocationEnabled(context: Context): Boolean { val locationManager = context.getSystemService(Context.LOCATION_SERVICE) as LocationManager return locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) || locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER) }
调用扫描前判断,未开启则引导用户打开:
if (!isLocationEnabled(localContext)) { val intent = Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS) localContext.startActivity(intent) return }
4. 修正扫描逻辑的核心问题
你的代码存在两个关键缺陷:
- 广播注册后未注销,会导致内存泄漏,需在合适时机(如Composable的
DisposableEffect)注销广播 startScan()返回false不代表扫描彻底失败,Android 10之后系统可能延迟处理请求,应等待广播回调结果,而非直接判定失败
修改后的扫描逻辑及Composable调用示例:
@Composable fun WifiScannerScreen() { val localContext = LocalContext.current var scanResult by remember { mutableStateOf<List<ScanResult>>(emptyList()) } DisposableEffect(Unit) { val wifiManager = localContext.applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager val wifiScanReceiver = object : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { val success = intent.getBooleanExtra(WifiManager.EXTRA_RESULTS_UPDATED, false) if (success) { scanResult = wifiManager.scanResults Toast.makeText(localContext, "扫描成功", Toast.LENGTH_SHORT).show() } else { scanResult = wifiManager.scanResults Toast.makeText(localContext, "扫描未更新,使用旧结果", Toast.LENGTH_SHORT).show() } } } val intentFilter = IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION) localContext.registerReceiver(wifiScanReceiver, intentFilter) // 执行扫描(先校验位置服务) if (isLocationEnabled(localContext)) { wifiManager.startScan() } // 组件销毁时注销广播 onDispose { localContext.unregisterReceiver(wifiScanReceiver) } } // 展示扫描结果 LazyColumn { items(scanResult) { result -> Text("SSID: ${result.SSID}, 信号强度: ${result.level}") } } }
5. 规避扫描频率限制
Android 8.0及以上系统对WiFi扫描频率有严格管控:
- 后台应用每分钟最多扫描4次
- 前台应用每2分钟最多扫描4次
短时间内重复调用startScan()会被系统直接拒绝,导致扫描失败。
6. 模拟器测试注意事项
Android 12模拟器默认可能未开启WiFi功能,需在模拟器设置中手动打开;优先使用真实设备测试,模拟器的WiFi模拟环境存在兼容性问题。
内容的提问来源于stack exchange,提问作者Bendzsike
相关产品推荐
相关产品推荐

