使用Retrofit开发Android Widget时遇UnknownHostException求助
问题:Android Widget真机网络请求失败(UnknownHostException)
开发一款Android Widget用于展示Github Pages托管的JSON数据,使用Retrofit实现网络请求。在Android Studio模拟器中运行正常,但生成APK安装到真机后出现错误:
java.net.UnknownHostException: Unable to resolve host "host": No Address associated
尝试请求google.com同样无法解析主机,已在Manifest中添加以下权限但问题未解决:
<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
Retrofit代码实现
@Keep object RetrofitService { private val numbersRetrofit: Retrofit = Retrofit.Builder() .baseUrl("https://host.github.io/") .client(OkHttpClient()) .addConverterFactory(GsonConverterFactory.create()) .build() fun getGamesApiService(): GamesApiService { return numbersRetrofit.create(GamesApiService::class.java) } }
更新:网络状态检测结果
使用以下方法检测网络状态,返回netInfo.isConnected为false:
private fun isOnline(mgr: ConnectivityManager): Boolean { val netInfo = mgr.activeNetworkInfo return if (netInfo != null && netInfo.isConnected) { true } else false }
解决方法
1. 修复网络状态检测逻辑(适配Android 10+)
activeNetworkInfo在API 29已被废弃,且无法准确判断网络是否可正常访问。改用NetworkCapabilities检测:
private fun isOnline(context: Context): Boolean { val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager val activeNetwork = connectivityManager.activeNetwork ?: return false val networkCapabilities = connectivityManager.getNetworkCapabilities(activeNetwork) ?: return false // 验证网络是否具备互联网访问能力且已通过验证 return networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) && networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED) }
2. 适配Android后台网络访问限制
Widget属于后台组件,Android 8.0+对后台网络请求有严格限制:
- 改用
WorkManager调度网络请求:避免在Widget的onUpdate中直接发起请求,通过WorkManager在后台执行网络操作,完成后更新Widget数据。 - 合理申请权限(可选):若需长期后台同步,可在Manifest中为相关组件添加
android:foregroundServiceType="dataSync",或申请ACCESS_BACKGROUND_LOCATION权限(需用户授权),注意合规性。
3. 优化OkHttpClient配置
添加超时设置并指定DNS服务器,避免真机DNS解析异常:
val okHttpClient = OkHttpClient.Builder() .dns(Dns.SYSTEM) // 或自定义DNS:Dns.Builder().add("8.8.8.8").build() .connectTimeout(30, TimeUnit.SECONDS) .readTimeout(30, TimeUnit.SECONDS) .writeTimeout(30, TimeUnit.SECONDS) .build()
4. 检查网络安全配置(Android 9+)
若存在域名访问限制,在res/xml/network_security_config.xml中添加配置:
<?xml version="1.0" encoding="utf-8"?> <network-security-config> <domain-config cleartextTrafficPermitted="false"> <domain includeSubdomains="true">github.io</domain> </domain-config> </network-security-config>
并在Manifest的application标签中引用:
android:networkSecurityConfig="@xml/network_security_config"
5. 验证APK混淆规则
若使用release构建,确保Retrofit相关类未被混淆,在proguard-rules.pro中添加:
-keep class retrofit2.** { *; } -keep interface retrofit2.** { *; } -keepclasseswithmembers class * { @retrofit2.http.* <methods>; } -keep class com.yourpackage.GamesApiService { *; } // 替换为你的接口类路径
6. 排查真机本地网络问题
- 切换网络环境:尝试切换WiFi/移动数据,排除单一网络故障。
- 手动设置DNS:将真机DNS改为公共DNS(如8.8.8.8、1.1.1.1),测试域名解析是否正常。
内容的提问来源于stack exchange,提问作者Marco
相关产品推荐
相关产品推荐

