0

I'm having trouble switching between 2 networks programmatically on a Raspberry Pi 3 running Android things (but it should be the same as running normal Android).

The first network is coming from a device server as an access point. It runs an FTP server which I need to access through its network. It has a static IP-address in the 192.168.xxx.xxx network that I know, and is secured by WPA2-PSK. I have the SSID and passphrase which I know to be correct. This device is in it's own private network that it makes itself and isn't reachable an external address. The only way to connect to it is by connecting to it's network and FTP'ing to it's static address.

The second network is an open network of which I also know the SSID. This one is preconfigured by another application, so my application can't update the configuration.

The code below is what I have at the moment. The DownloadFilesTask is called in the onCreate of my startscreen.

The configuration of the first network seems to fail, as adding the configuration to the WifiManager returns -1 as networkId as I can see in the log in the last 2 lines before disconnecting and loosing all logging. The 2 lines are:

04-11 11:10:51.258 1332-1349/rocks.androidthings.hellothings D/connecting: SSID1 passphase

04-11 11:10:51.259 411-740/system_process I/addOrUpdateNetwork: uid = 10026 SSID SSID1 nid=-1

After this I get a java.net.socketException: invalid argument or cannot connect assign requested address.

I have been struggling with this for the past few days, so any help would be appreciated.

public String connectToNetwork1() {
    try {
        WifiManager wifiManager = (WifiManager) this.getApplicationContext().getSystemService(Context.WIFI_SERVICE);

        if (!wifiManager.getConnectionInfo().getSSID().equals("\"" + SSID1 + "\"")) {

            WifiConfiguration conf = new WifiConfiguration();
            conf.SSID = "\"" + SSID1 + "\"";

            conf.preSharedKey = "\"" + passphrase + "\"";
            conf.allowedProtocols.set(WifiConfiguration.Protocol.RSN); // For WPA2
            conf.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
            Log.d("connecting", conf.SSID + " " + conf.preSharedKey);

            int networkId = wifiManager.addNetwork(conf);

            Log.d("after connecting", conf.SSID + " " + conf.preSharedKey);
            wifiManager.disconnect();
            Thread t = new Thread(() -> {
                wifiManager.enableNetwork(networkId, true);                 
            });
            t.start();
            t.join();
            wifiManager.reconnect();
            Log.d("re connecting", wifiManager.getConnectionInfo().getSSID());
            return wifiManager.getConnectionInfo().toString();
        } else {
            Log.d("WIFI", "already connected to network1");
            return "already connected to network1";
        }
    } catch (Exception ex) {
        Log.d("ERROR", ex.toString());
    }
    return "nougabollen";
}

public String connectToNetwork2() {
    try {
        WifiManager wifiManager = (WifiManager) this.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
        if (!wifiManager.getConnectionInfo().getSSID().equals("\"" + SSID2 + "\"")) {

            /*WifiConfiguration conf = new WifiConfiguration();             //
            conf.SSID = "\"" + SSID2 + "\"";                                //
                                                                            //  
            conf.status = WifiConfiguration.Status.ENABLED;                 //
            conf.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);  // this block is useless since my application can't update this network
                                                                            // since network 2 is configured elsewhere  
            Log.d("connecting", conf.SSID);                                 //
                                                                            //
            int networkId = wifiManager.addNetwork(conf);*/                 //
            int networkId = -2;
            List<WifiConfiguration> configs = wifiManager.getConfiguredNetworks();
            for(WifiConfiguration wc : configs){
                if(wc.SSID.equals("\"" + SSID2 + "\"")){
                    networkId = wc.networkId;
                }
            }
            int finalNetworkId = networkId;
            wifiManager.disconnect();
            Thread t = new Thread(() -> {
                wifiManager.enableNetwork(finalNetworkId, true);
            });
            t.start();
            t.join();
            wifiManager.reconnect();
            Log.d("re connecting", wifiManager.getConnectionInfo().getSSID());
            return  "tried networkId: " + networkId + "   " + wifiManager.getConnectionInfo().toString();
        } else {
            Log.d("WIFI", "already connected to network2");
            return "already connected to network2";
        }
    } catch (Exception ex) {
        Log.d("ERROR", ex.toString());
    }
    return "smoutebollen";
}

private class DownloadFilesTask extends AsyncTask<Void, Void, String> {

    @Override
    protected String doInBackground(Void... params) {
        String text = "";
        text += " " + connectToNetwork1();
        text += " " + retrieveFile();
        text += " " + connectToNetwork2();
        Log.d("text", text);
        return text;
    }

    protected void onPostExecute(String text) {
        test.setText(text);
    }
}

The code that I use to retrieve the file is (using apache.commons.net):

public static String getDummyFile(){
    FTPClient client = new FTPClient();
    Log.d("ftp","client created");
    InetAddress ip = null;
    try {
        ip = InetAddress.getByName("192.168.242.129"); // this is the address of the device creating the first network
    }
    catch (Exception e){
        Log.d("inetaddres",e.toString());
    }
    try {
        Log.d("inet", ip.getHostAddress());
        int reply = -1; //response


        client.connect(ip);
        Log.d("ftp","client connected");
        reply = client.getReplyCode();
        Log.d("ftp",""+reply);
        client.enterLocalPassiveMode();
        Log.d("ftp","passive mode");

        //check if login is accepted
        /*if (!client.login("anonymous", "")) {
            Log.d("FTP", "error logging in");
        }*/

        //check if bad reponse code
        /*if (!FTPReply.isPositiveCompletion(reply)) {
            client.disconnect();
            Log.d("FTP", "connection refused");
        }*/

        //set file type to binary and enter passive mode, active not supported on android
        client.setFileType(FTP.BINARY_FILE_TYPE);
        Log.d("ftp", "set type to binary");
        client.changeWorkingDirectory("/files");
        Log.d("ftp","changed dir");
        String[] names = client.listNames();
        Log.d("FTP", names[1].toString());
        Log.d("FTP", client.printWorkingDirectory() + "/" + names[1].toString());
        mapFiles(client,"/files","",0);
        return client.printWorkingDirectory() + "/" + names[1].toString();

    } catch (Exception e) {
        Log.d("ftp",e.toString());
        text = e.toString();
    }
    finally {
        try {
            client.disconnect();
        }
        catch (Exception e){

        }
    }
    return text;
}

which gives the exception when trying to connect, since I'm not connected to the network.

SJoos
  • 91
  • 8
  • PLease add the stacktrace. 192.168 is the local network. Meaning if you connect to 192.168.1.1(or 192.168.0.1, whatever is the routers address) you will come to the router on your network, not a specific router. If you are to connect to a specific script on either network, you have to find the external ip(use a site like whatsmyip.com). – Zoe Apr 11 '17 at 09:38
  • If you've got a host in the 169.254-range, something about your network setup isn’t working, never should a host use that range. Devices that can't get an IP from a DHCP server gets these addresses. – kaderud Apr 11 '17 at 15:19
  • That was an error on my part, if I connect to the device in a LAN network it gives back the 169.254 address, in WLAN it has an address in the 192.168 network, It's the address in the 192.168 network that I need to ftp to. My apologies for the confusion. – SJoos Apr 11 '17 at 15:35
  • Does this code work on an Android mobile device, and allow to to connect to the networks as you expect? – devunwired Apr 11 '17 at 20:01
  • That's a good question, I haven't tried that yet. – SJoos Apr 12 '17 at 06:29

1 Answers1

0

So I managed to get it working, the following is my working code. Main differences are setting WPA as protocol, and letting the thread were I connect sleep for 3 seconds after enabling the network.

    public String connectToXs() {
    try {
        WifiManager wifiManager = (WifiManager) this.getApplicationContext().getSystemService(Context.WIFI_SERVICE);

        if (!wifiManager.getConnectionInfo().getSSID().equals("\"ssid\"")) {

            WifiConfiguration wc = new WifiConfiguration();
            wc.SSID = "\"ssid\"";

            wc.preSharedKey  = "\"key\"";
            wc.status = WifiConfiguration.Status.ENABLED;
            wc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
            wc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
            wc.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
            wc.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
            wc.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
            wc.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
            wc.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
            int res = wifiManager.addNetwork(wc);
            Log.d("WifiPreference", "add Network returned " + res );
            final boolean[] b = new boolean[1];
            Thread t = new Thread(() -> {
                b[0] = wifiManager.enableNetwork(res, true);
                wifiManager.setWifiEnabled(true);
                try {
                    Thread.sleep(3000);
                }
                catch (Exception e){
                    Log.d("ERROR",e.toString());
                }
            });
            t.start();
            t.join();
            Log.d("WifiPreference", "enableNetwork returned " + b[0]);

            return wifiManager.getConnectionInfo().toString();
        } else {
            Log.d("WIFI", "already connected");
            return "already connected";
        }
    } catch (Exception ex) {
        Log.d("ERROR", ex.toString());
    }
    return "nougabollen";
}

public String connectToGuest() {
    try {
        WifiManager wifiManager = (WifiManager) this.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
        if (!wifiManager.getConnectionInfo().getSSID().equals("\"" + "ssid2" + "\"")) {

            //int networkId = wifiManager.addNetwork(conf);
            int networkId = -2;
            List<WifiConfiguration> configs = wifiManager.getConfiguredNetworks();
            for(WifiConfiguration wc : configs){
                if(wc.SSID.equals("\"SSID2\"")){
                    networkId = wc.networkId;
                }
            }
            int finalNetworkId = networkId;
            wifiManager.disconnect();
            Thread t = new Thread(() -> {
                wifiManager.enableNetwork(finalNetworkId, true);
                try {
                    Thread.sleep(3000);
                }
                catch (Exception e){
                    Log.d("ERROR",e.toString());
                }
            });
            t.start();
            t.join();
            wifiManager.reconnect();
            Log.d("re connecting", wifiManager.getConnectionInfo().getSSID());
            return  "tried networkId: " + networkId + "   " + wifiManager.getConnectionInfo().toString();
        } else {
            Log.d("WIFI", "already connected");
            return "already connected";
        }
    } catch (Exception ex) {
        Log.d("ERROR", ex.toString());
    }
    return "smoutebollen";
}
SJoos
  • 91
  • 8