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漂移。

位置更新策略:省电的「三板斧」

位置更新策略,说白了就是回答三个问题:多久更新一次?精度要多高?什么时候可以停?

我总结了一套「省电三板斧」,你可以直接套用:

  1. 降低频率:能10秒一次就别1秒一次。大部分场景下,5-10秒的间隔完全够用。
  2. 降低精度:能接受100米就别要10米。GPS每提高一个精度等级,功耗翻倍。
  3. 及时停止:用户切到后台、或者已经离开目标区域,立刻停止定位。别让定位服务在后台空转。

不同场景的推荐配置

场景 优先级 更新间隔 备注
天气/新闻 BALANCED 5-10分钟 甚至可以用被动监听
外卖/打车 BALANCED 10-30秒 用户下单后提高频率
运动轨迹 HIGH_ACCURACY 1-5秒 跑步/骑行场景
导航 HIGH_ACCURACY 1秒 必须持续定位
一个小技巧:removeLocationUpdates() 及时清理。很多开发者只记得「请求」,不记得「释放」。Activity onPause 时就应该停止定位,onResume 时再恢复。

知识体系图:位置服务省电的核心逻辑

位置服务省电核心逻辑 目标:按需索取,降低功耗 Fused Location Provider Geofence API 位置更新策略 自动选择最优定位源 GPS / Wi-Fi / 基站 融合 边界触发,不持续定位 进出围栏时唤醒 降低频率 / 降低精度 及时停止定位 结果:省电 30%-70%,用户体验提升

避坑指南:我踩过的几个坑

  • 不要同时开多个定位请求:我曾经在一个页面里同时调了FLP和原生GPS,结果电量直接翻倍。一个App里,只保留一个定位客户端。
  • Geofence 数量别太多:系统对Geofence数量有限制(通常100个)。超过限制,后面的围栏不会触发。我做过一个巡检App,设了200个围栏,结果一半没生效。
  • 别忘了处理权限:Android 10以后,后台定位权限需要单独申请。很多开发者只申请了前台权限,结果App切到后台就收不到位置更新。
  • 测试时别用模拟器:模拟器的位置数据是「假」的,测不出真实功耗。我建议用真机,插上电池监控工具,看电流变化。
一句话总结: 位置服务省电,不是「不用」,而是「巧用」。FLP帮你选源,Geofence帮你减频,策略帮你控量。三管齐下,电量自然就省下来了。
公众号:蓝海资料掘金营,微信deep3321