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
相关产品推荐
相关产品推荐

