Android Release模式下网络连接检测功能失效问题求助
嘿,我之前碰到过一模一样的问题!你的代码在Debug和iOS上都正常,但Android Release模式下死活返回false,大概率是这几个坑导致的,咱们一步步来解决:
1. 先排查R8/ProGuard混淆的锅
Release模式下R8会自动优化代码,它可能误判java.net.InternetAddress这类网络相关的类是“无用代码”,直接给你移除了,导致DNS查询失败。
解决办法:
在你的proguard-rules.pro文件里加上这两行混淆规则,保住这些关键类:
-keep class java.net.InternetAddress { *; } -keep class java.net.SocketException { *; }
2. Android 9+的明文网络限制搞事情
从Android 9开始,系统默认禁止明文HTTP请求,虽然你用的是DNS查询(不是HTTP),但有些严格的网络安全配置可能会影响DNS解析的正常执行。
解决办法:
新建或修改res/xml/network_security_config.xml,添加允许明文流量的配置:
<?xml version="1.0" encoding="utf-8"?> <network-security-config> <!-- 允许google.com的明文流量,也可以改成允许所有域名 --> <domain-config cleartextTrafficPermitted="true"> <domain includeSubdomains="true">google.com</domain> </domain-config> </network-security-config>
然后在AndroidManifest.xml的<application>标签里引用这个配置:
<application ... android:networkSecurityConfig="@xml/network_security_config"> ... </application>
3. DNS解析失败(比如google.com被屏蔽)
有些地区或网络环境下,google.com的DNS解析可能不通,哪怕你有网络连接,lookup也会返回空结果。
解决办法:换个更可靠的检测目标
比如直接用Cloudflare的公共DNS IP(1.1.1.1),或者国内的baidu.com,甚至多检测几个域名提高容错率:
Future<bool> checkInternetConnection() async { // 同时检测多个域名,只要有一个能解析通就返回true final targets = ['1.1.1.1', 'baidu.com', 'google.com']; for (var target in targets) { try { final result = await InternetAddress.lookup(target); if (result.isNotEmpty && result[0].rawAddress.isNotEmpty) { return true; } } on SocketException catch (_) { // 这个目标不行,换下一个 continue; } } return false; }
4. 确认网络权限没丢
虽然Debug模式正常,但有时候Release打包时可能不小心把权限配置搞丢了,再检查下AndroidManifest.xml里有没有这两行:
<uses-permission android:name="android.permission.INTERNET" /> <!-- 可选,但能更准确获取系统网络状态 --> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
INTERNET是正常权限,不需要动态申请,只要加了就生效。
终极方案:用connectivity_plus库
如果上面的方法都不好使,建议换成官方推荐的connectivity_plus库,它专门处理网络检测,兼容性比自己写的代码好太多:
首先在pubspec.yaml加依赖:
dependencies: connectivity_plus: ^5.0.1 # 记得用最新版本
然后修改检测函数:
import 'package:connectivity_plus/connectivity_plus.dart'; Future<bool> checkInternetConnection() async { // 先检测系统的网络状态 final connectivityResult = await Connectivity().checkConnectivity(); if (connectivityResult == ConnectivityResult.none) { return false; } // 再做一次实际的网络请求验证(避免假连接) try { final result = await InternetAddress.lookup('1.1.1.1'); return result.isNotEmpty && result[0].rawAddress.isNotEmpty; } on SocketException catch (_) { return false; } }
这个库会先判断系统有没有网络,再做实际的DNS查询,双重验证更靠谱。
内容的提问来源于stack exchange,提问作者BraveEvidence




