29、WiFi优化:WiFi扫描频率、网络切换策略、热点检测、WiFi RTT定位
WiFi优化这个话题,说实话,在Android系统性能优化里属于「看似简单,实则坑多」的那一类。很多开发者觉得WiFi嘛,能连上就行。但真正做过系统级优化的工程师都知道,WiFi模块要是没调好,用户的续航、网络体验、甚至定位精度都会出问题。
我个人习惯把WiFi优化拆成四个维度来看:扫描频率、网络切换、热点检测、以及RTT定位。咱们一个一个聊。
WiFi扫描频率:别让手机像个无头苍蝇
WiFi扫描是耗电大户,这一点做过功耗优化的朋友应该深有体会。我曾在某个项目里遇到过,用户反馈手机待机一晚上掉电20%,查来查去,罪魁祸首就是WiFi扫描频率太高——每10秒扫一次,CPU根本没法深度休眠。
Android系统默认的WiFi扫描策略其实已经做了权衡:
- 屏幕亮着且连接WiFi:扫描间隔约60秒
- 屏幕亮着但未连接WiFi:扫描间隔约30秒
- 屏幕熄灭:扫描间隔拉长到120秒以上,甚至停止扫描
但问题是,很多第三方应用会通过WifiManager.startScan()主动发起扫描。你想想看,如果装了十几个应用,每个都来扫一下,那功耗能不高吗?
优化建议:
- 在系统层限制第三方应用的扫描频率,比如每分钟最多允许发起一次扫描
- 使用
WifiManager.SCAN_ONLY_WITH_WIFI_OFF模式,避免在WiFi关闭时仍被唤醒扫描 - 利用
WifiManager.WIFI_STATE_CHANGED_ACTION广播,动态调整扫描策略
// 限制扫描频率的示例代码
public class ScanThrottleHelper {
private static final long MIN_SCAN_INTERVAL_MS = 30_000; // 30秒
private long lastScanTime = 0;
public boolean canStartScan() {
long now = SystemClock.elapsedRealtime();
if (now - lastScanTime < MIN_SCAN_INTERVAL_MS) {
return false; // 太频繁了,拒绝
}
lastScanTime = now;
return true;
}
}
网络切换策略:别让用户感觉「断网了」
网络切换,说白了就是手机在WiFi和移动数据之间做选择。我见过最糟糕的情况是:用户从家里走到电梯口,WiFi信号已经弱到不行了,但手机还死死抓着不放,结果网页死活打不开。
Android系统里有个关键参数叫WifiManager.THRESHOLD_QUALITY,它决定了什么时候触发网络切换。默认值一般是-70dBm到-80dBm之间。但说实话,这个阈值不能一刀切。
| 信号强度 | 等级 | 建议行为 |
|---|---|---|
| -50dBm 以上 | 优秀 | 保持WiFi连接 |
| -60dBm ~ -70dBm | 良好 | 正常使用,开始监测 |
| -70dBm ~ -80dBm | 一般 | 准备切换,评估移动网络 |
| -80dBm 以下 | 差 | 立即切换,避免丢包 |
我的经验:不要只看信号强度,还要看链路质量。我曾经遇到过信号强度-65dBm但丢包率高达30%的情况。建议结合WifiInfo.getRxSuccessRate()和WifiInfo.getTxSuccessRate()做综合判断。
热点检测:别让用户连上「假WiFi」
热点检测,嗯,这里要注意。Android从9.0开始引入了WifiNetworkSuggestion机制,但很多厂商还是自己写了一套热点检测逻辑。我见过最离谱的是,某个ROM把隔壁奶茶店的WiFi识别成了「安全热点」,结果用户连上去后,所有流量都被劫持了。
热点检测的核心逻辑其实就三点:
- SSID白名单:系统预置的可信热点列表
- 证书验证:企业级热点需要验证CA证书
- 行为分析:检测热点是否有DNS劫持、ARP欺骗等行为
避坑指南:我曾经在某个项目里,把热点检测做得太严格了,结果用户连自家路由器都提示「不安全」。后来发现是路由器固件太老,不支持WPA3。所以建议在检测到不兼容时,给出降级提示而不是直接拒绝连接。
WiFi RTT定位:精度能到米级
WiFi RTT(Round Trip Time)定位,是Android 9引入的新特性。它不像传统RSSI定位那样靠信号强度估算距离,而是直接测量信号往返时间,精度能到1-2米。
我参与过一个商场导航项目,就是用WiFi RTT做的室内定位。效果确实比蓝牙要好,但有个前提——需要支持802.11mc的路由器。目前市面上支持的路由器还不多,这是个硬伤。
// WiFi RTT 定位示例
public class RttLocationHelper {
private WifiRttManager rttManager;
public void startRanging(List<ScanResult> apList) {
RangingRequest.Builder builder = new RangingRequest.Builder();
for (ScanResult ap : apList) {
builder.addAccessPoint(ap);
}
RangingRequest request = builder.build();
rttManager.startRanging(request, Runnable::run, new RangingResultCallback() {
@Override
public void onRangingResults(List<RangingResult> results) {
for (RangingResult result : results) {
int distanceMm = result.getDistanceMm(); // 距离,单位毫米
int rssi = result.getRssi();
// 用距离做三角定位
}
}
@Override
public void onRangingFailure(int code) {
// 处理失败情况
}
});
}
}
关键点:WiFi RTT定位需要至少3个AP才能做三角定位。而且AP的位置要固定,不能是移动热点。另外,RTT测量结果会受到多径效应影响,建议做卡尔曼滤波平滑处理。
知识体系总览
下面这张图,是我自己整理的WiFi优化知识体系。你可以把它当作一个检查清单,看看自己的项目里哪些环节还没做到位。
说实话,WiFi优化没有银弹。每个项目的情况都不一样,有的偏重功耗,有的偏重体验,有的偏重定位精度。我的建议是:先做数据采集,看看你的用户场景里,WiFi相关的痛点到底是什么,然后再对症下药。
好了,这一章的内容就到这里。如果你在实际项目中遇到了WiFi优化的具体问题,欢迎随时交流。
公众号:蓝海资料掘金营,微信deep3321