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
1 Answer
Reset to default 0The 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:
Active network validation before attempting network operations
Proper exponential backoff and retry logic
For critical tasks, using a foreground service with higher priority
If you can share your Worker class implementation then I could offer more help.
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744293203a4567131.html
评论列表(0条)