45

Yesterday my Nexus 5 receive the update from Android MNC to version 6.0 - Marshmallow. Since then, the action to scan the networks available in the device stop receiving the list, in this case the result list have a size of 0, even with 10+ Wifi networks listed in the Wifi system settings.

The code for this is the usual: Register the SCAN_RESULTS_AVAILABLE_ACTION and wait for the event in the Receiver, like this:

// Register the Receiver in some part os fragment...
getActivity().registerReceiver(wifiListener, new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
WifiManager wifiManager = (WifiManager) getActivity().getSystemService(Context.WIFI_SERVICE);
wifiManager.startScan();

// Inside the receiver:
WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
List<ScanResult> results = wifiManager.getScanResults();
// the result.size() is 0 after update to Android v6.0, same code working in older devices.

I searched in the changes of the API topic about this, but I didn' see any breaking changes for this functionality.

Did anyone notice this? Is something new in the API or just a isolated case?

Deividi Cavarzan
  • 10,034
  • 13
  • 66
  • 80
  • Is Allow Wi-Fi scanning option enabled on your N5? Eliminating the suspects. – Nikola Despotoski Aug 22 '15 at 02:30
  • In `Wifi > Advanced` I just see `Network Notification` and `Keep Wifi...` options, the Scanning options that appears between these two seems to be gone in this version. – Deividi Cavarzan Aug 22 '15 at 02:40
  • Do you see a dialog popping when it reaches that code for the first time to grant permission for location services? I bet in M, you should see such dialog. See http://developer.android.com/reference/android/app/Activity.html#requestPermissions(java.lang.String[], int) – Nikola Despotoski Aug 22 '15 at 02:42
  • YEAH! In another apps I used to call this dialog to force the Location Settings to be activated, generally when I work with maps, of course, this is the same use case when I've use location for maps and things like this, even not having a map. The dialog is not automatic, it need to be called from the Play Services response, this make completelly me forgot about it. Please answer this question with this particullar advice. – Deividi Cavarzan Aug 22 '15 at 03:00
  • 1
    @debihiga did you see the date from this "duplication"? I posted this question 6 months before it. – Deividi Cavarzan Jan 23 '17 at 13:50
  • Can you edit with the content of your `wifiListener`? I tried all the code provided, but I'm still getting empty list for Android 6.0 (works fine for < 6.0). – Minoru Jun 09 '17 at 14:00
  • How you have solved this problem in android 6.0 and above. I am not getting peer list in some of the devices which has the Android version more than 6.0. Please share the process. – Bhola Nath Mahto Jul 06 '18 at 06:26
  • @BholaNathMahto look at the answer mark as correct below. – Deividi Cavarzan Jul 07 '18 at 22:56

5 Answers5

59

As of Android 6.0, permission behaviour has changed to runtime. To use a feature that requires a permission, one should check first if the permission is granted previously. Using checkSelfPermission(permissionString) method a result is returned, wither ther permission is PERMISSION_GRANTED or PERMISSION_DENIED.

If permission isn't granted or it is first time, a request for permission should be made. Giving a user an option to grant or deny.

if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED){
   requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION},
                 PERMISSIONS_REQUEST_CODE_ACCESS_COARSE_LOCATION);
    //After this point you wait for callback in onRequestPermissionsResult(int, String[], int[]) overriden method

}else{
    getScanningResults();
   //do something, permission was previously granted; or legacy device
}

If your code is running on device prior to M, you proceed with your code, permission was granted using legacy method.

Once requested for permission, dialog will be shown to user. His/her response will be delivered as:

@Override
 public void onRequestPermissionsResult(int requestCode, String[] permissions,
         int[] grantResults) {
     if (requestCode == PERMISSIONS_REQUEST_CODE_ACCESS_COARSE_LOCATION
             && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
         // Do something with granted permission
        mWifiListener.getScanningResults();
     }
 }

After that, you can check if the Location Services is ON, using LocationServices.SettingsApi and request the user to enable if this options is disabled. This is possible with Play Services LocationSettingsStatusCodes.RESOLUTION_REQUIRED callback.

Deividi Cavarzan
  • 10,034
  • 13
  • 66
  • 80
Nikola Despotoski
  • 49,966
  • 15
  • 119
  • 148
  • Thanks! I realize that this will show the dialog when permission is off, but to enable I think that I will need to call play services and show the option to enable location. – Deividi Cavarzan Aug 22 '15 at 04:13
  • 1
    IMHO, checking if location and wifi are enabled (and enabling) should percede requesting permission to use the features. – Nikola Despotoski Aug 22 '15 at 12:10
  • 1
    I tried running this on a virtual device with android m, the result was no dialog asking for the permission, instead onRequestPermission returned permission denied instantly – user1354603 Sep 14 '15 at 09:32
  • 5
    7.5% of users on M, it means the rest of the folks should accept "access location" permission which is completely useless for them. Most likely it will scare them away - app which never used (and not supposed to use) location start to ask additional permission. Is there a way to add the permission only for M? – surlac May 16 '16 at 20:29
  • @surlac IMHO your comment should be a separate question. – naXa stands with Ukraine Jul 10 '16 at 11:47
  • So I can no longer scan for wifi through a broadcast receiver only added in the Manifest file? – cherry-wave Jul 29 '16 at 15:04
  • @surlac Actually you are right, this answer is useless for me and scares me away. Access network state is not a dangerous permission so what do I need to do...? I read below that gps need to be turned on to get scan results from wifimanager, but why? isn't there a different way? – DAVIDBALAS1 Aug 19 '16 at 11:02
  • FYI, this applies when your App uses a `targetSdkVersion` that is `> 22`. If you stay below this, the behavior can NOT be observed. – Lukas Knuth Apr 26 '18 at 09:17
  • Its still not showing device list after the location permission provided. – Priyanka Singhal May 24 '19 at 05:04
36

I find related issue in AOSP issue tracker issue 185370 WifiManager#getScanResults() returns an empty array list if GPS is turned off.

The problem mentions from #1, The mobile must open location service to get wifi list of mobile.

And From #18, The Android project member claims that the development team has fixed the issue that you have reported and it will be available in a future build.

The APP is in targetSdkVersion 23, just follow above solution to check runtime permission. Enforcing to enable location services problem will fix in Android future release.

Fantasy Fang
  • 6,106
  • 2
  • 25
  • 30
  • This problem has not been fixed yet, right? I am testing it on a Lenovo phone running 6.0 and still face this issue. – camelCaseCoder Jul 04 '16 at 11:21
  • The issue from https://code.google.com/p/android/issues/detail?id=185370#c70 reply points out that it seems that still Android N (preview) has the same behavior so far. – Fantasy Fang Aug 16 '16 at 06:44
  • 2
    @fantasy Really thanks for an answer. But it's an annoying issue because I had already allowed granted the location permission to my app but my device GPS is off still it not work. Now the case is useless if a user did not explicitly turn on the GPS. I could not understand that the wifi scanning is really needed a help of GPS. – Bhavdip Sagar Jan 10 '17 at 09:39
  • still exists in 7.1.1 wtf is going on – behelit Jan 17 '18 at 04:56
  • 1
    @FantasyFang Thank you so much man i wasted 1 days....you are god git for me thank so much +1 – Gowthaman M Mar 27 '18 at 14:37
8

This won't work unless you have the GPS turned on. Weird, but it's the only way I got the list of wifi's :-(.

Robbie
  • 81
  • 1
  • 5
7

Edit

So, the problem seems to be with the new permission handling. You have to ask for permission before proceeding to the wifi code. Here is an example:

// call this method only if you are on 6.0 and up, otherwise call doGetWifi()
private void getWifi() {
    if (checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
        requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION}, 0x12345);
    } else {
        doGetWifi(); // the actual wifi scanning
    }
}

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
    if (requestCode == 0x12345) {
        for (int grantResult : grantResults) {
            if (grantResult != PackageManager.PERMISSION_GRANTED) {
                return;
            }
        }
        getWifi();
    }
}

This check must be done in an Activity.

The original sample code is available here, modified according to the problem discussed in this topic.

Original

According to the linked changes of the API, your application must have one of the location permissions. Quote:

WifiManager.getScanResults(): Your app must have ACCESS_FINE_LOCATION or ACCESS_COARSE_LOCATION permission.

Also note that there is a new boolean key received by your BroadcastReceiver on SCAN_RESULTS_AVAILABLE_ACTION action: EXTRA_RESULTS_UPDATED. This shows if the scan is complete and you can access the results by calling wifiManager.getScanResults().

Community
  • 1
  • 1
Gergely Kőrössy
  • 5,620
  • 3
  • 28
  • 44
  • 1
    Hi @Gergely Kőrössy, thanks for the anwser. Since my app have Location Features, these permissions are currently enabled in the app. ` ` – Deividi Cavarzan Aug 22 '15 at 02:42
  • @DeividiCavarzan, note that there is a new extra in the bundle received by the BroadcastReceiver: http://developer.android.com/reference/android/net/wifi/WifiManager.html#EXTRA_RESULTS_UPDATED – Gergely Kőrössy Aug 22 '15 at 02:44
  • Yes, I lookup to it, and return true as expected, indicating that are available networks. The Wifi state returned is also 3, `WIFI_STATE_ENABLED` – Deividi Cavarzan Aug 22 '15 at 02:49
  • As mentioned in the update, `intent.getBooleanExtra("resultsUpdated", false);` returns true in this case. – Deividi Cavarzan Aug 22 '15 at 02:52
  • is `onRequestPermissionsResult` removed from the AppCompatActivity? It doesn't have this method to override in this version... – Deividi Cavarzan Aug 22 '15 at 03:15
  • No, it's inherited from ActivityCompat.OnRequestPermissionsResultCallback, see [here](https://developer.android.com/intl/zh-cn/reference/android/support/v4/app/ActivityCompat.OnRequestPermissionsResultCallback.html#onRequestPermissionsResult%28int,%20java.lang.String[],%20int[]%29). – Gergely Kőrössy Aug 22 '15 at 03:18
  • I tried this but still i am not getting any result in my wifi.getScanResult(); did any one figured out what is the solution? if yes please help me out.. – Ashwani Sep 06 '16 at 07:22
3

In addition to the given responses; you can also use checkSelfPermission of ContextCompat to allow for backwards compatibility with lower Android versions:

if (ContextCompat.checkSelfPermission(getContext(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
    requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, PERMISSIONS_REQUEST_CODE_ACCESS_FINE_LOCATION);
    // Get the result in onRequestPermissionsResult(int, String[], int[])
} else {
    // Permission was granted, do your stuff here
}
CptSadface
  • 61
  • 3