One Plus上与ESP8266的Android连接(Android 6.0.1)

问题描述 投票:1回答:1

Android 6.0上的改造在连接到Access Point后进行Http调用时出现问题

重现步骤:

  1. 连接到Esp8266接入点
  2. http://192.168.4.1进行http调用(esp8266 accesspoint的默认网关)WIFI的IP地址为192.168.4.2
  3. 它引发了以下异常

我在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(机器不在网络上) at libcore.io.Posix.socket(Native Method) 在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..Socket.setSoTimeout(Socket.java:543)的okhttp3.internal.io.RealConnection.connectSocket(RealConnection.java:183)okhttp3.internal.io.RealConnection.buildConnection(RealConnection.java:170)at at 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 retrofit retrofit2 esp8266 okhttpclient
1个回答
1
投票

Problem

错误ENONET意味着NetworkInfo.isConnected()返回false

指示是否存在网络连接,并且可以建立连接并传递数据。在尝试执行数据事务之前始终调用此方法。

Solution

产生一个守护进程线程等待Wifi网络(由ssid给出)“完全”连接(见上文)并用callback(成功连接)或true(超时或错误)调用你的false

Implementation

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_STATEACCESS_COARSE_LOCATION(运行时权限)
© www.soinside.com 2019 - 2024. All rights reserved.