Android 9-启用移动数据后,套接字连接超时

时间:2019-05-09 19:51:38

标签: java android sockets android-wifi android-9.0-pie

我有一个已部署的应用程序,该应用程序在Android 9上无法运行。其部分功能是通过访问点网络配置一个模块,以允许该模块连接到用户的本地网络。

我有检测和连接到正确的WIFI网络的代码,但是当我尝试打开设备的套接字时,它失败-仅在Android 9上且仅在启用了移动数据的情况下。如果我在设备上手动禁用移动数据,则一切运行正常。

Socket open() {
    Socket sock = new Socket(Proxy.NO_PROXY);
    try {
        sock.bind(new InetSocketAddress(localIpAddress(), 50000));
    } catch (IOException e) {
        activity.logContent("Warning: Failed to bind socket : " + e.toString());
    }
    try {
        sock.connect(new InetSocketAddress("192.168.17.1", 5555), (int)5000);
    } catch (IOException e) {
        // This catch fires when Mobile Data is on.
        activity.logContent("Connected to " + activity.mWifiManager.getConnectionInfo().getSSID());
        activity.logContent("Couldn't open socket : " + e.toString());
    }
    return sock;
}

无论是否有Proxy.NO_PROXY以及有没有bind()调用,我都尝试过。如果缺少绑定调用,则错误表明套接字正在尝试通过单元网络进行连接。 (注意:activity.logContent()是一个屏幕日志,因此在未连接调试器时更容易查看正在发生的情况。)

有什么想法吗?

3 个答案:

答案 0 :(得分:1)

经过几天的恳求,我相信我已经找到了问题的所在,因此也找到了解决方案:

由于android版本的某些更改(即使在API 21上进行了其他更改,我也认为是9.0),特别是在创建套接字时,如果系统检测到存在“更好的网络(访问互联网,高信号等),套接字创建是指该网络,而不是您想要的wifi网络。

我寻找了强制在wifi网络(我想要的网络)上创建套接字的方法,而我发现的唯一方法是:

简单地放置而不是:

Socket sock = new Socket();

要做:

ConnectivityManager connectivity = (ConnectivityManager) MyApp.getContext().getSystemService(Context.CONNECTIVITY_SERVICE);
                if (connectivity != null)
                {
                    for (Network network : connectivity.getAllNetworks())
                    {
                        NetworkInfo networkInfo = connectivity.getNetworkInfo(network);

                        if (networkInfo != null && networkInfo.getType() == ConnectivityManager.TYPE_WIFI)
                        {
                            if (networkInfo.isConnected())
                            {
                                Socket sock =  network.getSocketFactory().createSocket();
                            }
                        }
                    }
            }

实际上浏览设备中存在的网络,当您发现活动的wifi时,您什么也没做,只能利用此功能来确定正确的插座:

getSocketFactory()。createSocket()

现在您有了工作插座!

就我而言,它现在可以完美运行,如果有人找到更好的解决方案,这是值得欢迎的,但是目前,这是我发现使所有功能都像以前版本的android一样工作的唯一方法。

答案 1 :(得分:0)

在Android 9中,存在有关网络的安全配置:Android security config

在network_security_config中添加您的域可能会解决您的问题。我在network_security_config.xml中有此文件:

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <domain-config cleartextTrafficPermitted="true">
        <domain includeSubdomains="true">119.xxx.xxx.xxx</domain>
    </domain-config>
</network-security-config>

答案 2 :(得分:0)

我不确定发生这种情况的确切原因。但是,当您打开移动数据并且仅使用移动数据连接到Internet(考虑关闭wifi)时,它将从蜂窝网络获取IP地址,而该IP网络在您的家庭网络中不再连接。因此,期望这种超时情况是微不足道的,因为它无法到达以192.168....开头的家庭网络的专用IP地址。

现在,我的困惑是,即使打开了移动数据,并且同时打开了wifi和移动数据,设备仍应默认连接到wifi。

因此,我建议您检查以下内容。

  • Android 9(Pie)引入了特殊的Wifi preference,可防止自动连接到公共网络。您可以考虑检查设置。
  • 请检查您设备的IP地址,并检查其IP地址是否以192.168....开头。如果不是,那么肯定是从蜂窝网络获取IP地址,因此它无法到达家庭网络的私有IP地址。