Search code examples
javaandroidandroid-arrayadapterandroid-wifiwifimanager

Filter wifi network names uniquely


I want to display a list of available wifi networks in a spinner. But with the current version, I'm getting a lot of duplicate networks and white space values when there are many wifi networks in the range. How can I uniquely identify each wifi network name? I have tried various methods and still could not get it correctly. Any help in this regard would be highly appreciated. my current code which is made for android 24 onwards is:

  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            List<ScanResult> wifiList = wifiManager.getScanResults();
            ssids = wifiList.stream()
                    .map(scanResult -> scanResult.SSID)
                    .filter(ssid -> ssid.equals(""))
                    .distinct()
                    .collect(Collectors.toList());

            deviceList = new String[ssids.size()];
            for (int i = 0; i < ssids.size(); i++) {
                deviceList[i] = ((ssids.get(i)));

                if(SCAN_RESULTS_AVAILABLE_ACTION.equals(true)){
                    wifiManager.disconnect();
                }
            }


             ArrayAdapter<String> adapter = new ArrayAdapter<String>(context, 
             android.R.layout.simple_spinner_item, deviceList) {
                @Override
                public View getView(int position, View convertView, ViewGroup parent) {

                    View v = super.getView(position, convertView, parent);
                    if (position == getCount()) {
                        ((TextView)v.findViewById(android.R.id.text1)).setText("");
                        ((TextView)v.findViewById(android.R.id.text1)).setHint(getItem(getCount())); 
                        //"Hint to be displayed"
                    }

                    return v;
                }

                @Override
                public int getCount() {
                    return super.getCount()-1; // you don't display last item. It is used as hint.
                }
            };
            adapter.setDropDownViewResource(R.layout.support_simple_spinner_dropdown_item);
            wifiDeviceList.setAdapter(adapter);
            wifiDeviceList.setSelection(adapter.getCount());//set the hint the default selection so it appears on launch.
            wifiDeviceList.setOnItemSelectedListener(this);
            adapter.notifyDataSetChanged();
        }

Solution

  • If you're seeing the same SSID, it's likely because the BSSID is different.

    You may be seeing different routers which belong to different networks but happen to have the same name (e.g. "netgear" or "dlink"). This is common in dense residential areas.

    You may also be seeing different routers which belong to the same network. These would be different access points on a corporate network, for example, strategically placed to provide maximum coverage.

    You may also be seeing legitimately duplicated entries.

    You have several options for how to deal with these, but the generally accepted approach is to de-duplicate by BSSID, then display a list of SSIDs with signal meters.

    The problem with your code above is that filter() does not work the way you expect it to. It seems like you're expecting it to filter out ssid.equals(""), when in fact filter() will remove any items which to not match the criteria. You can see an example of this on the Stream documentation page.

    You want to change .filter(ssid -> ssid.equals("")) to be

    .filter(ssid -> !ssid.equals(""))