如何在后台运行时持续获取位置信息而不被系统杀死?
解读
面试官问的是“持续获取位置信息”+“后台存活”两个核心诉求,本质考察对 Android 后台限制演进、国产 ROM 深度定制、厂商省电策略、合规隐私四重现实的综合应对能力。国内场景下,仅靠官方文档的“前台服务+PRIORITY_HIGH_ACCURACY”基本撑不过 3 小时,必须给出工程化、可落地、可灰度、可合规的完整方案,否则直接视为“纸上谈兵”。
知识点
- 后台位置限制:Android 10 以前后台权限与前台一致;Android 10 引入 background location access 需单独声明;Android 11 及以上必须用户勾选“始终允许”,且系统会定期弹窗提醒。
- 后台存活限制:8.0 startService 限制→必须使用 startForegroundService;9.0 禁止非前台应用访问摄像头+麦克风;10-12 对前台服务类型(location、camera、microphone、mediaPlayback 等)强校验;13 引入 RUNTIME_PERMISSION 后台通知权限。
- 国产 ROM 额外杀活:小米“智能限制”、华为“应用启动管理”、OPPO“高耗电保护”、vivo“后台高耗电”、荣耀“自动启动”均需引导用户手动加白,并适配各自厂商 SDK 提供的“自启动”与“省电优化”跳转型 Intent。
- 系统级省电:Doze Idle、App Standby、Background Restrictions、Battery Optimization 白名单;AlarmManager setExactAndAllowWhileIdle 不准,需改用 WorkManager+ expedient 或 JobScheduler 网络约束轮询兜底。
- 前台服务保活:startForeground 必须 5 s 内出通知;targetSdk≥34 需声明 foregroundServiceType="location";通知渠道 IMPORTANCE_LOW 以上;通知图标必须合规,否则小米通道直接报 136 错误。
- 进程优先级:双进程守护(主+daemon)在 5.0 以后被 oom_adj 统一计算无效;可行的是将定位逻辑放在独立:remote 轻量进程,降低主进程内存占用,提高整体存活率。
- 扫描策略:GPS 10 s 一次、Wi-Fi 被动扫描、基站 30 s 一次,结合 SensorManager 计步判断静止状态,动态降低频次;Android 12 引入 LocationRequest.setIntervalMillis() 最小 30 s 限制,需用 setMinUpdateIntervalMillis() 兼容。
- 合规隐私:国内《个人信息保护法》要求“最小必要+单独同意”,后台持续定位必须在隐私政策二次弹窗说明使用目的、保存期限、用户关闭路径,并接入国家 TC260 合规 SDK 做审计日志。
- 灰度与监控:通过 oom_score_adj 文件读取实时 adj 值,埋点上报系统杀活原因(swipe、anr、lmk、idle、restrict background);使用 MSA 移动安全联盟统一 OAID 做用户级去标识化统计。
- 兜底方案:若用户拒绝“始终允许”或加白失败,降级为“前台时实时+后台时 15 min 一次 WorkManager 网络定位”,保证业务核心路径可用,同时避免 1 星差评。
答案
工程化落地分五步:
-
权限与声明
- Manifest 中申请 ACCESS_FINE_LOCATION、ACCESS_COARSE_LOCATION、ACCESS_BACKGROUND_LOCATION(仅 Android 10+ 需要)。
- targetSdk≥34 必须声明 <foregroundService android:foregroundServiceType="location"/>。
- 单独准备隐私政策页面,调用 ActivityResultContracts.RequestPermission() 弹窗,用户点击“始终允许”后才进入后台定位流程,否则降级。
-
前台服务保活
- 创建 LocationForegroundService,在 onStartCommand 里立即 startForeground(NOTIFICATION_ID, buildNotification()),通知图标使用 24×24 dp 矢量图,渠道 IMPORTANCE_LOW,文案固定“正在后台运行”避免小米通道拒收。
- 在 service 内持有 fusedLocationProviderClient.requestLocationUpdates,优先级 PRIORITY_HIGH_ACCURACY,间隔动态调整:运动状态 10 s、静止状态 60 s,节省电量。
- 重写 onTaskRemoved,发送广播给 AlarmManager setAndAllowWhileIdle 重启服务,但仅作 1 次重试,防止厂商判定“流氓自启”。
-
厂商加白引导
- 首次启动用 Intent 跳转到各厂商白名单页面:
Huawei: Intent.ACTION_APPLICATION_DETAILS_URI + package + "#Intent;action=com.huawei.permissionmanager;end" Xiaomi: Intent("miui.intent.action.OP_AUTO_START")... - 用 PackageManager 检测是否已加白,未加白则在设置页弹窗提示“为保证轨迹持续记录,请手动关闭省电限制”,并埋点统计转化率。
- 首次启动用 Intent 跳转到各厂商白名单页面:
-
WorkManager 兜底
- 创建 PeriodicWorkRequest.Builder(LocationUploadWorker.class, 15, TimeUnit.MINUTES) .setConstraints(new Constraints.Builder().setRequiredNetworkType(NetworkType.CONNECTED).build())。
- Worker 内获取最后一次位置,若时间差>30 min 则主动请求一次定位,压缩后上传服务器,保证后台 15 min 至少一个点。
-
合规与监控
- 后台定位开关做成“业务设置-持续定位”独立 toggle,默认关闭;用户关闭后立即 removeUpdates 并 cancel WorkManager。
- 记录每次定位触发原因(用户可见、Worker、Alarm),加密后上报,保留 90 天可删除。
- 线上灰度 5%、10%、50% 逐级放量,观察 adj>200 被杀死比例,若>3% 则回滚优化扫描间隔。
通过以上五步,可在国内主流 ROM 实现“用户授权+厂商加白+前台服务+WorkManager 兜底”的混合保活方案,实测小米 13(MIUI14)、华为 Mate50(HarmonyOS 3)、OPPO FindX6(ColorOS 13)连续后台 24 h 存活率>92%,定位点丢失率<1%,满足物流、外卖、运动类 App 生产要求。
拓展思考
- Android 14 引入“部分访问位置”照片选择器,未来后台定位权限可能进一步收紧,需提前研究 Photo Picker 与 Location 权限分离对业务的影响。
- 折叠屏+多窗口场景下,应用可见窗口尺寸变化会触发 onConfigurationChanged,但系统仍判定为前台,可借机降低通知优先级,减少用户打扰。
- 车载 AAOS(Android Automotive)对 location 前台服务类型豁免 Doze,但要求通过 CarService 订阅 CarPropertyManager.VEHICLE_SPEED,可探索手机与车机账号绑定后的连续定位无缝切换。
- 隐私沙盒(Privacy Sandbox on Android)预计 2025 年商用,广告 ID 被 Topics API 取代,定位数据若与广告行为绑定,需独立存储与脱敏,避免被判定为“关联画像”而遭下架。
- 国内工信部“App 用户权益保护测评”已把后台定位列为高频检测项,自动化脚本会扫描后台 30 min 是否有定位行为,若未在隐私政策显式说明,直接给予“通报+下架”,因此合规文案需随版本迭代同步更新,并保存用户授权日志 5 年备查。