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
}