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

MIUI系统中WorkManager Worker运行2-3天后停止工作的问题

MIUI系统WorkManager Worker运行几天后停止的解决方案

已开启应用自启动权限并关闭电池优化,但MIUI系统中WorkManager Worker运行2-3天后不再执行任务,三星设备上运行正常。以下是现有后台上传服务及WorkManager实现代码,需实现跨设备一致的运行效果:


后台上传服务代码

package com.unischolarz.calllogger.utils
import android.app.Service
import android.content.Context
import android.content.Intent
import android.os.IBinder
import android.os.PowerManager
import android.util.Log
import androidx.work.Constraints
import androidx.work.NetworkType
import androidx.work.OneTimeWorkRequestBuilder
import androidx.work.WorkManager
import java.util.UUID

class BackgroundService() : Service() {

    private var wakeLock: PowerManager.WakeLock? = null

    override fun onCreate() {
        val powerManager = getSystemService(Context.POWER_SERVICE) as PowerManager
        wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "MyApp::MyWakeLockTag")
        wakeLock?.acquire(10 * 60 * 1000L /*10 minutes*/)
    }

    override fun onBind(intent: Intent?): IBinder? {
        return null
    }

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        if (intent == null) {
            return START_STICKY
        }

        if (intent.getBooleanExtra("ACTION", false)) {
//            performNetworkTask()
            Logger.e("networkIntent", "Inetent Received1")
        }
        return START_STICKY
    }

    override fun onDestroy() {
        super.onDestroy()

        wakeLock?.let {
            if (it.isHeld) {
                it.release()
            }
        }
        val broadcastIntent = Intent("ACTION.RESTART.YourService")
        sendBroadcast(broadcastIntent)

    }

    private fun performNetworkTask() {
        val constraints = Constraints.Builder()
            .setRequiredNetworkType(NetworkType.CONNECTED)
            .build()

        val workRequest = OneTimeWorkRequestBuilder<LogUpdateWorker>()
            .setConstraints(constraints)
            .addTag(UUID.randomUUID().toString())
            .build()


        WorkManager.getInstance(this).enqueue(workRequest)
        Log.d("WorkRequest", workRequest.toString())
        Log.d("MakingWrk", "Making Work")
    }

}

WorkManager实现代码

package com.unischolarz.calllogger.utils

import android.content.Context
import android.content.SharedPreferences
import android.util.Log
import androidx.work.CoroutineWorker
import androidx.work.Worker
import androidx.work.WorkerParameters
import com.unischolarz.calllogger.main.MainActivityViewModel

class LogUpdateWorker(private val appContext: Context, workerParams: WorkerParameters) :
    CoroutineWorker(appContext, workerParams) {

    private val sharedPrefs: SharedPreferences =
        appContext.getSharedPreferences("UPLOAD_PREFS", Context.MODE_PRIVATE)

    override suspend fun doWork(): Result {
        try {
            synchronized(this) {
                val currentTime = System.currentTimeMillis()

                val uploadStartTimestamp1 = sharedPrefs.getLong("UPLOAD_START_TIMESTAMP1", 0)
                if (currentTime - uploadStartTimestamp1 > MainActivityViewModel.UPLOAD_TIMEOUT) {
                    sharedPrefs.edit().putBoolean("UPLOAD_IN_PROGRESS1", false).apply()
                }

                val isUploadInProgress1 = sharedPrefs.getBoolean("UPLOAD_IN_PROGRESS1", false)

                Log.d("UPLOAD_IN_PROGRESS4", "$currentTime |||| $uploadStartTimestamp1")
                Log.d("UPLOAD_IN_PROGRESS4", "$isUploadInProgress1")

                if (!isUploadInProgress1) {
                    sharedPrefs.edit()
                        .putLong("UPLOAD_START_TIMESTAMP1", currentTime)
                        .apply()

                    Log.d("UPLOAD_IN_PROGRESS4", "INITIALIZING UPLOAD IN BACKGROUND AFTER CALL")
                    MainActivityViewModel().getAllData2(appContext)
                    Log.d("UPLOAD_IN_PROGRESS4", "UPLOAD COMPLETED IN BACKGROUND AFTER CALL")
                } else {
                    Log.d("UPLOAD_IN_PROGRESS4", "UPLOAD ALREADY IN PROGRESS")
                }
            }
        } catch (e: Exception) {
            Log.e("UPLOAD_IN_PROGRESS4", "Exception: ${e.message}")
            logException(e)
            sharedPrefs.edit().putBoolean("UPLOAD_IN_PROGRESS1", false).apply()
            return Result.failure()
        }
        return Result.success()
    }
}

解决方案

1. 优化WorkManager任务配置

MIUI对后台任务调度限制更严格,需调整WorkRequest配置适配:

  • 替换随机Tag为固定标识,便于任务管理,避免无意义Tag占用系统资源
  • 添加退避重试策略,任务失败时自动重试,提升存活率
  • 开启任务持久化,确保设备重启后任务不丢失

修改后的performNetworkTask代码:

private fun performNetworkTask() {
    val constraints = Constraints.Builder()
        .setRequiredNetworkType(NetworkType.CONNECTED)
        .build()

    val workRequest = OneTimeWorkRequestBuilder<LogUpdateWorker>()
        .setConstraints(constraints)
        .addTag("LOG_UPLOAD_WORKER") // 固定Tag
        .setBackoffCriteria(
            BackoffPolicy.LINEAR,
            OneTimeWorkRequest.MIN_BACKOFF_MILLIS,
            TimeUnit.MILLISECONDS
        ) // 退避重试
        .setPersisted(true) // 开启持久化
        .build()

    WorkManager.getInstance(this).enqueue(workRequest)
    Log.d("WorkRequest", workRequest.id.toString())
    Log.d("MakingWrk", "Upload work enqueued")
}

2. 移除不可靠的Service重启机制

MIUI对隐式广播限制极严,sendBroadcast("ACTION.RESTART.YourService")几乎无法触发Service重启,且START_STICKY在MIUI后台限制下无法保证Service持续运行。建议直接依赖WorkManager调度任务,删除Service销毁时的广播重启逻辑。

3. 适配MIUI特殊后台权限

除自启动和电池优化外,需引导用户开启应用的无限制后台活动:
路径:设置→应用设置→应用管理→找到你的应用→省电策略→选择「无限制」

4. 优化Worker内部逻辑

  • 移除synchronized块:CoroutineWorker的doWork方法默认在单线程调度器执行,无需额外同步;若需协程安全同步,改用Mutex:
private val mutex = Mutex()

override suspend fun doWork(): Result {
    try {
        mutex.withLock {
            // 原有业务逻辑
        }
    } catch (e: Exception) {
        // 异常处理
    }
    return Result.success()
}
  • 避免直接实例化ViewModel:ViewModel为UI生命周期设计,应将上传逻辑抽离为独立Repository或工具类,在Worker中直接调用:
// 替换MainActivityViewModel().getAllData2(appContext)
DataUploader.uploadAllData(appContext) // 抽离后的上传工具类示例

5. 改用周期性任务(若业务需要)

如果是定期执行上传任务,直接使用PeriodicWorkRequest替代多次创建OneTimeWorkRequest,减少系统调度压力:

val periodicWorkRequest = PeriodicWorkRequestBuilder<LogUpdateWorker>(1, TimeUnit.HOURS)
    .setConstraints(constraints)
    .setBackoffCriteria(BackoffPolicy.LINEAR, OneTimeWorkRequest.MIN_BACKOFF_MILLIS, TimeUnit.MILLISECONDS)
    .setPersisted(true)
    .build()

WorkManager.getInstance(this).enqueueUniquePeriodicWork(
    "PERIODIC_LOG_UPLOAD",
    ExistingPeriodicWorkPolicy.KEEP,
    periodicWorkRequest
)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 18:16:00