21、WiFi与位置服务:为什么WiFi扫描需要位置权限

这个问题,我几乎每次培训都会被问到。

“我只是想扫个WiFi列表,为什么非要给我弹位置权限?”

嗯,说实话,我第一次接触这个限制时也挺懵的。后来踩过坑、翻过源码,才彻底搞明白——这背后其实是隐私保护的历史遗留问题。

21.1 为什么WiFi扫描和位置绑定在一起?

核心原因很简单:WiFi AP(接入点)的BSSID(MAC地址)本质上是一个位置标识符

你想想看,Google的街景车满世界跑,就是在收集WiFi信号和GPS坐标的对应关系。只要你的设备扫描到某个AP,就能通过云端数据库反推出你的大致位置。

所以,Android从6.0开始,就把WiFi扫描归入了“位置信息”的范畴。你不给位置权限,系统就不让你拿扫描结果。

核心逻辑:

  • WiFi AP的BSSID → 可映射到物理位置
  • 扫描结果包含BSSID → 属于位置数据
  • 访问位置数据 → 需要位置权限

我在项目中遇到过一位产品经理,坚持认为“扫WiFi和定位是两回事”。我只好打开设置里的WiFi扫描记录给他看——每次扫描,系统都会记录位置变化。他看完就沉默了。

21.2 Android 12+ 的粗略位置权限

Android 12之前,你要扫WiFi,必须申请ACCESS_FINE_LOCATION(精确位置)。这其实有点过度授权了——我只是想知道周围有哪些WiFi,并不需要知道我在哪条街上。

Google自己也意识到了这个问题。所以Android 12引入了粗略位置权限ACCESS_COARSE_LOCATION)。

我的建议:如果你的App只需要扫描WiFi列表来做网络切换、信号监测,不需要地图定位,那就只申请粗略位置权限。这样用户更容易接受,审核也更容易通过。

但注意,这里有个坑:

我曾经踩过的坑:在Android 12上只申请了粗略位置权限,结果WifiManager.startScan()返回了空列表。排查了半天才发现——某些厂商的定制ROM把粗略权限的WiFi扫描给阉割了。所以,建议在运行时检测扫描结果是否为空,如果为空,提示用户切换到精确位置模式

权限声明示例:

<!-- AndroidManifest.xml -->
<!-- Android 12+ 推荐使用粗略位置 -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

<!-- 如果需要精确位置(比如地图导航),再加这个 -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

运行时请求权限:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
    // Android 12+ 可以只请求粗略位置
    requestPermissions(
        arrayOf(Manifest.permission.ACCESS_COARSE_LOCATION),
        REQUEST_CODE
    )
} else {
    // 低版本必须请求精确位置
    requestPermissions(
        arrayOf(Manifest.permission.ACCESS_FINE_LOCATION),
        REQUEST_CODE
    )
}

21.3 WiFi扫描与隐私合规

这块是重灾区。我见过太多App因为WiFi扫描被下架了。

说白了,隐私合规就三条红线:

  1. 不能偷偷扫:必须在用户同意位置权限后才能开始扫描
  2. 不能一直扫:后台持续扫描会被系统限制,也会被用户投诉
  3. 不能乱传数据:扫描到的BSSID、SSID不能随意上传到自己的服务器

合规检查清单:

  • ✅ 扫描前检查权限是否已授予
  • ✅ 扫描频率控制在30秒以上一次
  • ✅ 扫描结果仅用于本地功能(如网络切换)
  • ❌ 不要将BSSID上传到第三方分析平台
  • ❌ 不要在后台无限制循环扫描

我记得有一次,一个合作方的App在后台每5秒扫一次WiFi,结果被Google Play直接下架。他们找我帮忙,我一看日志——好家伙,一天扫描了17万次。这已经不是技术问题了,是设计问题。

21.4 知识体系总览

下面这张图,是我自己整理的知识结构。每次带新人,我都会先让他们看这张图:

WiFi扫描与位置服务知识体系 WiFi扫描 为什么需要位置权限? BSSID → 位置映射 Android 12+ 粗略位置权限 ACCESS_COARSE_LOCATION 隐私合规三条红线 权限声明 + 运行时请求 扫描频率控制 厂商ROM兼容性问题 后台扫描限制

21.5 避坑指南

最后,分享几个我亲身踩过的坑:

  • 坑1:在Android 13上,即使有了位置权限,WifiManager.getScanResults()也可能返回空——因为系统限制了扫描频率。解决方案是监听SCAN_RESULTS_AVAILABLE_ACTION广播,不要主动轮询。
  • 坑2:有些国产手机(比如某米、某为)在后台会直接杀掉WiFi扫描线程。我曾经调试了一整天,最后发现是手机管家把App的定位权限给禁了。
  • 坑3:隐私合规审核时,Google会检查你的App是否在用户拒绝权限后仍然调用startScan()。如果检测到,直接拒审。所以一定要做权限拒绝后的降级处理。

我的小技巧:在开发阶段,可以在设置里开启“始终允许位置权限”,避免反复弹窗。但上线前一定要测试“拒绝权限”的场景,确保App不会崩溃。

好了,这一章的内容就到这里。WiFi扫描和位置权限的关系,说白了就是“你扫到的每个AP,都在告诉别人你在哪”。理解了这一点,后面的权限申请、隐私合规就都顺理成章了。


公众号:蓝海资料掘金营,微信deep3321