28、位置服务省电:Fused Location Provider、Geofence API、位置更新策略
说到位置服务,很多同学第一反应就是「费电」。确实,GPS一开,电量哗哗往下掉。但说实话,大部分场景根本不需要那么高的精度。我做过一个外卖App,最开始直接调GPS,结果用户骂声一片——手机烫得像暖手宝。
后来我换了思路:能用基站定位就别开GPS,能隔5分钟更新就别每秒刷新。位置服务省电的核心,说白了就四个字——按需索取。
Fused Location Provider:Google的「智能定位」
Fused Location Provider(FLP)是Google Play服务里的位置API。它最大的好处是:自动帮你选最优定位源。GPS、Wi-Fi、基站、蓝牙,哪个省电用哪个,哪个精度够用哪个。
我个人习惯,只要不是导航类App,一律用FLP。为什么?因为它会做「融合」——比如你在室内,GPS信号弱,它自动切到Wi-Fi定位;你走到室外,它再切回GPS。整个过程对开发者透明,你只管设参数就行。
核心要点: FLP 不是「一个定位源」,而是一个「定位源调度器」。它帮你平衡精度和功耗。
FLP 的基本用法
// 创建定位请求
val locationRequest = LocationRequest.Builder(
Priority.PRIORITY_BALANCED_POWER_ACCURACY, // 平衡精度和功耗
10000L // 更新间隔:10秒
).apply {
setMinUpdateIntervalMillis(5000L) // 最快5秒更新一次
setMaxUpdateDelayMillis(30000L) // 最大延迟30秒
}.build()
// 获取FusedLocationProviderClient
val fusedClient = LocationServices.getFusedLocationProviderClient(context)
// 请求位置更新
fusedClient.requestLocationUpdates(
locationRequest,
locationCallback,
Looper.getMainLooper()
)
这里有个坑:PRIORITY_BALANCED_POWER_ACCURACY 对应的是「百米级」精度,大约100米。如果你做的是天气App,这个精度完全够用。我曾经见过有人做新闻App也开 PRIORITY_HIGH_ACCURACY,那纯属浪费电。
我的建议: 先评估你的业务场景。显示天气?用BALANCED。记录运动轨迹?用HIGH_ACCURACY。找附近餐厅?BALANCED就够了。
Geofence API:围栏里的省电哲学
Geofence(地理围栏)是另一种省电思路:不持续定位,只在「进出某个区域」时触发。比如你做一个「到店提醒」功能,用户离店铺500米时弹通知。如果用持续定位,电量撑不过半天。但用Geofence,系统只在边界检测时唤醒一下,功耗低得多。
我记得有个项目是做商场导购,用户进商场就推送优惠券。最开始用FLP轮询,结果用户反馈「手机半天就没电了」。后来换成Geofence,电量问题直接解决。
Geofence 的创建步骤
// 1. 定义围栏
val geofence = Geofence.Builder()
.setRequestId("shop_001")
.setCircularRegion(
39.9042, // 纬度
116.4074, // 经度
100.0f // 半径:100米
)
.setExpirationDuration(Geofence.NEVER_EXPIRE)
.setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER)
.build()
// 2. 创建请求
val geofenceRequest = GeofencingRequest.Builder()
.addGeofence(geofence)
.setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER)
.build()
// 3. 注册
val geofencingClient = LocationServices.getGeofencingClient(context)
geofencingClient.addGeofences(geofenceRequest, geofencePendingIntent)
注意: Geofence 的半径不要小于100米。太小的围栏会导致频繁触发,反而更费电。我见过有人设50米半径,结果用户路过地铁站时疯狂弹通知——因为GPS漂移。
位置更新策略:省电的「三板斧」
位置更新策略,说白了就是回答三个问题:多久更新一次?精度要多高?什么时候可以停?
我总结了一套「省电三板斧」,你可以直接套用:
- 降低频率:能10秒一次就别1秒一次。大部分场景下,5-10秒的间隔完全够用。
- 降低精度:能接受100米就别要10米。GPS每提高一个精度等级,功耗翻倍。
- 及时停止:用户切到后台、或者已经离开目标区域,立刻停止定位。别让定位服务在后台空转。
不同场景的推荐配置
| 场景 | 优先级 | 更新间隔 | 备注 |
|---|---|---|---|
| 天气/新闻 | BALANCED | 5-10分钟 | 甚至可以用被动监听 |
| 外卖/打车 | BALANCED | 10-30秒 | 用户下单后提高频率 |
| 运动轨迹 | HIGH_ACCURACY | 1-5秒 | 跑步/骑行场景 |
| 导航 | HIGH_ACCURACY | 1秒 | 必须持续定位 |
一个小技巧: 用
removeLocationUpdates() 及时清理。很多开发者只记得「请求」,不记得「释放」。Activity onPause 时就应该停止定位,onResume 时再恢复。
知识体系图:位置服务省电的核心逻辑
避坑指南:我踩过的几个坑
- 不要同时开多个定位请求:我曾经在一个页面里同时调了FLP和原生GPS,结果电量直接翻倍。一个App里,只保留一个定位客户端。
- Geofence 数量别太多:系统对Geofence数量有限制(通常100个)。超过限制,后面的围栏不会触发。我做过一个巡检App,设了200个围栏,结果一半没生效。
- 别忘了处理权限:Android 10以后,后台定位权限需要单独申请。很多开发者只申请了前台权限,结果App切到后台就收不到位置更新。
- 测试时别用模拟器:模拟器的位置数据是「假」的,测不出真实功耗。我建议用真机,插上电池监控工具,看电流变化。
一句话总结: 位置服务省电,不是「不用」,而是「巧用」。FLP帮你选源,Geofence帮你减频,策略帮你控量。三管齐下,电量自然就省下来了。