SCAN_RESULTS_AVAILABLE_ACTION вернуть пустой список в Android 6.0

Вчера мой Nexus 5 получил обновление от Android MNC к версии 6.0 - Marshmallow, С тех пор действие по сканированию сетей, доступных на устройстве, прекращает прием списка, в этом случае список результатов имеет размер 0, даже если в настройках системы Wifi указано 10+ сетей Wifi.

Код для этого является обычным: зарегистрировать SCAN_RESULTS_AVAILABLE_ACTION и ждать события в приемнике, например так:

// 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.

Я искал изменения в теме API по этому поводу, но я не увидел каких-либо серьезных изменений для этой функциональности.

Кто-нибудь это заметил? Что-то новое в API или просто единичный случай?

5 ответов

Решение

Начиная с Android 6.0 поведение разрешений изменилось на время выполнения. Чтобы использовать функцию, требующую разрешения, необходимо сначала проверить, было ли предоставлено разрешение ранее. С помощью checkSelfPermission(permissionString) метод, возвращается результат, с каким разрешением PERMISSION_GRANTED или же PERMISSION_DENIED,

Если разрешение не предоставлено или это впервые, следует запросить разрешение. Предоставление пользователю возможности предоставить или отклонить.

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
}

Если ваш код работает на устройстве до M, вы продолжаете работу с кодом, разрешение было предоставлено устаревшим методом.

После запроса разрешения пользователю будет показан диалог. Его / ее ответ будет доставлен как:

@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();
     }
 }

После этого вы можете проверить, включены ли службы определения местоположения, используя LocationServices.SettingsApi и попросите пользователя включить, если эта опция отключена. Это возможно с Play Services LocationSettingsStatusCodes.RESOLUTION_REQUIRED Перезвоните.

Я нахожу связанную проблему в проблеме трекера проблем AOSP 185370 WifiManager # getScanResults () возвращает пустой список массивов, если GPS выключен.

Проблема упоминается из # 1, мобильный телефон должен открыть сервис определения местоположения, чтобы получить список Wi-Fi мобильного телефона.

И начиная с № 18, участник проекта Android заявляет, что команда разработчиков исправила проблему, о которой вы сообщили, и она будет доступна в будущей сборке.

Приложение находится в targetSdkVersion 23, просто следуйте приведенному выше решению, чтобы проверить разрешение во время выполнения. Проблема принудительного включения служб определения местоположения будет исправлена ​​в следующем выпуске Android.

Это не будет работать, если у вас не включен GPS. Странно, но это единственный способ получить список Wi-Fi:-(.

редактировать

Таким образом, проблема, похоже, связана с новой обработкой разрешений. Вы должны запросить разрешение, прежде чем переходить к коду Wi-Fi. Вот пример:

// 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();
    }
}

Эта проверка должна быть сделана в Деятельности.

Оригинальный пример кода доступен здесь, измененный в соответствии с проблемой, обсуждаемой в этом разделе.

оригинал

Согласно связанным изменениям API, ваше приложение должно иметь одно из разрешений местоположения. Цитата:

WifiManager.getScanResults (): Ваше приложение должно иметь разрешение ACCESS_FINE_LOCATION или ACCESS_COARSE_LOCATION.

Также обратите внимание, что новый BroadleReceiver получил новый логический ключ SCAN_RESULTS_AVAILABLE_ACTION действие: EXTRA_RESULTS_UPDATED, Это показывает, если сканирование завершено, и вы можете получить доступ к результатам, позвонив wifiManager.getScanResults(),

Помимо приведенных ответов; Вы также можете использовать checkSelfPermission из ContextCompat чтобы обеспечить обратную совместимость с более низкими версиями Android:

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
}
Другие вопросы по тегам