Ответ 1
Начиная с Android 6.0, поведение разрешений изменилось на время выполнения. Чтобы использовать функцию, требующую разрешения, сначала нужно проверить, разрешено ли разрешение. Используя метод checkSelfPermission(permissionString)
Вчера мой Nexus 5 получил обновление от Android MNC
до версии 6.0 - Marshmallow
.
С тех пор действие сканирования сетей, доступных на устройстве, перестает получать список, в этом случае список результатов имеет размер 0, даже с 10+ Wi-Fi-сетями, указанными в настройках системы Wi-Fi.
Код для этого является обычным: зарегистрируйте 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 или просто изолированный случай?
Начиная с Android 6.0, поведение разрешений изменилось на время выполнения. Чтобы использовать функцию, требующую разрешения, сначала нужно проверить, разрешено ли разрешение. Используя метод checkSelfPermission(permissionString)
Я нашел связанную проблему с проблемой отслеживания проблем AOSP 185370 WifiManager # getScanResults() возвращает список пустых массивов, если GPS отключен.
Проблема связана с # 1. Мобильный телефон должен открыть службу определения местоположения, чтобы получить список мобильных телефонов wifi.
И из # 18 участник проекта Android утверждает, что команда разработчиков исправила проблему, о которой вы сообщили, и она будет доступна в будущей сборке.
APP находится в targetSdkVersion 23, просто следуйте приведенному выше решению, чтобы проверить разрешение во время выполнения. Принятие решения о включении проблемы с службами местоположений будет исправлено в будущей версии Android.
Итак, проблема связана с новой обработкой разрешений. Вы должны попросить разрешения, прежде чем переходить к коду 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();
}
}
Эта проверка должна выполняться в Activity.
Исходный образец кода доступен здесь, измененный в соответствии с проблемой, обсуждаемой в этом разделе.
Согласно связанным изменениям API, ваше приложение должно иметь одно из разрешений на размещение. Цитата:
WifiManager.getScanResults(): ваше приложение должно иметь разрешение ACCESS_FINE_LOCATION или ACCESS_COARSE_LOCATION.
Также обратите внимание, что есть новый логический ключ, полученный вашим BroadcastReceiver в действии 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
}