androidandroid-workmanagerandroid-backgroundandroid-connectivitymanager

WorkManager with `.setRequiredNetworkType(NetworkType.UNMETERED)` has no active internet connection inside `doWork`


I am creating a backup app which backs up some files at night. Because it needs to be every night around the same time I'm using a OneTimeWorkRequest which will be scheduled again after the last time has run. So this is the code I am using:

private fun scheduleNextSyncWorker(context: Context) {
    val nextScheduleDelay = 60000L

    val test = OneTimeWorkRequestBuilder<TestWorker>()
        .setInitialDelay(nextScheduleDelay, TimeUnit.MILLISECONDS)
        .setConstraints(
            Constraints.Builder()
                .setRequiredNetworkType(NetworkType.UNMETERED)
                .build()
        )
        .addTag("test")
        .build()
    WorkManager.getInstance(context)
        .enqueueUniqueWork("test", ExistingWorkPolicy.REPLACE, test)
}

class TestWorker(appContext: Context, workerParameters: WorkerParameters) : CoroutineWorker(appContext, workerParameters) {
    override suspend fun doWork(): Result {
        try {
            withContext(Dispatchers.IO) {
                val connectivityManager = applicationContext.connectivityManager()
                var waitedMillis = 0L
                var waitedSince = System.currentTimeMillis()

                // Added this to check if it is connected and usually this is false
                while(connectivityManager.activeNetworkInfo?.isConnected != true && waitedMillis < 10000) {
                    Log.d("TEST", "connected: ${connectivityManager.activeNetworkInfo?.isConnected}")
                    waitedMillis = System.currentTimeMillis() - waitedSince
                    delay(1000)
                }

                // Api calls here which mostly fail because no internet connection
            }
            return Result.success()
        } catch (t: Throwable) {
            return Result.failure()
        } finally {
            GlobalScope.launch {
                // Probably not the best way, but the worker needs to pass back that we succeeded or failed before we will schedule the next
                delay(1000)
                scheduleNextSyncWorker(applicationContext)
            }
        }
    }
}

This code will all run fine while the app is in the foreground. However as soon as I move the app to the background and lock the device most api calls fail with java.net.UnknownHostException: Unable to resolve host "graph.microsoft.com": No address associated with hostname. Like you can see in the code I have some extra code to check if we are currently connected which when device is locked is mostly false. Sometimes after a few seconds we regain internet access, but sometimes not.

I thought the WorkManager was supposed to call doWork only if the constraints are met. But since I'm not having an active connection I'm not sure how I should continue. It seems trivial to add a full network check inside the worker while it's suppose to check it itself.

Any thoughts?


Solution

  • I figured it out after a lot of headaches and hours of work. It is a bug in the new 2.10.0 version. This is the first time I used WorkManager, so didn't know it had to do with the new version. Just revert back to 2.9.1 and it will work again.

    I created an issue on IssueTracker: https://issuetracker.google.com/issues/387656869