Android connection with ESP8266 on One Plus ( Android 6.0.1)

≯℡__Kan透↙ 提交于 2020-01-04 09:36:35

问题


Retrofit on Android 6.0 has a problem making Http calls after connecting to Access Point

Steps to reproduce:

  1. Connect to Esp8266 Access Point
  2. Make an http call to http://192.168.4.1 (Default gateway of esp8266 accesspoint) The IP address of WIFI is 192.168.4.2
  3. It throws the below exception

I have tried the same on Android 5.1 and the same code works flawlessly

java.net.SocketException: socket failed: ENONET (Machine is not on the network)
at libcore.io.IoBridge.socket(IoBridge.java:619)
at java.net.PlainSocketImpl.create(PlainSocketImpl.java:198)
at java.net.Socket.checkOpenAndCreate(Socket.java:689)
at java.net.Socket.setSoTimeout(Socket.java:543)
at okhttp3.internal.io.RealConnection.connectSocket(RealConnection.java:183) at okhttp3.internal.io.RealConnection.buildConnection(RealConnection.java:170) at okhttp3.internal.io.RealConnection.connect(RealConnection.java:111) at okhttp3.internal.http.StreamAllocation.findConnection(StreamAllocation.java:187) at okhttp3.internal.http.StreamAllocation.findHealthyConnection(StreamAllocation.java:123) at okhttp3.internal.http.StreamAllocation.newStream(StreamAllocation.java:93) at okhttp3.internal.http.HttpEngine.connect(HttpEngine.java:296)
at okhttp3.internal.http.HttpEngine.sendRequest(HttpEngine.java:248)
at okhttp3.RealCall.getResponse(RealCall.java:243)
at okhttp3.RealCall$ApplicationInterceptorChain.proceed(RealCall.java:201) at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:163) at okhttp3.RealCall.access$100(RealCall.java:30)
at okhttp3.RealCall$AsyncCall.execute(RealCall.java:127)
at okhttp3.internal.NamedRunnable.run(NamedRunnable.java:32)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113 at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588) at java.lang.Thread.run(Thread.java:818)
Caused by: android.system.ErrnoException: socket failed: ENONET (Machine is not on the network)
at libcore.io.Posix.socket(Native Method)
at libcore.io.BlockGuardOs.socket(BlockGuardOs.java:282)
at libcore.io.IoBridge.socket(IoBridge.java:604)
at java.net.PlainSocketImpl.create(PlainSocketImpl.java:198) 
at java.net.Socket.checkOpenAndCreate(Socket.java:689) 
at java.net.Socket.setSoTimeout(Socket.java:543)  at okhttp3.internal.io.RealConnection.connectSocket(RealConnection.java:183)  at okhttp3.internal.io.RealConnection.buildConnection(RealConnection.java:170) at okhttp3.internal.io.RealConnection.connect(RealConnection.java:111) 
at okhttp3.internal.http.StreamAllocation.findConnection(StreamAllocation.java:187) at okhttp3.internal.http.StreamAllocation.findHealthyConnection(StreamAllocation.java:123)  at okhttp3.internal.http.StreamAllocation.newStream(StreamAllocation.java:93) at okhttp3.internal.http.HttpEngine.connect(HttpEngine.java:296) 
at okhttp3.internal.http.HttpEngine.sendRequest(HttpEngine.java:248)  at okhttp3.RealCall.getResponse(RealCall.java:243)  at okhttp3.RealCall$ApplicationInterceptorChain.proceed(RealCall.java:201) at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:163) 
at okhttp3.RealCall.access$100(RealCall.java:30) 
at okhttp3.RealCall$AsyncCall.execute(RealCall.java:127) 
at okhttp3.internal.NamedRunnable.run(NamedRunnable.java:32) 
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113 at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588 at java.lang.Thread.run(Thread.java:818)


回答1:


Problem

Error ENONET means that NetworkInfo.isConnected() returns false

Indicates whether network connectivity exists and it is possible to establish connections and pass data. Always call this before attempting to perform data transactions.

Solution

Spawn a daemon Thread which waits for the Wifi network (given by ssid) to "fully" connect (see above) and call your callback with either true (successfully connected) or false (timeout or error).

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 must be enclosed in double quotation marks (see wifiConfiguration.SSID)
  • ConnectivityManager.getAllNetworks() requires permission ACCESS_NETWORK_STATE
  • WifiManager.getConnectionInfo() requires permissions ACCESS_NETWORK_STATE and ACCESS_COARSE_LOCATION (runtime permission)


来源:https://stackoverflow.com/questions/40830284/android-connection-with-esp8266-on-one-plus-android-6-0-1

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!