Android API 35中MockWebServer启动失败的原因及解决咨询
问题背景
我有一个基于API 34的应用,使用MockWebServer 5.0.0-alpha.12开展测试,仅在需Mock的测试中触发该服务,MockWebServer类在8080端口初始化,代码如下:
class MockedkWebServer { ... init { val mockServer = MockWebServer() mockServer.start(8080) ... } ... }
该配置在API 34上运行正常,但在API 35设备上执行Mock测试时失败,调用mockServer.start(8080)启动MockWebServer1秒后抛出错误:
java.net.UnknownHostException: Unable to resolve host "localhost"; No address associated with hostname.
尝试在network_config.xml中添加部分IP地址后测试可运行但启动时仍可能失败,配置如下:
<domain-config cleartextTrafficPermitted="true"> <domain includeSubdomains="true">localhost</domain> <domain includeSubdomains="false">10.0.2.2</domain> <domain includeSubdomains="false">10.0.2.3</domain> <!-- added --> <domain includeSubdomains="false">10.0.3.2</domain> <domain includeSubdomains="true">10.0.2.15</domain> <!-- added --> <domain includeSubdomains="true">10.0.2.16</domain><!-- added --> </domain-config>
问题成因
- API 35网络管控升级:Android 14(API 35)对localhost域名解析、测试进程的网络访问权限做了更严格的限制,默认情况下可能阻止测试进程将localhost解析为环回地址,导致服务启动时无法找到对应主机。
- MockWebServer预览版适配不足:使用的
5.0.0-alpha.12是预览版本,未针对API 35的网络行为变更做充分适配,存在绑定地址或解析逻辑的兼容性问题。 - 固定IP配置的局限性:手动添加的10.0.x.x系列地址是模拟器特定网关/内网地址,但API 35可能为测试进程分配随机环回地址,或网络命名空间与API 34不同,导致固定IP无法覆盖所有场景,出现偶发启动失败。
稳定解决方案
1. 绑定环回地址启动MockWebServer
直接使用系统环回地址启动服务,绕过localhost解析环节,从根源避免解析失败:
class MockedkWebServer { ... init { val mockServer = MockWebServer() // 绑定到环回地址,无需依赖localhost解析 mockServer.start(InetAddress.getLoopbackAddress(), 8080) ... } ... }
InetAddress.getLoopbackAddress()会返回当前系统的环回IP(通常是127.0.0.1或::1),确保服务能稳定绑定。
2. 升级MockWebServer到稳定适配版本
放弃使用alpha预览版,升级到官方最新的稳定版本(如5.x正式版及以上)。正式版本会针对API 35的网络变更做适配修复,解决版本兼容性导致的启动问题。
3. 优化network_config.xml配置
在网络配置中明确包含所有环回地址,覆盖IPv4和IPv6场景,同时保留模拟器常用地址:
<domain-config cleartextTrafficPermitted="true"> <!-- 允许IPv4/IPv6环回地址 --> <domain includeSubdomains="true">127.0.0.1</domain> <domain includeSubdomains="true">::1</domain> <domain includeSubdomains="true">localhost</domain> <!-- 模拟器常用调试地址 --> <domain includeSubdomains="false">10.0.2.2</domain> <domain includeSubdomains="false">10.0.3.2</domain> </domain-config>
同时确保测试用的AndroidManifest.xml中包含必要的网络权限:
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
4. 测试前强制初始化localhost映射
在测试启动前,手动向/etc/hosts添加localhost到环回地址的映射,确保系统能正确解析:
@BeforeClass fun setupLocalhostMapping() { val hostsFile = File("/etc/hosts") val hostsContent = hostsFile.readText() if (!hostsContent.contains("127.0.0.1 localhost") || !hostsContent.contains("::1 localhost")) { hostsFile.appendText("\n127.0.0.1 localhost\n::1 localhost") } }
注意:该方法仅适用于模拟器或有root权限的测试设备,需确保测试进程具备写入/etc/hosts的权限。
内容的提问来源于stack exchange,提问作者AShX
相关产品推荐
相关产品推荐

