Android studio сканирование wifi сетей
Всем снова привет! Давно я ничего не писал и вот решил сегодня выдать новый перл (:
У нас будет всего лишь один класс который будет выполнять работу, еще будет подкласс рессивер который будет коннектиться к нужной нам сети.
Для начала давайте создадим разметку и добавим препишены для приложения в манифесте. И так сначала разметка. У нас будет всего два объекта, EditText и Bitton по нажатию на которую будет производиться подключение к имени нужной сети которое вы введете в EditText.
activity_main.xml
А так же нам нужно добавить кучу премишенов для того что бы можно было работать с вайфай, интернетом, регулировать состояние вайфая, доступ к вайфаю и так далее.
Вот так будет выглядеть Манифест после редактирования:
AndroidManifest.xml
С настройками для работы мы закончили, так же скорей всего если у вас обновленный Eclipse вам понадобиться appcompat_v7 который Eclipse создает теперь после каждого создания нового проекта, это жутко бесить но без него работать наперекор всему отказывается, проект выдает кучи ошибок и все. Так что я его прикреплю к проекту как дополнительную библиотеку, и на гите он будет лежать вместе с проектом.
Теперь можем смело вставлять в MainActivity наш код который подключается к конкретной точке.
MainActivity.java
Думаю комментарии тут совершенно лишними не будут. Что мы тут делаем? В первую очередь мы создали кучу переменных для работы с Wifi, такие как конфигурации и менеджеры, они нам дают возможность полностью командовать нашим Wifi в телефоне \ планшете.
Далее мы все это инициализируем в методе init(). После чего в методе onCreate() мы сперва вызываем этот init(), а после обрабатываем нажатие на кнопку и после нажатия вызываем метод и делаем нашу булевую переменную активной которая запускает рессивер.
Все получается запутанно, а это только начало (: Думаю проследить в коде будет проще, там такие же комментарии.
Дальше переходим в сам рессивер. В нем мы сканируем все сети WiFi и получаем кокретные их имена
дальше при помощи ифа мы вытаскиваем нужное нам имя,
и подключаемся к той сети имя которой похоже на введенное из EditText
Остальные параметры важны но самое важное в принципе я описал.
Все это мы делаем в рессивере для того что бы выполнялось оно в отдельном потоке и не захламляло UI поток, да и без отдельного потока приложение просто падает с NullPointerExeption. Так что вот такие пироги.
Однажды мне понадобилось сканировать из Android приложения сети Wi-Fi и получать подробную выкладку данных о точках доступа.
Тут пришлось столкнуться с несколькими трудностями: в офф.документации Android многие описанные классы стали deprecated (API level > 26), что никак не было в ней отражено; описание некоторых вещей в документации минимально (например поле capabilities класса ScanResult на момент написания не описано почти никак, хотя содержит много важных данных). Третья сложность может заключаться в том, что при первой близости с Wi-Fi, отличной от чтения теории и настройки роутера по localhost, приходится иметь дело с рядом аббревиатур, которые кажутся понятными по отдельности. Но может быть не очевидно, как их соотнести и структурировать (суждение субъективно и зависит от предыдущего опыта).
В данной статье рассмотрено как из Android кода получить исчерпывающие данные о Wi-Fi окружении без NDK, хаков, а лишь с помощью Android API и понять, как их интерпретировать.
Не будем тянуть и начнем писать код.
1. Создаем проект
Заметка рассчитана на тех, кто больше одного раза создавал Android проект, поэтому подробности данного пункта опускаем. Код ниже будет представлен на языке Kotlin, minSdkVersion=23.
2. Разрешения на доступы
Для работы с Wi-Fi из приложения понадобится получить от пользователя несколько разрешений. В соответствии с документацией, для того, чтобы осуществить сканирование сети на устройствах с ОС версий после 8.0, помимо доступа к просмотру состояния сетевого окружения нужен либо доступ на изменение состояния модуля Wi-Fi устройства, либо доступ к координатам (примерным или точным). Начиная с версии 9.0 необходимо запросить у пользователя и то и то, и при этом явно запросить у пользователя включить службу определения местоположения. Не забываем галантно объяснять пользователю, что это прихоть компании Google, а не наше желание устроить за ним слежку :)
Итого, в AndroidManifest.xml добавим:
А в коде, в котором есть ссылка на текущую Activity:
3. Создаем BroadcastReceiver и подписываемся на события обновления данных о сканировании сетевого окружения Wi-Fi
Метод WiFiManager.startScan в документации помечен как depricated с версии API 28, но офф. guide предлагает использовать его.
Итого, получили список объектов ScanResult.
4. Смотрим на ScanResult и разбираемся в терминах
Посмотрим на некоторые поля этого класса и опишем, что они означают:
SSID — Service Set Identifier – это название сети
BSSID – Basic Service Set Identifier – MAC адрес сетевого адаптера (Wi-Fi точки)
level — Received Signal Strength Indicator [dBm (русское дБм) — Децибел, опорная мощность 1 мВт.] — Показатель уровня принимаемого сигнала. Принимает значение от 0 до -100, чем дальше от 0, тем больше мощности сигнала потерялось по пути от Wi-Fi точки к вашему устройству. Подробнее можно посмотреть например на Википедии. Здесь же расскажу, что с помощью Android класса WifiManager можно проградуировать уровень сигнала по шкале от отличного до ужасного с выбранным вами шагом:
frequency — частота работы точки Wi-Fi [Гц]. Помимо самой частоты вас может заинтересовать так называемый канал. У каждой точки есть своя рабочая чистота. На момент написания текста наиболее популярным диапозоном Wi-Fi точек является 2.4 GHz. Но, если быть точнее, точка передает информацию на ваш телефон на пронумерованной частоте, близкой к названной. Количество каналов и значения соответствующих частот стандартизованы. Это сделано для того, чтобы точки поблизости работали на разных частотах, тем самым не создавая помехи друг другу и взаимно не понижая скорость и качество передачи. При этом точки работают не на одной частоте, а на диапазоне частот (пареметр channelWidth), называемом шириной канала. То есть точки, работающие на соседних (и не только на соседних, а даже на 3 от себя) каналах создают друг другу помехи. Вам может пригодится этот незамысловатый код, который позволяет вычислить номер канала по значению частоты для точек с частотой 2.4 и 5 Ghz:
capabilities — наиболее интересное поле для анализа, работа с которым потребовало много времени. Тут в строку записываются «возможности» точки. При этом подробности интерпритации строки в документации можно не искать. Вот несколько примеров того, что может лежать в этой строке:
5. Разбираемся в аббревиатурах и парсим capabilities
Будем действовать последовательно. Рассмотрим сначала вывод такого формата, при котором внутри скобок элементы отделены знаком "-":
Первое значение описывает т.н. метод аутентификации (authentication). То есть, какую последовательность действий должны произвести устройство и точка доступа, чтобы точка доступа позволила собой пользоваться и каким образом шифровать полезную нагрузку. На момент написания поста самые частые варианты это WPA и WPA2, при котором либо каждое подключаемое устройство напрямую, либо через т.н. RADIUS-сервер (WPA-Enterprice) предоставляет пароль по зашифрованному каналу. Скорее всего у вас дома точка доступа предоставляет подключение по этой схеме. Отличие второй версии от первой в болеее стойком шифре: AES против небезопасного TKIP. Также постепенно внедряется WPA3, более сложный и продвинутый. Теоритически может встретиться вариант с enterprice-решением CCKM (Cisco Centralized Key Managment), но мне так и не встретился.
Точка доступа могла быть настроена на аутентификацию по MAC-адресу. Или, если точка доступа предоставляет данные по устаревшему алгоритму WEP, то аутентификации фактически нет (секретный ключ тут и является ключом шифрования). Такие варианты отнесем к типу OTHER.
Ещё есть полюбившийся в общественных wi-fi метод со скрытым Captive Portal Detection — запрос аутентификации через браузер. Такие точки доступа выглядят для сканера как открытые (какими с точки зраения физического подключения и являются). Поэтому отнесем их к типу OPEN.
Второе значение можно обозначить как алгоритм использования ключей (key management). Является параметром метода аутентификации, о котором написано выше. Говорит о том, как именно происходит обмен ключами шифрования. Рассмотрим возможные варианты. EAP — используется в упомянутом WPA-Enterprice, использует базу данных для сверки введеных аутентификационных данных. SAE — используется в продвинутом WPA3, более устойчива к перебору. PSK — самый частый вариант, подразумевает ввод пароля и его передачу в зашифрованном виде. IEEE8021X — по международному стандарту (отличному от поддержанным семейством WPA). OWE (Opportunistic Wireless Encryption) является расширением стандарта IEEE 802.11, для точек, которые мы отнесли к типу OPEN. OWE обеспечивает безопасность данных, передаваемых по незащищенной сети, за счет их шифрования. Также возможен варинант когда ключей доступа нет, назовем такой вариант NONE.
Третьим параметром является т.н. метод шифрования (encryption schemes) — как именно используется шифр для зашиты передаваемых данных. Перечислим варианты. WEP — использует поточный шифр RC4, секретный ключ является ключом шифрования, что в мире современной криптографии считается неприемлемым. TKIP — используется в WPA, CKIP — в WPA2. TKIP+CKIP — может быть указан в точках умеющих WPA и WPA2 для обратной совместимости.
Вместо трех элементов можно встретить одинокую пометку WEP:
Как мы обсудили выше, этого достаточно чтобы не конкретизировать алгоритм использования ключей, которого нет, и метода шифрования, которое одно по-умолчанию.
Теперь рассмотрим такую скобочку:
Это режим работы Wi-Fi или топология сетей Wi-Fi. Вам может встретиться Режим BSS (Basic Service Set) — когда есть одна точка доступа, через которую общаются подключенные устройства. Можно встретить в локальных сетях. Как правило точки доступа нужны для того, чтобы соединять устройства из разных локальных сетей, поэтому они являются частью Extended Service Sets — ESS. Тип IBSSs (Independent Basic Service Sets) говорит о том, что устройство является частью Peer-to-Peer сети.
Ещё может попасться флаг WPS:
6. Создаем модель и функцию парсинга
На основе того, что выяснили выше опишем data-классами то, что получилось:
Теперь напишем функцию, которая будет парсить поле capabilities:
8. Смотрим результат
Посканирую сеть и покажу, что получилось. Показаны результаты простого вывода через Log.d:
Спасибо Егору Пономареву за ценные дополнения.
Android позволяет приложениям получать доступ для просмотра состояния доступа беспроводных соединений на очень низком уровне. Приложение может получить доступ практически ко всей информации о подключении Wi-Fi.
Информация, к которой приложение может получить доступ, включает скорость соединения в подключенной сети, IP-адрес, состояние согласования, другую информацию о сети. Приложения также могут сканировать, добавлять, сохранять, прерывать и инициировать соединения Wi-Fi.
addNetwork (конфигурация WifiConfiguration)
Этот метод добавляет новое описание сети в набор настроенных сетей.
createWifiLock (строковый тег)
Этот метод создает новый WifiLock.
Этот метод отсоединяется от текущей активной точки доступа.
enableNetwork (int netId, логическое значение disableOthers)
Этот метод позволяет связать ранее настроенную сеть.
getWifiState ()
Этот метод получает состояние Wi-Fi включен
isWifiEnabled ()
Этот метод возвращает, включен ли Wi-Fi или нет.
setWifiEnabled (логическое значение включено)
Этот метод включает или отключает Wi-Fi.
Ниже приводится содержимое измененного основного файла активности src / MainActivity.java .
Ниже приводится измененное содержимое файла xml res / layout / activity_main.xml .
Ниже приводится содержимое файла AndroidManifest.xml .
Давайте попробуем запустить ваше приложение. Я предполагаю, что вы подключили свое фактическое мобильное устройство Android к компьютеру. Чтобы запустить приложение из студии Android, откройте один из файлов деятельности вашего проекта и нажмите «Выполнить». значок с панели инструментов. Перед запуском приложения Android Studio отобразит следующее окно, чтобы выбрать опцию, в которой вы хотите запустить приложение Android.
Выберите ваше мобильное устройство в качестве опции, и оно покажет следующее изображение
Теперь нажмите на кнопку «отключить Wi-Fi». Пример вывода должен быть таким:
где context – используем текущую Activity , т.е. this ; - text – текст, который надо показать; — duration – продолжительность показа ( Toast.LENGTH_LONG — длинная, Toast.LENGTH_SHORT — короткая); - show () – отображение на экране.
Ниже на рисунке пример работы на эмуляторе и скриншот реального девайса:
Выводим состояние сети либо wi–fi либо мобильный интернет.
Ниже на рисунках пример работы:
Ниже на рисунках пример работы:
Теперь в методе onCreate, который отвечает за установку параметров и инициализации активности, переопределим методы для выше описанного класса. Зарегистрируем объект данного класса в системе, и с помощью фильтра IntentFilter получаем необходимое событие, а именно изменение сетевого подключения. Если параметры нашего Intent совпадают с условиями этого фильтра, то Activity вызывается. Ниже код.
Этот метод предназначен для использования в эмулируемых средах обработки. Он никогда не будет вызываться на реальном устройстве Android, где процессы удаляются, просто убивая их. При этом не выполняется код пользователя (включая этот обратный вызов).
Если вы переопределите этот метод, вы должны выполнить вызов суперкласса.
Для просмотра сетей Wi-Fi и вывода информации создадим еще один класс и наследуемся от BroadcastReceiver.
И будем производить поиск сетей по нажатию на кнопку. Ниже код и рисунок работы на эмуляторе и реальном устройстве. Работу с кнопкой в Android-приложении мы частично рассматривали в прошлой статье а также в приложении подключения AVR к ОС Android.
Для работы данного приложения необходимо внести разрешения в файл Манифеста, , в корневом теге <manifest>.
где первый получает доступ к приблизительному местоположению, второй — приложение сможет получать доступ к точному местоположению. Два последних разрешения являются опасными.
И в методе OnCreate пропишем следующую строку.
Все, добавляем код в наше приложение SmartHouse. Теперь мы имеем доступ к сетям. В последующем мы выведем сети Wi-Fi в листинг и научимся выбирать определенную и подключаться к ней. В следующей статье вернемся к контроллеру STM32 и свяжем его с ESP8266, который по нашей задумке будет управляющим элементом в системе умный дом. На этом сегодня и остановимся. Всем пока.
Читайте также: