2

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.

Maxim Mazurok
  • 3,856
  • 2
  • 22
  • 37
  • 1
    Well, if you need a connected network, why *wouldn't* you use a connected network requirement? – ianhanniballake Jan 02 '21 at 04:51
  • 1
    You should add network constraint`setRequiredNetworkType(NetworkType.CONNECTED)` . – ADM Jan 02 '21 at 05:07
  • Thank you, guys. Even with that constraint added, it still doesn't work sometimes. The first time it worked, after 15 minutes - it doesn't. and then after another 15 minutes - it works again. Should I add FlexInterval?... – Maxim Mazurok Jan 02 '21 at 05:24
  • @ianhanniballake my original understanding was that Android wouldn't cut the network when the screen is locked. Which is not the case, apparently? – Maxim Mazurok Jan 02 '21 at 05:25
  • @ADM is it better to use it together with FlexInterval? It seems like even with this constraint sometimes there's no internet access... – Maxim Mazurok Jan 02 '21 at 05:26

1 Answers1

1

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).

Maxim Mazurok
  • 3,856
  • 2
  • 22
  • 37