Android 6.0 上的 Retrofit 在连接到 Access Point 后进行 Http 调用时出现问题
重现步骤:
- 连接到 Esp8266 接入点
- 进行 http 调用http://192.168.4.1 http://192.168.4.1(esp8266接入点的默认网关)
WIFI的IP地址是192.168.4.2
- 它抛出以下异常
我在 Android 5.1 上尝试过相同的操作,相同的代码可以完美运行
java.net.SocketException:套接字失败:ENONET(机器不在网络上)
在 libcore.io.IoBridge.socket(IoBridge.java:619)
在 java.net.PlainSocketImpl.create(PlainSocketImpl.java:198)
在 java.net.Socket.checkOpenAndCreate(Socket.java:689)
在 java.net.Socket.setSoTimeout(Socket.java:543)
在
okhttp3.internal.io.RealConnection.connectSocket(RealConnection.java:183)
在
okhttp3.internal.io.RealConnection.buildConnection(RealConnection.java:170)
在 okhttp3.internal.io.RealConnection.connect(RealConnection.java:111)
在
okhttp3.internal.http.StreamAllocation.findConnection(StreamAllocation.java:187)
在
okhttp3.internal.http.StreamAllocation.findHealthyConnection(StreamAllocation.java:123)
在
okhttp3.internal.http.StreamAllocation.newStream(StreamAllocation.java:93)
在 okhttp3.internal.http.HttpEngine.connect(HttpEngine.java:296)
在 okhttp3.internal.http.HttpEngine.sendRequest(HttpEngine.java:248)
在 okhttp3.RealCall.getResponse(RealCall.java:243)
在
okhttp3.RealCall$ApplicationInterceptorChain.proceed(RealCall.java:201)
在 okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:163)
在 okhttp3.RealCall.access$100(RealCall.java:30)
在 okhttp3.RealCall$AsyncCall.execute(RealCall.java:127)
在 okhttp3.internal.NamedRunnable.run(NamedRunnable.java:32)
在
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113
在
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
在 java.lang.Thread.run(Thread.java:818)
导致:android.system.ErrnoException:套接字失败:ENONET
(机器未联网)
在 libcore.io.Posix.socket(本机方法)
在 libcore.io.BlockGuardOs.socket(BlockGuardOs.java:282)
在 libcore.io.IoBridge.socket(IoBridge.java:604)
在 java.net.PlainSocketImpl.create(PlainSocketImpl.java:198)
在 java.net.Socket.checkOpenAndCreate(Socket.java:689)
在 java.net.Socket.setSoTimeout(Socket.java:543)
在 okhttp3.internal.io.RealConnection.connectSocket(RealConnection.java:183)
在
okhttp3.internal.io.RealConnection.buildConnection(RealConnection.java:170)
在
okhttp3.internal.io.RealConnection.connect(RealConnection.java:111)
在
okhttp3.internal.http.StreamAllocation.findConnection(StreamAllocation.java:187)
在
okhttp3.internal.http.StreamAllocation.findHealthyConnection(StreamAllocation.java:123)
在 okhttp3.internal.http.StreamAllocation.newStream(StreamAllocation.java:93)
在 okhttp3.internal.http.HttpEngine.connect(HttpEngine.java:296)
在 okhttp3.internal.http.HttpEngine.sendRequest(HttpEngine.java:248)
在 okhttp3.RealCall.getResponse(RealCall.java:243)
在 okhttp3.RealCall$ApplicationInterceptorChain.proceed(RealCall.java:201)
在
okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:163)
在 okhttp3.RealCall.access$100(RealCall.java:30)
在 okhttp3.RealCall$AsyncCall.execute(RealCall.java:127)
在 okhttp3.internal.NamedRunnable.run(NamedRunnable.java:32)
在
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113
在
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588
在 java.lang.Thread.run(Thread.java:818)
Problem
Error ENONET
意思是NetworkInfo.isConnected()
回报false
指示网络连接是否存在并且可以
建立连接并传递数据。
在尝试执行数据事务之前始终调用此方法。
Solution
生成一个等待 Wifi 网络的守护线程(由下式给出)ssid
)“完全”连接(见上文)并致电您的callback
与任一true
(连接成功)或false
(超时或错误)。
执行
private ConnectivityManager connectivity = ...;
private WifiManager wifi = ...;
private void waitForWifi(final String ssid, final Consumer<Boolean> callback) {
final Thread thread = new Thread(() -> {
for (int i = 0; i < 300; i++) {
final WifiInfo info = wifi.getConnectionInfo();
NetworkInfo networkInfo = null;
for (final Network network : connectivity.getAllNetworks()) {
final NetworkCapabilities capabilities = connectivity.getNetworkCapabilities(network);
if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
networkInfo = connectivity.getNetworkInfo(network);
break;
}
}
if (info != null && info.ssid == ssid && networkInfo != null && networkInfo.isConnected()) {
callback.accept(true);
return;
}
Thread.sleep(100);
}
callback.accept(false);
});
thread.setDaemon(true);
thread.start();
}
Notes
-
ssid
必须用双引号引起来(参见wifiConfiguration.SSID
)
-
ConnectivityManager.getAllNetworks()
需要许可ACCESS_NETWORK_STATE
-
WifiManager.getConnectionInfo()
需要权限ACCESS_NETWORK_STATE
and ACCESS_COARSE_LOCATION
(运行时权限)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)