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

最新Android版本实现可抗任务管理器清理的后台持续运行服务方案

Android Oreo+: Build a Persistent Background Service That Survives Task Swipe (No AlarmManager)

Hey, let's break down how to build this properly—since you've already tried AlarmManager and found it only restarts the service (not keeps it alive through swipes), we'll focus on Oreo-compliant, non-hacky methods that prioritize no notifications where possible.

Core Approach: JobScheduler + Bound Service

Android Oreo's background restrictions make regular Service instances easy targets for system cleanup. JobScheduler is the official replacement, and pairing it with a bound service ensures your process stays prioritized (since bound services are tied to active connections, which the system avoids killing).

Step 1: Implement the JobService

This job will act as a watchdog—when it triggers, it binds to your persistent service to keep the process alive, and reschedules itself if it gets stopped.

class PersistentJobService : JobService() {
    private var serviceConnection: ServiceConnection? = null

    override fun onStartJob(params: JobParameters?): Boolean {
        // Bind to our persistent service to maintain an active connection
        serviceConnection = object : ServiceConnection {
            override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
                // Connection established—keep it alive
            }

            override fun onServiceDisconnected(name: ComponentName?) {
                // Re-bind if connection drops
                bindService(
                    Intent(this@PersistentJobService, PersistentService::class.java),
                    this,
                    BIND_AUTO_CREATE
                )
            }
        }
        bindService(
            Intent(this, PersistentService::class.java),
            serviceConnection!!,
            BIND_AUTO_CREATE
        )
        return true // Indicates job is still running
    }

    override fun onStopJob(params: JobParameters?): Boolean {
        // Cleanup and re-schedule the job to maintain persistence
        serviceConnection?.let { unbindService(it) }
        scheduleJob()
        return true // Request re-scheduling if job was terminated
    }

    private fun scheduleJob() {
        val jobInfo = JobInfo.Builder(1001, ComponentName(this, PersistentJobService::class.java))
            .setPersisted(true) // Retain job after device reboot
            .setMinimumLatency(1000) // Trigger 1 second after scheduling
            .setOverrideDeadline(2000) // Ensure job runs within 2 seconds
            .setRequiresBatteryNotLow(false) // Don't restrict to high battery
            .setRequiresCharging(false)
            .build()

        (getSystemService(JOB_SCHEDULER_SERVICE) as JobScheduler).schedule(jobInfo)
    }
}

Step 2: Build the Bound Persistent Service

This service will handle your actual background logic. Since it's bound to the JobService, we can avoid showing a noticeable foreground notification (or use a nearly invisible one if system rules require it).

class PersistentService : Service() {
    private val binder = LocalBinder()

    inner class LocalBinder : Binder() {
        fun getService(): PersistentService = this@PersistentService
    }

    override fun onBind(intent: Intent?): IBinder {
        // Elevate to foreground priority with a minimal, unobtrusive notification
        startForeground(1002, createLowProfileNotification())
        return binder
    }

    private fun createLowProfileNotification(): Notification {
        val channelId = "persistent_service_channel"
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            // Create a low-priority channel hidden from the user's notification shade
            val channel = NotificationChannel(
                channelId,
                "Persistent Service",
                NotificationManager.IMPORTANCE_MIN
            ).apply {
                setShowBadge(false)
                lockscreenVisibility = Notification.VISIBILITY_SECRET
            }
            getSystemService(NotificationManager::class.java).createNotificationChannel(channel)
        }

        // Build a nearly invisible notification that meets system requirements
        return NotificationCompat.Builder(this, channelId)
            .setSmallIcon(R.drawable.ic_transparent) // Use a 1x1 transparent icon
            .setContentTitle("")
            .setContentText("")
            .setPriority(NotificationCompat.PRIORITY_MIN)
            .build()
    }

    override fun onDestroy() {
        super.onDestroy()
        stopForeground(STOP_FOREGROUND_REMOVE)
    }
}

Key Optimizations to Survive Swipe Cleanup

  • Foreground Priority: Even with a minimal notification, startForeground pushes your process to the foreground priority tier, making it much harder for system swipe cleanup to kill it.
  • Auto-Rebind: If the connection between JobService and PersistentService drops, we immediately re-bind to maintain the active connection that keeps the process alive.
  • Reboot Resilience: Add the RECEIVE_BOOT_COMPLETED permission to your manifest, and create a broadcast receiver to re-schedule the job when the device boots:
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
    
    <receiver android:name=".BootCompletedReceiver">
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED" />
        </intent-filter>
    </receiver>
    
    class BootCompletedReceiver : BroadcastReceiver() {
        override fun onReceive(context: Context?, intent: Intent?) {
            if (intent?.action == Intent.ACTION_BOOT_COMPLETED) {
                context?.let {
                    val jobInfo = JobInfo.Builder(1001, ComponentName(it, PersistentJobService::class.java))
                        .setPersisted(true)
                        .setMinimumLatency(1000)
                        .build()
                    (it.getSystemService(JOB_SCHEDULER_SERVICE) as JobScheduler).schedule(jobInfo)
                }
            }
        }
    }
    

Critical Notes for Custom ROMs

  • Battery Optimization: Most OEMs (Xiaomi, Huawei, Samsung) have aggressive battery savers. You'll need to guide users to add your app to the "No Optimization" list in device settings—without this, even the best implementation will get killed.
  • Swipe Cleanup Behavior: On some devices, swiping an app kills the entire process. In this case, JobScheduler will automatically re-schedule the job within a few minutes (system-dependent) to restart your service.

内容的提问来源于stack exchange,提问作者user9367441

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 08:56:22