Android平台EIdResolveError/EIdConnectTimeout问题求助
Android平台Indy组件DNS解析异常(EIdResolveError)排查与解决方案
问题背景
仅在Android 7、9、11版本出现无法稳定复现的DNS解析异常:应用已获取并启用网络权限,启动时调用基于WSDL生成的WebService接口,偶尔抛出EIdResolveError(提示No address associated with hostname),多次重试后转为EIdConnectTimeout。重启手机后问题消失,但2-3天后会复发。其他平台无此问题,adb未检测到异常,且设备通过ping命令或浏览器可正常访问目标域名my-backend.test.com。
相关调用代码:
function TXXVersion.GetVersion : IXXVersion; var LVSPortType : VersionServicePortType; // generate from wsdl LIdURI: TIdURI; begin Result := nil; if Assigned(FWebServiceHelper.PrepareCall(VersionServicePortType, LVSPortType, false)) then begin LIdURI := TIdURI.Create('https://my-backend.test.com'); try Result := ParseVersion(LVSPortType.GetVersion, LIdURI.Host); finally LIdURI.Free; end; end; end;
报错信息:
An unexpected error (EIdResolveError) occurred with message: Error resolving Address my-backend.test.com: No address associated with hostname (7)
可能的解决方案
1. 强制Indy使用系统DNS解析器
Indy默认自带DNS解析逻辑,与Android系统的DNS缓存/解析机制可能存在兼容性问题。可全局启用系统解析器,让Indy调用Android系统原生解析接口:
// 在应用初始化阶段添加 IdGlobal.GIdUseOSResolver := True;
2. 增加解析失败后的缓存清理与重试
Indy会缓存DNS解析结果,若缓存了失效记录,即使系统已更新DNS,应用仍会使用旧数据。可在捕获异常时清理缓存并重试:
function TXXVersion.GetVersion : IXXVersion; var LVSPortType : VersionServicePortType; LIdURI: TIdURI; begin Result := nil; if Assigned(FWebServiceHelper.PrepareCall(VersionServicePortType, LVSPortType, false)) then begin LIdURI := TIdURI.Create('https://my-backend.test.com'); try try Result := ParseVersion(LVSPortType.GetVersion, LIdURI.Host); except on E: EIdResolveError do begin // 清空Indy的DNS缓存 if Assigned(LVSPortType.HTTP.IOHandler) and Assigned(LVSPortType.HTTP.IOHandler.Resolver) then LVSPortType.HTTP.IOHandler.Resolver.ClearCache; // 重试一次 Result := ParseVersion(LVSPortType.GetVersion, LIdURI.Host); end; end; finally LIdURI.Free; end; end; end;
3. 检查Android私有DNS设置
Android 9及以上版本支持私有DNS(DNS over TLS),若设备开启此功能,可能与旧版本Indy的解析逻辑冲突。可提示用户暂时关闭私有DNS,或升级Indy到支持DoT的版本。
4. 升级Indy组件至最新稳定版
旧版本Indy在Android平台的DNS处理存在已知bug(如IPv6兼容问题、系统DNS变更同步不及时),升级到最新版可修复此类问题。
5. 手动指定DNS服务器
若系统DNS不稳定,可强制Indy使用公共DNS服务器:
if Assigned(LVSPortType.HTTP.IOHandler) and Assigned(LVSPortType.HTTP.IOHandler.Resolver) then begin LVSPortType.HTTP.IOHandler.Resolver.DNS.Clear; LVSPortType.HTTP.IOHandler.Resolver.DNS.Add('8.8.8.8'); // Google公共DNS LVSPortType.HTTP.IOHandler.Resolver.DNS.Add('8.8.4.4'); end;
内容的提问来源于stack exchange,提问作者Haifisch
相关产品推荐
相关产品推荐

