Search code examples
androidwifimanager

Android WifiManager::getScanResults() still returns empty list


As a newbie to Android programming, I am trying to get the SSID list using WifiManager's getScanResults() method, but it remains empty, even though I have granted it the ACCESS_COARSE_LOCATION permission as well as the CHANGE_WIFI_STATE (for the startScan() method), both in the manifest and by checking/requesting it at runtime.

In the broadcast receiver for the SCAN_RESULTS_AVAILABLE_ACTION, I even check the extra field of the intent with key EXTRA_RESULTS_UPDATED and the result returns true.

Yet, the list.size() always returns 0.

What am I missing here? I am testing on a Android 7.0 API 24 device.

Edit: The code is as follows:

MainActivity.java:

public class MainActivity extends Activity implements View.OnClickListener {
    private static final String TAG="WiFiDemo";

    WifiManager wifiManager;
    WifiBroadcastReceiver wifiReceiver;

    TextView textView;
    Button btn;

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        Log.d(TAG, "onCreate()");
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //Check for permissions
        if ((ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION)
                != PackageManager.PERMISSION_GRANTED)
            || (ContextCompat.checkSelfPermission(this, Manifest.permission.CHANGE_WIFI_STATE)
                    != PackageManager.PERMISSION_GRANTED))
        {
            Log.d(TAG, "Requesting permissions");

            //Request permission
            ActivityCompat.requestPermissions(this,
                    new String[]{Manifest.permission.ACCESS_COARSE_LOCATION,
                                 Manifest.permission.ACCESS_FINE_LOCATION,
                                 Manifest.permission.ACCESS_WIFI_STATE,
                                 Manifest.permission.CHANGE_WIFI_STATE,
                                 Manifest.permission.ACCESS_NETWORK_STATE},
                    123);
        }
        else
            Log.d(TAG, "Permissions already granted");

        wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);

        textView = findViewById(R.id.text);
        textView.setTextAlignment(View.TEXT_ALIGNMENT_TEXT_START);

        btn = findViewById(R.id.btn);
        btn.setOnClickListener(this);

        //Instantiate broadcast receiver
        wifiReceiver = new WifiBroadcastReceiver();

        //Register the receiver
        registerReceiver(wifiReceiver, new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults)
    {
        Log.d(TAG, "onRequestPermissionsResult");

        switch (requestCode)
        {
            case 123:
            {
                // If request is cancelled, the result arrays are empty.
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED)
                {
                    // permission was granted
                    Log.d(TAG, "permission granted: " + permissions[0]);
                }
                else
                {
                    // permission denied, boo! Disable the
                    // functionality that depends on this permission.
                    Log.d(TAG, "permission denied: " + permissions[0]);
                }

                return;
            }

            // other 'case' lines to check for other
            // permissions this app might request.
        }
    }

    //Define class to listen to broadcasts
    class WifiBroadcastReceiver extends BroadcastReceiver
    {
        @Override
        public void onReceive(Context context, Intent intent)
        {
            Log.d(TAG, "onReceive()");
            Toast.makeText(getApplicationContext(), "Scan complete!", Toast.LENGTH_SHORT).show();

            boolean ok = intent.getBooleanExtra(WifiManager.EXTRA_RESULTS_UPDATED, false);

            if (ok)
            {
                Log.d(TAG, "scan OK");

                //StringBuffer buffer = new StringBuffer();
                List<ScanResult> list = wifiManager.getScanResults();

                Toast.makeText(getApplicationContext(), Integer.toString(list.size()), Toast.LENGTH_SHORT).show();

                for (ScanResult scanResult : list)
                {
                    //buffer.append(scanResult);
                    textView.append(scanResult.toString());
                }
            }
            else
                Log.d(TAG, "scan not OK");
        }
    }

    @Override
    protected void onStop()
    {
        // TODO Auto-generated method stub
        unregisterReceiver(wifiReceiver);
        super.onStop();
    }

    @Override
    public void onClick(View view)
    {
        // TODO Auto-generated method stub
        //Toast.makeText(getApplicationContext(), "All Network seached !!",0).show();
        if(view.getId()==R.id.btn)
        {
            Log.d(TAG, "onCreate() wifi.startScan()");

            //if (!wifiManager.isWifiEnabled())
            //    wifiManager.setWifiEnabled(true);

            wifiManager.startScan();
        }
    }
}

In the manifest:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.wifi2ir.umagi.wifitest2">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
</manifest>

Solution

  • Starting from Android 6, you have to enable location services in order to get desired results. Granting permissions is just the half work done.

    You can also fire an intent to redirect user to this setting:

    Intent myIntent = new Intent( Settings.ACTION_LOCATION_SOURCE_SETTINGS);
    startActivity(myIntent);
    

    Location services are necessary because when you access the scan results, you can access the information like BSSID (address of the access point). This information can also be used to detect the location of device. By requiring location services, OS ensures that user understands their location information is being accessed when they use your app.