如何在低功耗模式下实现周期性位置更新?

解读

面试官想考察的是:在国内真机环境(GMS 缺失、厂商深度定制、后台限制极严)下,如何既保证业务“周期性”拿到定位,又把电量消耗压到最低,同时通过国内各大应用市场的隐私合规审查。回答必须围绕 Android 10 以后的位置权限模型、国产 ROM 的省电精灵、系统级休眠、Doze、App Standby、厂商心跳对齐机制,以及国内可用的定位 SDK(高德、百度、华为)提供的低功耗接口展开,而不是照搬官方 Fused Location Provider。

知识点

  1. 定位通道:GPS(高功耗)、基站/Wi-Fi 被动扫描(低功耗)、BLE 蓝牙 beacon、加速度传感器辅助判断静止/移动。
  2. Android 10 分区权限:前台位置(仅运行时)、后台位置(需额外弹窗声明且应用市场审核)、ACCESS_BACKGROUND_LOCATION。
  3. 国产 ROM 后台限制:小米“神隐”、华为“应用启动管理”、OPPO“高耗电保护”、vivo“后台高耗电”,均需引导用户手工加白名单。
  4. 系统省电模式:Doze Idle、Light-Doze、App Standby、厂商对齐唤醒(AlarmManager 批量对齐到 5~15 min 窗口)。
  5. 国内低功耗定位 SDK:高德“智能定位”、百度“低功耗定位”、华为 Fused Location(HMS Core),均支持 30 s~3 min 周期采样,功耗 < 5 mA。
  6. 传感器辅助:Significant Motion + Step Counter 判断用户是否移动,静止期主动拉长采样周期;车载场景可结合车载 Host 的 GNSS 芯片。
  7. 网络策略:定位结果优先走缓存,非必要不上传;上传走统一推送通道(如厂商 Push、MQTT 长连接),避免频繁唤醒无线。
  8. 合规要求:隐私政策必须明示“后台定位目的、频率、保存期限”,并在首次后台定位前弹窗征得用户单独同意,否则华为应用市场会直接驳回。
  9. 电量归因:使用 Battery Historian 查看 “GPS sensor” 与 “Network location” 耗电占比,确保后台定位 < 总电量 2%。

答案

“低功耗周期性定位”在国内落地分四步:

第一步,权限与合规
AndroidManifest 中仅保留 coarse + fine 权限,targetSdk≥30 时后台定位权限拆分到单独声明;首次启动弹窗向用户说明“后台定位用于运动轨迹记录,周期 2 min,不用于商业广告”,并引导用户把应用加到“电池无限制”白名单,否则周期会被系统压到 15 min 以上。

第二步,选择定位通道
静止场景:直接采用高德 Android 定位 SDK 的“智能定位”模式,setOnceLocation(false) + setInterval(120_000),内部自动用 Wi-Fi/基站扫描,屏蔽 GPS,功耗约 3 mA。
移动场景:注册 SignificantMotionListener,检测到大幅度移动后,临时把周期缩短到 30 s 并允许 GPS 参与,持续 5 min 后恢复 2 min 周期;若进入车载模式(BluetoothA2dp 连接车载),则通过 CarConnection 把定位需求 offload 到车机,手机端只接收结果,零功耗。

第三步,对齐唤醒与网络
用 WorkManager 的 setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST) 创建 2 min 周期任务,系统会自动对齐到厂商心跳窗口,避免频繁唤醒 CPU;定位结果先写 Room 本地缓存,攒够 10 条或 5 km 位移后,通过厂商统一推送通道(如华为 Push)一次性压缩上传,减少无线激活次数。

第四步,电量兜底
后台定位服务运行在独立 :location 进程,startForeground() 挂出“正在记录轨迹”通知,ID 固定为 1,防止 10 s 内被系统杀;同时监听 PowerManager.isPowerSaveMode(),一旦用户打开系统省电开关,主动把周期拉长到 10 min 并关闭 GPS,保证电量占比始终低于 2%。上线前用 Battery Historian 跑 8 小时 monkey,后台定位耗电 1.8%,符合国内主流应用市场审核要求。

拓展思考

  1. 折叠屏/大屏设备在展开态常放在桌面车载支架,可结合 WindowInfoTracker 判断屏幕状态,若连续 30 min 处于展开+充电态,则把定位周期缩短到 15 s 做高精度导航,同时利用 TEE 安全存储轨迹,兼顾体验与隐私。
  2. 未来 Android 14 引入“部分访问位置”权限,允许用户仅授予“大致位置”,需提前在代码里用 Location.isMock() 与 getVerticalAccuracyMeters() 做降级策略,防止业务因精度不足而异常。
  3. 国内厂商正在推进系统级“统一定位缓存”,同一设备上所有 App 共享一份 Wi-Fi/基站扫描结果;可主动调用 VendorLocationManager.getUnifiedLocation() 获取系统缓存,实现 0 功耗“秒定”,但需适配各厂商隐藏 API,建议用反射 + 灰度开关控制。