Search code examples
androidkotlinandroid-workmanagerbackground-sync

How to fix "unable to resolve host" error in WorkerWrapper?


I'm trying to implement background sync on Android.

It works just fine when emulator (API 30) is awake and unlocked.

But if I quit the app (not force quit, just remove from the recent apps) and lock the emulator screen - eventually I'll start getting the following error:

D/Error: Unable to resolve host "jsonplaceholder.typicode.com": No address associated with hostname
I/WM-WorkerWrapper: Worker result FAILURE for Work [ id=5cfe9175-b6f8-4aa8-8cbc-7d507915a77d, tags={ com.better.alarm.workers.SyncEventsWorker } ]

I didn't enable battery saving mode on the device and the internet connection on my PC that runs emulator is very good and stable. And RAM is not an issue.

Here's my worker:

class SyncEventsWorker(appContext: Context, workerParams: WorkerParameters) :
        Worker(appContext, workerParams) {
    private val client = OkHttpClient()

    @Serializable
    data class Event(val userId: Int, val id: Int, val title: String, val completed: Boolean)

    override fun doWork(): Result {
        try {
            getEvents()
        } catch (e: IOException) {
            Log.d("Error", e.localizedMessage)
            return Result.failure()
        }

        return Result.success()
    }

    private fun getEvents(): Array<Event> {
        val request = Request.Builder()
                .url("https://jsonplaceholder.typicode.com/todos")
                .build()

        client.newCall(request).execute().use { response ->
            if (!response.isSuccessful) throw IOException("Unexpected code $response")

            val body = response.body!!.string()

            return Json.decodeFromString(body)
        }
    }
}

And this is how I schedule the work:

class MyApplication : Application() {
    override fun onCreate() {
        val uploadWorkRequest: WorkRequest =
                PeriodicWorkRequestBuilder<SyncEventsWorker>(PeriodicWorkRequest.MIN_PERIODIC_INTERVAL_MILLIS, TimeUnit.MILLISECONDS)
                        .build()
        WorkManager
                .getInstance(this)
                .enqueue(uploadWorkRequest)
    }
}

I suspect that it's some kind of battery optimization when the emulator enters a "deep sleep" mode and cuts off the internet connection to save the battery.

How can I go around this? Should I use setRequiredNetworkType(NetworkType.CONNECTED), maybe?

UPDATE With setRequiredNetworkType(NetworkType.CONNECTED) it works only sometimes. Some runs still fail, but some runs succeed now.


Solution

  • It seems like there's nothing you can do from the code part.

    But I managed to solve this by disabling Battery Manager in the android settings. Now all my requests from background worker succeed even when the app is closed and the emulator is locked (sleeping).