Android 12及以上版本应用关闭时通过WorkManager获取定位被系统终止的问题及解决方案探讨
我来帮你拆解问题根源,给出可行的修复方案,同时聊聊WhatsApp位置共享的实现逻辑。
一、你的WorkManager代码为什么会失效?
你的LocationWorker存在一个核心逻辑问题:doWork方法是CoroutineWorker的核心执行体,它执行完毕返回Result.success()后,整个Worker的生命周期就结束了。但你在getLocation里调用的requestLocationUpdates是异步持续监听的操作——Worker销毁后,绑定的LocationCallback和定位请求会被系统一并清理,这就是为什么只能运行几分钟就停止的原因。
WorkManager本质是用来处理一次性或周期性的短任务,不是为持续后台运行设计的,尤其是Android 12对后台服务的限制非常严格,普通后台任务很难长期存活。
正确的修复方案:改用前台服务(Foreground Service)
要实现App关闭后持续获取定位,必须使用前台服务——这是Android官方允许的长期后台运行方式,只要显示一个可见的通知,系统就不会轻易终止它。你可以结合WorkManager来启动前台服务,或者直接在需要时启动:
1. 改造Worker:让它启动前台服务
修改LocationWorker的doWork方法,不再自己处理定位,而是启动专门的前台服务:
override suspend fun doWork(): Result { val serviceIntent = Intent(context, LocationForegroundService::class.java) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { // Android 8.0+必须用startForegroundService context.startForegroundService(serviceIntent) } else { context.startService(serviceIntent) } return Result.success() }
2. 创建前台服务类LocationForegroundService
这个类专门负责持续定位,同时维护前台通知:
class LocationForegroundService : Service() { private val NOTIFICATION_ID = 10 private lateinit var fusedLocationClient: FusedLocationProviderClient private lateinit var locationCallback: LocationCallback override fun onCreate() { super.onCreate() fusedLocationClient = LocationServices.getFusedLocationProviderClient(this) // 启动前台服务,必须显示通知 startForeground(NOTIFICATION_ID, createPersistentNotification()) // 开始定位监听 setupLocationUpdates() } private fun createPersistentNotification(): Notification { // Android 8.0+需要创建通知渠道 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { createNotificationChannel() } return NotificationCompat.Builder(this, NOTIFICATION_ID.toString()) .setContentTitle("正在共享位置") .setContentText("点击查看详情") .setPriority(NotificationCompat.PRIORITY_HIGH) .setSmallIcon(R.drawable.ic_location) // 设置为持续通知,用户不能手动取消 .setOngoing(true) .build() } @RequiresApi(Build.VERSION_CODES.O) private fun createNotificationChannel() { val channel = NotificationChannel( NOTIFICATION_ID.toString(), "位置共享", NotificationManager.IMPORTANCE_DEFAULT ) val notificationManager = getSystemService(NotificationManager::class.java) notificationManager.createNotificationChannel(channel) } private fun setupLocationUpdates() { val locationRequest = LocationRequest.create().apply { interval = 3000 fastestInterval = 1500 priority = LocationRequest.PRIORITY_HIGH_ACCURACY maxWaitTime = 2000 } locationCallback = object : LocationCallback() { override fun onLocationResult(locationResult: LocationResult) { val latestLocation = locationResult.locations.lastOrNull() ?: return Log.d("LocationLog", "纬度:${latestLocation.latitude} 时间:${System.currentTimeMillis()}") // 在这里处理定位结果,比如上传到服务器 } } // 检查权限,确保已获取精确定位权限 if (ActivityCompat.checkSelfPermission( this, Manifest.permission.ACCESS_FINE_LOCATION ) == PackageManager.PERMISSION_GRANTED ) { fusedLocationClient.requestLocationUpdates( locationRequest, locationCallback, Looper.getMainLooper() ) } } override fun onDestroy() { super.onDestroy() // 服务销毁时,停止定位更新,避免内存泄漏 fusedLocationClient.removeLocationUpdates(locationCallback) } override fun onBind(intent: Intent?): IBinder? = null }
3. 在清单文件中声明服务
别忘了在AndroidManifest.xml里注册前台服务,并指定位置类型:
<service android:name=".LocationForegroundService" android:foregroundServiceType="location" />
4. 权限检查与申请
确保你已经在清单中添加了必要的权限:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <uses-permission android:name="android.permission.FOREGROUND_SERVICE_LOCATION" /> <!-- 如果需要App关闭后仍能获取后台位置,还需要这个权限 --> <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
并且在运行时动态请求ACCESS_FINE_LOCATION和ACCESS_BACKGROUND_LOCATION(Android 10+需要后台位置权限才能在App退到后台后继续获取定位)。
二、WhatsApp的位置共享为什么不用改电池模式?
WhatsApp并没有什么“黑科技”,它完全遵循Android的官方规范,核心原因有这几点:
- 前台服务+持续通知:和我们上面的方案一样,WhatsApp启动前台服务并显示持续的位置共享通知,前台服务的优先级很高,系统会默认给予资源倾斜,不会轻易终止,所以不需要用户修改电池模式。
- 智能的定位策略:WhatsApp不会一直保持最高精度的定位,它会根据用户的状态调整——比如用户静止时,会降低定位更新频率,减少CPU和电量消耗,这样既符合用户需求,也不会触发系统的资源优化机制。
- 厂商适配:作为全球知名应用,WhatsApp会针对小米、华为、OPPO等国内厂商的定制系统做适配,比如加入厂商的后台白名单,但这只是辅助,核心还是依赖前台服务的合法机制。
内容的提问来源于stack exchange,提问作者speedy.user

