Lcukerd
Lcukerd

Reputation: 448

WifiManger.getScanResults() returns empty list on android

Yes, I did take a look at all other similar question but they are not working for me. I am trying to get a list of wifi connections available near me. This is how I am doing it:

 public class WifiFunction {

    private final String tag = WifiFunction.class.getSimpleName();
    private WifiManager wifiManager;

    public List<WifiDetail> getListofWifi(Context context) {

        List<WifiDetail> wifiDetails = new ArrayList<>();
        List<ScanResult> results = wifiManager.getScanResults();
        Log.d(tag,"Wifi Details " + wifiManager.getScanResults().size());
        for (ScanResult result : results) {
            wifiDetails.add(new WifiDetail(result.BSSID, result.SSID));
            Log.d(tag, result.BSSID + result.SSID);
        }
        return wifiDetails;
    }

    public void startScan(Context context)
    {
        wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
        wifiManager.startScan();
        IntentFilter filter = new IntentFilter();
        filter.addAction(SCAN_RESULTS_AVAILABLE_ACTION);
        context.registerReceiver(new resultReciever(this),filter);
    }

}

Receiver class :

    public class resultReciever extends BroadcastReceiver {

    private WifiFunction wifiFunction;

    resultReciever(WifiFunction wifiFunction)
    {
        this.wifiFunction = wifiFunction;
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        Log.d("Receiver","started");
        wifiFunction.getListofWifi(context);
    }
}

From Main Activity I am just calling:

(new WifiFunction()).startScan(this);

that is after checking for permissions. Yes, I did declare receiver in the manifest. I am asking for access and change of wifi state and access coarse location.

Still, Log prints the size of the returned list to be 0. What am I doing wrong? How to solve it?

Edit: Manifest

<?xml version="1.0" encoding="utf-8"?>

<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.permisiion.ACCESS_COARSE_LOCATION" />

<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>
    <receiver android:name=".resultReciever"/>
</application>

EDIT 2: Runtime Permission:

private boolean checkPermission() {

    List<String> permissionsList = new ArrayList<String>();

    if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_WIFI_STATE) != PackageManager.PERMISSION_GRANTED) {
        permissionsList.add(Manifest.permission.ACCESS_WIFI_STATE);
    }

    if (ContextCompat.checkSelfPermission(this, Manifest.permission.CHANGE_WIFI_STATE) != PackageManager.PERMISSION_GRANTED) {
        permissionsList.add(Manifest.permission.CHANGE_WIFI_STATE);
    }

    if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
        permissionsList.add(Manifest.permission.ACCESS_COARSE_LOCATION);
    }

    if (permissionsList.size() > 0) {
        ActivityCompat.requestPermissions(this, permissionsList.toArray(new String[permissionsList.size()]),
                1);
        return false;
    }
    return true;
}

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions,
                                       int[] grantResults) {
    switch (requestCode) {
        case 1:
            (new WifiFunction()).startScan(this);
            break;
    }
}

Upvotes: 3

Views: 6775

Answers (5)

katwekibs
katwekibs

Reputation: 1437

Set permission in your AndroidManifest.xml

<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
  1. Now go to settings > Apps > your app > Permissions. Make sure Location is switched on.
  2. Now go to Settings > Location make sure its switched on.

You should be able to get results in WifiManger.getScanResults()

Upvotes: 1

Lcukerd
Lcukerd

Reputation: 448

This worked. I just had to give Access_Fine_Location permission.

Upvotes: 5

Sion C
Sion C

Reputation: 451

A successful call to WifiManager.getScanResults() requires any one of the following permissions:

ACCESS_FINE_LOCATION

ACCESS_COARSE_LOCATION

CHANGE_WIFI_STATE

If the calling app does not have any of these permissions, the call fails with a SecurityException.

So Android 8 able to retrive all wifi APs by just enabling the CHANGE_WIFI_STATE

Upvotes: 0

Sagar
Sagar

Reputation: 24907

You were missing permission to access Access_Fine_Location, but starting from Android 6 granting all the permissions won't yield the expected output. 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.

Upvotes: 2

Bad Loser
Bad Loser

Reputation: 3155

Adding the following line to your manifest is not necessarily enough to fix the problem!

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

If your targetSdkVersion is 23 or greater, then (because this is one of the dangerous permissions) you must also do something like this

ActivityCompat.requestPermissions(Main.this, 
                new String[]{Manifest.permission.ACCESS_FINE_LOCATION }, 1); 

Doing this fixed the problem for both me and the OP. I double-checked the assertion by reversing the changes to recreate the problem.

NB: There are 2 highly remarkable elements here:
(1) Nowhere is it documented that WifiManager.startScan() requires this permission.
(2) My app is based on a working (pre-API 23) app that does NOT have Manifest.permission.ACCESS_FINE_LOCATION

Upvotes: 4

Related Questions