Android快捷设置控制WiFi插座出现SocketTimeoutException问题求助
Android快捷设置Tile控制WiFi插座:仅USB调试时生效的问题解决
问题重现
入手带WiFi功能的插座控制台灯,浏览器调用URL可正常开关。开发Android快捷设置开关后,解决了明文HTTP限制问题,但仅手机连接USB并开启调试时能正常控制,拔掉USB后触发SocketTimeoutException,错误堆栈如下:
java.net.SocketTimeoutException: failed to connect to /xxx.xxx.xxx.110 (port 80) from /xxx.xxx.xxx.120 (port 46074) after 5000ms at libcore.io.IoBridge.connectErrno(IoBridge.java:235) at libcore.io.IoBridge.connect(IoBridge.java:179) at java.net.PlainSocketImpl.socketConnect(PlainSocketImpl.java:142) at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:390) at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:230) at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:212) at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:436) at java.net.Socket.connect(Socket.java:646) at com.android.okhttp.internal.Platform.connectSocket(Platform.java:182) at com.android.okhttp.internal.io.RealConnection.connectSocket(RealConnection.java:145) at com.android.okhttp.internal.io.RealConnection.connect(RealConnection.java:116) at com.android.okhttp.internal.http.StreamAllocation.findConnection(StreamAllocation.java:186) at com.android.okhttp.internal.http.StreamAllocation.findHealthyConnection(StreamAllocation.java:128) at com.android.okhttp.internal.http.StreamAllocation.newStream(StreamAllocation.java:97) at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:289) at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:232) at com.android.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:465) at com.android.okhttp.internal.huc.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:131) at com.mine.qstile.MyQSTileService$1.run(MyQSTileService.java:93) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:644) at java.lang.Thread.run(Thread.java:1012)
解决方案
1. 解除电池优化限制
Android 8.0+的后台电池优化会阻断QSTileService的网络请求:
- 手动设置:打开「设置」→「电池」→「电池优化」,找到你的应用,设置为不允许优化
- 代码申请权限(可选,需用户授权):
在AndroidManifest.xml添加权限:
首次启动时弹出申请对话框:<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { Intent intent = new Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS); intent.setData(Uri.parse("package:" + getPackageName())); startActivity(intent); }
2. 确认设备处于同一WiFi局域网
USB调试时可能自动使用电脑代理,拔掉USB后需确保手机和插座在同一WiFi:
- 下拉状态栏确认WiFi已连接,且SSID与插座一致
- 用手机浏览器直接访问插座控制URL,验证网络连通性
3. 添加后台网络相关权限
Android 10+对后台网络访问有严格限制,需补充权限:
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" /> <!-- 部分机型需此权限关联WiFi定位 -->
Android 12+可额外申请通知权限,提升后台优先级:
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
4. 调整网络请求超时与重试逻辑
当前5秒超时可能不足以应对拔掉USB后的网络延迟:
HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setConnectTimeout(10000); // 延长至10秒连接超时 connection.setReadTimeout(10000); // 延长至10秒读取超时
添加重试逻辑,避免单次超时失败:
int retryCount = 0; boolean success = false; while (retryCount < 2 && !success) { try { // 执行网络请求逻辑 success = true; } catch (SocketTimeoutException e) { retryCount++; } }
5. 排查厂商系统后台限制
国内厂商(小米、华为、OPPO等)有额外管控:
- 进入应用「信息页面」→「电池用量」→ 设置为无限制
- 开启「自启动权限」和「后台运行权限」
- 将应用添加到系统「后台保护名单」或「白名单」
6. 清除代理设置
USB调试时Android Studio可能设置了代理,拔掉后需清除:
- 手动检查:「设置」→「网络和互联网」→「代理」,设置为无
- 代码强制清除代理:
System.setProperty("http.proxyHost", ""); System.setProperty("http.proxyPort", ""); System.setProperty("https.proxyHost", ""); System.setProperty("https.proxyPort", "");
内容的提问来源于stack exchange,提问作者kopi_b
相关产品推荐
相关产品推荐

