I am using WorkManager in my Android application to do some background work.
This work is primarily location tracking, but also using the Internet for HTTP POST requests to an API.
With the app running in the foreground everything works perfectly, but in the background my work often seems to lack Internet, thus the POST request often fails.
I can't get it to work reliably on my Pixel 7 API 35 emulator - why might that be?
Note that I don't want to set the constraint of
NetworkType.CONNECTED
to the work, because it's primary purpose is location tracking, not the Internet part.
My AndroidManifest.xml
:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
MainActivity.kt
- 20s delay allows me to go elsewhere in the foreground before work runs:
val oneTimeRequest = OneTimeWorkRequestBuilder<LocationWorker>()
.setInitialDelay(20, TimeUnit.SECONDS)
.build()
WorkManager.getInstance(context)
.enqueue(oneTimeRequest)
Worker.kt
:
class LocationWorker(
context: Context,
workerParams: WorkerParameters
): CoroutineWorker(context, workerParams) {
override suspend fun doWork(): Result {
// ... (1. Getting the location and storing it in a local database)
if (isNetworkAvailable(applicationContext)) {
// Always get here when the app is visible on-screen
Log.d("LocationWorker", "Uploading location.")
// ... (2. Uploading the data from the database to a remote API)
} else {
// Always get here when not having the app on-screen
Log.d("LocationWorker", "Network not available.")
}
}
private fun isNetworkAvailable(context: Context): Boolean {
val connectivityManager = context.getSystemService(ConnectivityManager::class.java)
val network = connectivityManager.activeNetwork ?: return false
val capabilities = connectivityManager.getNetworkCapabilities(network) ?: return false
return capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
}
I ensured that the device itself has WiFi enabled, the app is not stripped of permissions when unused and all permissions are allowed.
Minimum SDK version is 29 (Android 10).
Update:
Sometimes the network connection works flawlessly in the background. Sometimes not. Sometimes it fails two times and then miraculously it works on the third try. I've seen a lot of combinations now, with no recognizable deterministic pattern.
Now the issue is that it doesn't work reliably (more like coin-flip).
I've created a minimal example of the problem on GitHub.
The second commit shows all that there is to the application (plus a README.md
).
Check it out, test it according to the instructions in the README.md
and observe the problem.
Maybe this issue exists only on my emulator and not on real devices - I'm testing this right now...
Indeed the issue only exists on my emulator in Android Studio.
On real devices the network operations in the background work flawlessly, too. The WorkManager work even "works" when the app is completely closed.
So the reason for this issue seems to be that emulators might handle network access differently than real devices when apps are in the background.
This is weird and not officially documented as far as I know.
So, when in doubt, test your app on a real device to check whether the problem also exists in the field and not just in the emulated development environment.