You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现安卓防杀后台位置服务:随位置变化自动重启

实现防杀式低功耗位置追踪服务方案

核心思路

要满足「应用被杀后仍能触发、位置变化超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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 03:21:07