You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android 14下TCP/IP连接失败问题求助(附代码与堆栈信息)

Android 14下TCP Socket连接超时的代码级解决方案

问题描述

设备升级至Android 14后,自研APP使用以下代码创建TCP Socket连接时出现SocketTimeoutException:

Socket s = new Socket();
InetSocketAddress endpoint = new InetSocketAddress("192.168.137.1", 50024);
s.connect(endpoint, 3000);

对应的错误堆栈:

java.net.SocketTimeoutException: failed to connect to /192.168.137.1 (port 50024) from /172.27.250.17 (port 42916) after 3000ms
        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)

手动重置WiFi可临时规避问题,需代码层面的永久解决方案。

问题分析

从堆栈信息可见,APP尝试从172.27.250.17(非目标WiFi网段)连接目标192.168.137.1,说明Android 14的网络路由逻辑可能优先选择了非预期的网络接口(如移动数据、其他WiFi)。重置WiFi会让系统重新选择正确的网卡,但需通过代码强制绑定Socket到目标WiFi的网络接口。

代码解决方案

1. 权限声明

在AndroidManifest.xml中添加必要权限:

<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <!-- Android 10+ 获取WiFi信息需定位权限 -->

2. 动态申请权限(Android 6+)

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
    String[] requiredPermissions = {
        Manifest.permission.ACCESS_FINE_LOCATION,
        Manifest.permission.CHANGE_NETWORK_STATE
    };
    boolean needRequest = false;
    for (String perm : requiredPermissions) {
        if (checkSelfPermission(perm) != PackageManager.PERMISSION_GRANTED) {
            needRequest = true;
            break;
        }
    }
    if (needRequest) {
        requestPermissions(requiredPermissions, 1001);
    }
}

3. 绑定Socket到目标WiFi网络

通过ConnectivityManager获取目标WiFi对应的Network对象,将Socket绑定到该网络后再发起连接:

// 获取系统服务
ConnectivityManager connManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
WifiManager wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);

Network targetNetwork = null;

// 方式1:获取当前已连接的WiFi网络
NetworkInfo activeNetworkInfo = connManager.getActiveNetworkInfo();
if (activeNetworkInfo != null 
    && activeNetworkInfo.getType() == ConnectivityManager.TYPE_WIFI 
    && activeNetworkInfo.isConnected()) {
    targetNetwork = connManager.getActiveNetwork();
}

// 方式2:根据SSID指定特定WiFi(如果需要连接固定SSID)
if (targetNetwork == null && wifiManager != null) {
    List<Network> allNetworks = connManager.getAllNetworks();
    String targetSsid = "\"你的目标WiFi名称\""; // 注意SSID返回值带双引号
    WifiInfo currentWifiInfo = wifiManager.getConnectionInfo();
    if (currentWifiInfo != null && targetSsid.equals(currentWifiInfo.getSSID())) {
        // 当前已连接目标WiFi,直接获取对应Network
        targetNetwork = connManager.getActiveNetwork();
    } else {
        // 遍历所有网络查找目标WiFi
        for (Network network : allNetworks) {
            NetworkInfo networkInfo = connManager.getNetworkInfo(network);
            if (networkInfo != null 
                && networkInfo.getType() == ConnectivityManager.TYPE_WIFI 
                && networkInfo.isConnected()) {
                targetNetwork = network;
                break;
            }
        }
    }
}

// 绑定Socket并发起连接
if (targetNetwork != null) {
    Socket socket = new Socket();
    try {
        // Android 6+支持绑定Network到Socket
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            targetNetwork.bindSocket(socket);
        }
        InetSocketAddress endpoint = new InetSocketAddress("192.168.137.1", 50024);
        socket.connect(endpoint, 3000);
        // 连接成功后的业务逻辑处理
    } catch (SocketTimeoutException e) {
        // 超时处理
        e.printStackTrace();
    } catch (IOException e) {
        // 其他IO异常处理
        e.printStackTrace();
    } finally {
        // 记得关闭Socket
        try {
            socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
} else {
    // 未找到目标WiFi网络,提示用户连接
    Toast.makeText(this, "请连接目标WiFi网络", Toast.LENGTH_SHORT).show();
}

原理说明

通过Network.bindSocket()方法,强制Socket使用指定的WiFi网络接口进行通信,避免Android 14系统在多网络环境下自动选择非预期路由的问题,从根源上解决连接超时问题,无需手动重置WiFi。

内容的提问来源于stack exchange,提问作者たなかたろう

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 00:00:32