androidsocket.ionetwork-programmingwifiwifimanager

Android: app cant ping device on wifi network when connecting in the app


I have built an app using Socket.io and android network discovery. when the server is started and the android device resolves the service i attempt to create a socket, but it never works on first try. I have to kill the app and restart it and then it works fine. The server is running on the access point. the connection to the network is fine but i cannot ping the server. But as mentioned before if i kill the app and run it again it works fine.


Eidt 2

After further debugging I narrowed the crash down to any time my app sets up the wifi connection. the ssid and and password are obtained from a qrcode and the app sets up the wifi connection.


read qr code data

        @Override
        public void receiveDetections(Detector.Detections<Barcode> detections) {
            final SparseArray<Barcode> barCodes = detections.getDetectedItems();

            if (!receivedDetection) {
                if (barCodes.size() != 0) {

                    Log.i(TAG, "received a Barcode");
                    receivedDetection = true;

                    Gson g = new Gson();
                    try {
                        barCodeData = g.fromJson(barCodes.valueAt(0).rawValue, AccessPointCredentials.class);
                    } catch (Exception e) {
                        barCodeData = new AccessPointCredentials();
                        barCodeData.setSsid(barCodes.valueAt(0).rawValue);
                        barCodeData.setPass(null);
                        e.printStackTrace();
                    }

                    connectToWifi(barCodeData);

                }
            }
        }

connectToWifi()

private void connectToWifi(final AccessPointCredentials credentials) {

    new AsyncTask<Object, Object, Object>() {
        @Override
        protected Object doInBackground(Object... objects) {
            WifiManager wifiManager = (WifiManager) mActivity.getSystemService(Context.WIFI_SERVICE);

            wifiManager.setWifiEnabled(true);
            int netId;

            try {
                Thread.sleep(100);
            } catch (InterruptedException ie) {
                ie.printStackTrace();
            }

            for (WifiConfiguration tmp : wifiManager.getConfiguredNetworks()) {
                if (tmp.SSID.equals("\"" + credentials.getSsid() + "\"")) {

                    netId = tmp.networkId;
                    boolean enabled = wifiManager.enableNetwork(netId, true);

                    Log.i(TAG, "doInBackground: Enabled? " + enabled);

                    mActivity.runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            mActivity.onBackPressed();
                        }
                    });
                    return null;
                }
            }


            final String[] apSettings = {credentials.getSsid(), credentials.getPass()};
            final WifiConnect WifiTask = new WifiConnect(mActivity);
            mActivity.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    WifiTask.execute(apSettings);
                }
            });
            this.cancel(true);
            return null;
        }

        @TargetApi(23)
        @Override
        protected void onPostExecute(Object aVoid) {
            super.onPostExecute(aVoid);

            if (Build.VERSION.RELEASE.equalsIgnoreCase("6.0")) {
                if (!Settings.System.canWrite(mActivity)) {
                    Intent goToSettings = new Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS);
                    goToSettings.setData(Uri.parse("package:" + mActivity.getPackageName()));
                    mActivity.startActivity(goToSettings);
                } else {
                    bindToNetwork();
                }


            } else {
                bindToNetwork();
            }
        }
    }.execute();
}

bindToNetwork()

private void bindToNetwork() {
    final ConnectivityManager connectivityManager = (ConnectivityManager) mActivity.getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkRequest.Builder builder;
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        builder = new NetworkRequest.Builder();
        //set the transport type do WIFI
        builder.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
        connectivityManager.requestNetwork(builder.build(), new ConnectivityManager.NetworkCallback() {
            @Override
            public void onAvailable(Network network) {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                    connectivityManager.bindProcessToNetwork(network);

                } else {
                    //This method was deprecated in API level 23
                    ConnectivityManager.setProcessDefaultNetwork(network);
                }
                try {
                    //do a callback or something else to alert your code that it's ok to send the message through socket now
                } catch (Exception e) {
                    e.printStackTrace();
                }
                connectivityManager.unregisterNetworkCallback(this);
            }
        });
    }
}

Edit

the boolean method isServerReachable() trows an exception

java.net.SocketException: socket failed: ENONET (Machine is not on the network)


public boolean isServerReachable(){

        boolean isReachable;
        try {
            isReachable = InetAddress.getByName(mService.getHost().getHostAddress()).isReachable(5000);

        } catch (Exception e) {
            e.printStackTrace();
            isReachable = false;
        }
        Log.i(TAG, "onServiceResolved: Server reachable? " + String.valueOf(isReachable));

        Log.i(TAG, "onServiceResolved: Is Network online? " + String.valueOf(isNetworkOnline()));

    if (isReachable){
        return true;
    } else {
        return false;
    }
}

Solution

  • I solved it but I am not convinced it is the best solution and will accept a better one if it added.

    I modified the for loop in the connectToWifi() method by adding a Thread.sleep(500); call after wifiManager.enableNetwork() and it is now working.

    for (WifiConfiguration tmp : wifiManager.getConfiguredNetworks()) {
        if (tmp.SSID.equals("\"" + credentials.getSsid() + "\"")) {
            netId = tmp.networkId;
            boolean enabled = wifiManager.enableNetwork(netId, true);
    
            try {
                Thread.sleep(500);
            } catch (InterruptedException ie) {
                ie.printStackTrace();
            }
    
            mActivity.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    mActivity.onBackPressed();
                }
            });
            return null;
        }
    }