我部署的应用程序在 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()
调用。如果缺少绑定(bind)调用,则该错误意味着套接字正在尝试通过蜂窝网络进行连接。 (注意:activity.logContent()
是屏幕日志,因此在未连接到调试器时更容易查看发生的情况)。
知道出了什么问题吗?
最佳答案
经过几天的咒骂,我相信我已经找到了问题所在,从而找到了解决方案:
问题的发生是由于 android 版本的一些变化(我推测是 9.0,即使 API 21 上发生了其他变化),特别是在创建套接字时,如果系统检测到存在“更好的”网络(访问互联网、高信号等)套接字创建指的是该网络,而不是您想要的 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();
}
}
}
}
实际上浏览设备中存在的网络,当您找到 Activity 的 WiFi 时,您什么也不做,只需利用此功能来确保获得正确的套接字:
getSocketFactory().createSocket()
现在你有了工作套接字!
就我而言,它现在工作得很好,如果有人找到更好的解决方案,我们会很欢迎,但目前这是我发现的让一切像以前版本的 android 一样工作的唯一方法。
关于java - Android 9 - 启用移动数据时套接字连接超时,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56066632/