Android 14下WorkManager夜间网络请求异常:无主机地址关联
问题分析与解决方案
核心问题拆解
- WorkManager网络约束局限性:
NetworkType.CONNECTED仅验证设备存在网络连接,不保证网络实际可访问互联网(比如Wi-Fi物理连接但路由器休眠、DNS缓存失效)。 - Android 14网络行为变化:系统对后台网络的休眠优化更严格,夜间Wi-Fi可能处于"假连接"状态(有连接标识但无实际数据通路)。
- 自定义NetworkStateTracker检查不充分:仅判断
NET_CAPABILITY_INTERNET,该标记仅表示网络具备互联网能力,不代表实际连通。
具体解决方案
1. 升级WorkManager约束,使用更严格的网络验证
将WorkRequest的网络约束从CONNECTED改为UNMETERED(针对Wi-Fi场景),或结合Android 10+的NET_CAPABILITY_VALIDATED能力,确保网络已通过系统验证可访问:
val constraints = Constraints.Builder() // Wi-Fi场景优先使用UNMETERED .setRequiredNetworkType(NetworkType.UNMETERED) // 添加网络验证能力要求(Android 10+) .setRequiredNetworkCapabilities( NetworkCapabilities.Builder() .addCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED) .build() ) .build()
2. Worker内部添加实际网络连通性校验
不要依赖外部状态检查,在Worker执行请求前,做一次实际的域名解析或轻量请求验证,确保网络真的可用:
private fun isNetworkReachable(host: String = "script.googleapis.com"): Boolean { return try { // 尝试解析目标域名,超时设为3秒 val address = InetAddress.getByName(host) address.isReachable(3000) } catch (e: IOException) { false } } // 在Worker的doWork()中使用 override fun doWork(): Result { if (!isNetworkReachable()) { // 网络不可用,返回重试 return Result.retry() } // 执行实际请求逻辑 // ... }
3. 配置指数退避重试策略
默认的Result.retry()重试间隔过短,可能网络还未恢复。在WorkRequest中设置指数退避,让重试间隔随次数递增:
val request = OneTimeWorkRequestBuilder<ProgramWorker>() .setConstraints(constraints) // 指数退避:初始延迟1分钟,每次重试间隔翻倍,最大延迟1小时 .setBackoffCriteria(BackoffPolicy.EXPONENTIAL, 1, TimeUnit.MINUTES) .setInputData(...) .build()
4. 适配Android 14 Wi-Fi休眠优化
- 引导用户开启Wi-Fi休眠保持:
设置 > 网络和互联网 > Wi-Fi > Wi-Fi偏好 > 睡眠期间保持Wi-Fi开启 - 在Worker中主动请求活跃网络并绑定,确保请求使用的网络处于活跃状态:
override fun doWork(): Result { val connectivityManager = getSystemService(ConnectivityManager::class.java) val networkRequest = NetworkRequest.Builder() .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) .addCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED) .build() val networkCallback = object : ConnectivityManager.NetworkCallback() { override fun onAvailable(network: Network) { // 绑定到该活跃网络执行请求 connectivityManager.bindProcessToNetwork(network) // 执行请求逻辑 // ... connectivityManager.unregisterNetworkCallback(this) } } connectivityManager.requestNetwork(networkRequest, networkCallback) // 注:若使用CoroutineWorker,可改用异步逻辑避免阻塞 // ... }
5. 修复NetworkStateTracker的网络检查逻辑
更新网络状态判断,加入NET_CAPABILITY_VALIDATED(Android 10+),确保状态反映实际连通性:
private fun checkCurrentConnectivity(): Boolean { val network = connectivityManager.activeNetwork ?: return false val capabilities = connectivityManager.getNetworkCapabilities(network) ?: return false // 同时检查互联网能力和已验证状态 return capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) && capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED) } // 补充onCapabilitiesChanged的状态更新,实时同步网络验证状态 override fun onCapabilitiesChanged(network: Network, networkCapabilities: NetworkCapabilities) { val isConnected = networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) && networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED) _networkState.value = isConnected }
内容的提问来源于stack exchange,提问作者Viewed
相关产品推荐
相关产品推荐

