admin管理员组

文章数量:1401922

I set a Worker to run at night, with setRequiredNetworkType(NetworkType.CONNECTED) and during the run, one of the errors occurred:

Unable to resolve host "script.googleapis": No address associated with hostname

android.system.GaiException: android_getaddrinfo failed: EAI_NODATA (No address associated with hostname)

One Result.retry() also does not help. The second run fails too.

Crashlytics from Firebase shows that it happens only on Android 14. Before sending a request, check NetworkStateTracker.isNetworkAvailable which returns true.

At daytime, when the device is recently used, errors do not occur. The app is whitelisted for battery optimization, and the device has a Wi-Fi connection during the night. I suspect it is disconnected and not restored when the Worker starts. So, how to do background work with the network if even WorkManager fails to detect network connection?

private fun enqueueProgramWorkers(triggers: List<QueueDateTriggerModel>) {
    triggers.forEach {
        val constraints = Constraints.Builder()
            .setRequiredNetworkType(NetworkType.CONNECTED)
            .build()

        val tag = createTriggerTag(it.trigger.id)
        val request = OneTimeWorkRequestBuilder<ProgramWorker>()
            .setConstraints(constraints)
            .setInputData(ProgramWorker.workDataOf(it.trigger.programId, EnqueueSource.DATE_TRIGGER, it.trigger.id))
            .setInitialDelay(it.delayToLaunch, TimeUnit.MILLISECONDS)
            .addTag(tag)
            .build()
        workManager.enqueueUniqueWork(tag, ExistingWorkPolicy.REPLACE, request)
    }
}

@Singleton
class NetworkStateTracker @Inject constructor(
    @ApplicationContext context: Context,
) {

    private var connectivityManager: ConnectivityManager = context.getSystemService(ConnectivityManager::class.java)
    private val networkCallback = object : ConnectivityManager.NetworkCallback() {
        override fun onAvailable(network: Network) {
            _networkState.value = true
        }

        override fun onLost(network: Network) {
            _networkState.value = false
        }

        override fun onCapabilitiesChanged(network: Network, networkCapabilities: NetworkCapabilities) {

        }
    }

    private val _networkState = MutableStateFlow(checkCurrentConnectivity())
    val isNetworkAvailable = _networkState.asStateFlow()

    init{
        val networkRequest = NetworkRequest.Builder()
            .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
            .build()

        connectivityManager.registerNetworkCallback(networkRequest, networkCallback)
    }

    private fun checkCurrentConnectivity(): Boolean {
        val network = connectivityManager.activeNetwork ?: return false
        val capabilities = connectivityManager.getNetworkCapabilities(network) ?: return false
        return capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
    }


}

I set a Worker to run at night, with setRequiredNetworkType(NetworkType.CONNECTED) and during the run, one of the errors occurred:

Unable to resolve host "script.googleapis": No address associated with hostname

android.system.GaiException: android_getaddrinfo failed: EAI_NODATA (No address associated with hostname)

One Result.retry() also does not help. The second run fails too.

Crashlytics from Firebase shows that it happens only on Android 14. Before sending a request, check NetworkStateTracker.isNetworkAvailable which returns true.

At daytime, when the device is recently used, errors do not occur. The app is whitelisted for battery optimization, and the device has a Wi-Fi connection during the night. I suspect it is disconnected and not restored when the Worker starts. So, how to do background work with the network if even WorkManager fails to detect network connection?

private fun enqueueProgramWorkers(triggers: List<QueueDateTriggerModel>) {
    triggers.forEach {
        val constraints = Constraints.Builder()
            .setRequiredNetworkType(NetworkType.CONNECTED)
            .build()

        val tag = createTriggerTag(it.trigger.id)
        val request = OneTimeWorkRequestBuilder<ProgramWorker>()
            .setConstraints(constraints)
            .setInputData(ProgramWorker.workDataOf(it.trigger.programId, EnqueueSource.DATE_TRIGGER, it.trigger.id))
            .setInitialDelay(it.delayToLaunch, TimeUnit.MILLISECONDS)
            .addTag(tag)
            .build()
        workManager.enqueueUniqueWork(tag, ExistingWorkPolicy.REPLACE, request)
    }
}

@Singleton
class NetworkStateTracker @Inject constructor(
    @ApplicationContext context: Context,
) {

    private var connectivityManager: ConnectivityManager = context.getSystemService(ConnectivityManager::class.java)
    private val networkCallback = object : ConnectivityManager.NetworkCallback() {
        override fun onAvailable(network: Network) {
            _networkState.value = true
        }

        override fun onLost(network: Network) {
            _networkState.value = false
        }

        override fun onCapabilitiesChanged(network: Network, networkCapabilities: NetworkCapabilities) {

        }
    }

    private val _networkState = MutableStateFlow(checkCurrentConnectivity())
    val isNetworkAvailable = _networkState.asStateFlow()

    init{
        val networkRequest = NetworkRequest.Builder()
            .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
            .build()

        connectivityManager.registerNetworkCallback(networkRequest, networkCallback)
    }

    private fun checkCurrentConnectivity(): Boolean {
        val network = connectivityManager.activeNetwork ?: return false
        val capabilities = connectivityManager.getNetworkCapabilities(network) ?: return false
        return capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
    }


}
Share Improve this question edited Mar 23 at 8:36 Viewed asked Mar 23 at 8:22 ViewedViewed 1,3833 gold badges17 silver badges51 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 0

The core issue is that Android 14's Doze mode is more aggressive about network connections than previous versions. Even though the system reports a network is available, it may not actually maintain the connection or wake it up properly for background tasks.

Your best approach is likely a combination of:

  1. Active network validation before attempting network operations

  2. Proper exponential backoff and retry logic

  3. For critical tasks, using a foreground service with higher priority

If you can share your Worker class implementation then I could offer more help.

本文标签: androidWorkManager and error no address associated with hostnameStack Overflow