如何实现安卓防杀后台位置服务:随位置变化自动重启
实现防杀式低功耗位置追踪服务方案
核心思路
要满足「应用被杀后仍能触发、位置变化超100米才工作、低功耗」的需求,不能单纯依赖前台服务,必须结合系统级调度组件+低功耗状态感知+按需位置更新的组合方案,推荐用 WorkManager + Activity Transition API + Fused Location Provider 的被动更新模式,这是目前安卓平台最可靠的后台任务调度方案。
步骤1:用Activity Transition API实现低功耗状态感知
Transition API由系统层面监听设备活动状态,无需应用持续运行,能在设备从静止转为移动时触发后续任务,完美适配「静止停、移动启」的低功耗需求。
代码实现
1. 注册状态监听的Worker
class TransitionDetectionWorker(context: Context, params: WorkerParameters) : Worker(context, params) { private val activityRecognitionClient = ActivityRecognition.getClient(context) override fun doWork(): Result { // 监听从静止进入步行/乘车状态的变化 val transitions = listOf( ActivityTransition.Builder() .setActivityType(DetectedActivity.STILL) .setActivityTransition(ActivityTransition.ACTIVITY_TRANSITION_EXIT) .build(), ActivityTransition.Builder() .setActivityType(DetectedActivity.ON_FOOT) .setActivityTransition(ActivityTransition.ACTIVITY_TRANSITION_ENTER) .build(), ActivityTransition.Builder() .setActivityType(DetectedActivity.IN_VEHICLE) .setActivityTransition(ActivityTransition.ACTIVITY_TRANSITION_ENTER) .build() ) val request = ActivityTransitionRequest(transitions) val pendingIntent = PendingIntent.getBroadcast( context, 0, Intent(context, TransitionReceiver::class.java), PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE ) activityRecognitionClient.requestActivityTransitionUpdates(request, pendingIntent) .addOnFailureListener { // 处理注册失败逻辑,比如重试 } return Result.success() } }
2. 接收状态变化的Broadcast Receiver
class TransitionReceiver : BroadcastReceiver() { override fun onReceive(context: Context?, intent: Intent?) { if (ActivityTransitionResult.hasResult(intent)) { val result = ActivityTransitionResult.extractResult(intent) result?.transitionEvents?.forEach { event -> // 检测到设备开始移动,触发位置追踪任务 if ((event.activityType == DetectedActivity.ON_FOOT || event.activityType == DetectedActivity.IN_VEHICLE) && event.transitionType == ActivityTransition.ACTIVITY_TRANSITION_ENTER ) { val workRequest = OneTimeWorkRequestBuilder<LocationTrackingWorker>() .build() WorkManager.getInstance(context!!).enqueue(workRequest) } } } } }
步骤2:用WorkManager实现可靠的位置追踪调度
WorkManager是系统级任务调度器,即使应用被杀,也能保证任务被系统唤醒执行,同时可以按需启停位置更新,控制功耗。
位置追踪Worker实现
class LocationTrackingWorker(context: Context, params: WorkerParameters) : CoroutineWorker(context, params) { private lateinit var fusedLocationClient: FusedLocationProviderClient private var lastLocation: Location? = null private val locationCallback = object : LocationCallback() { override fun onLocationResult(locationResult: LocationResult?) { locationResult ?: return val currentLocation = locationResult.lastLocation ?: return lastLocation?.let { // 计算位置变化是否超过100米 if (it.distanceTo(currentLocation) > 100) { // 这里处理位置更新逻辑,比如上传服务器 handleLocationUpdate(currentLocation) } } ?: run { // 首次获取位置,记录基准点 lastLocation = currentLocation } // 检查设备是否回到静止状态,若静止则停止追踪 checkIfStill() } } override suspend fun doWork(): Result { fusedLocationClient = LocationServices.getFusedLocationProviderClient(applicationContext) val locationRequest = LocationRequest.create().apply { priority = LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY // 低功耗模式,避免持续唤醒GPS interval = 60000 // 1分钟更新一次,可按需调整 fastestInterval = 30000 } return try { fusedLocationClient.requestLocationUpdates(locationRequest, locationCallback, Looper.getMainLooper()) Result.success() } catch (e: Exception) { Result.retry() } } private suspend fun checkIfStill() { val client = ActivityRecognition.getClient(applicationContext) val pendingIntent = PendingIntent.getBroadcast( applicationContext, 1, Intent(applicationContext, StillCheckReceiver::class.java), PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE ) // 请求单次活动状态检测 client.requestActivityUpdates(5000, pendingIntent) } private fun handleLocationUpdate(location: Location) { // 自定义位置处理逻辑 } }
静止状态检测Receiver
class StillCheckReceiver : BroadcastReceiver() { override fun onReceive(context: Context?, intent: Intent?) { if (ActivityRecognitionResult.hasResult(intent)) { val result = ActivityRecognitionResult.extractResult(intent) val mostProbableActivity = result.mostProbableActivity // 检测到静止,停止位置更新 if (mostProbableActivity.type == DetectedActivity.STILL && mostProbableActivity.confidence >= 70) { val fusedClient = LocationServices.getFusedLocationProviderClient(context!!) fusedClient.removeLocationUpdates(PendingIntent.getBroadcast( context, 1, Intent(context, StillCheckReceiver::class.java), PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE )) } } } }
步骤3:基础配置与初始化
1. Manifest注册组件
<receiver android:name=".TransitionReceiver" android:exported="false" /> <receiver android:name=".StillCheckReceiver" android:exported="false" /> <service android:name=".LocationService" android:foregroundServiceType="location" />
2. 应用启动时初始化监听任务
在启动页或Application类的onCreate中添加:
// 注册周期性的状态监听任务,确保应用重启后能重新监听 val transitionWorkRequest = PeriodicWorkRequestBuilder<TransitionDetectionWorker>(1, TimeUnit.DAYS) .build() WorkManager.getInstance(this).enqueueUniquePeriodicWork( "TransitionDetection", ExistingPeriodicWorkPolicy.REPLACE, transitionWorkRequest )
关键注意事项
- 权限要求:必须动态申请
ACCESS_FINE_LOCATION、ACCESS_BACKGROUND_LOCATION(Android10+)、ACTIVITY_RECOGNITION权限,否则所有监听都会失效。 - 功耗优化:始终使用
PRIORITY_BALANCED_POWER_ACCURACY,避免高精准度模式;静止时立即停止位置更新,不要持续监听;尽量减少前台服务的使用,仅在部分严格限制后台的厂商ROM中作为补充(显示低优先级通知)。 - 厂商适配:国产ROM(小米、华为、OPPO等)存在后台杀进程限制,必须引导用户将应用加入「后台白名单」或「自启动列表」,否则即使按上述方案实现,也可能被系统强制终止。
内容的提问来源于stack exchange,提问作者Siddy Hacks
相关产品推荐
相关产品推荐

