Java подключение к wifi

Обновлено: 06.07.2024

Узнайте, как программно взаимодействовать с сетевыми интерфейсами с помощью Java.

1. Обзор

В этой статье мы сосредоточимся на сетевых интерфейсах и на том, как получить к ним программный доступ на Java.

На повседневном языке мы называем их сетевыми интерфейсными картами (NIC), но не все они должны иметь аппаратную форму.

Конечно, системы часто имеют несколько активных сетевых подключений, таких как проводной Ethernet, Wi-Fi, Bluetooth и т. Д.

2. Зачем Нужен Доступ К Сетевым Интерфейсам?

Большинство программ Java, вероятно, не будут взаимодействовать с ними напрямую; однако существуют специальные сценарии, когда нам действительно нужен такой низкоуровневый доступ.

Наиболее выдающимся из них является то, что в системе есть несколько карт, и вы хотели бы иметь свободу выбора конкретного интерфейса для использования сокета с . В таком сценарии мы обычно знаем имя, но не обязательно IP-адрес.

Обычно, когда мы хотим подключить сокет к определенному адресу сервера:

Таким образом, система выберет подходящий локальный адрес, свяжется с ним и свяжется с сервером через свой сетевой интерфейс. Однако такой подход не позволяет нам выбирать самостоятельно.

Здесь мы сделаем предположение: мы не знаем адреса, но знаем имя. Просто в демонстрационных целях предположим, что нам нужно соединение через интерфейс обратной связи, по соглашению, его имя lo , по крайней мере, в системах Linux и Windows, в OSX это lo0 :

Поэтому мы сначала извлекаем сетевой интерфейс, подключенный к lo , извлекаем прикрепленные к нему адреса, создаем сокет, привязываем его к любому из перечисленных адресов, которые мы даже не знаем во время компиляции, а затем подключаемся.

Объект Сетевой интерфейс содержит имя и набор назначенных ему IP-адресов. Таким образом, привязка к любому из этих адресов гарантирует связь через этот интерфейс.

На самом деле это не говорит ничего особенного об API. Мы знаем, что если мы хотим, чтобы наш локальный адрес был localhost, первого фрагмента будет достаточно, если мы просто добавим код привязки.

Кроме того, нам никогда не придется проходить все несколько шагов, так как localhost имеет один хорошо известный адрес, 127.0.0.1 и мы можем легко привязать к нему сокет.

Однако в вашем случае lo , возможно , представлял бы другие интерфейсы, такие как Bluetooth – net1 , беспроводная сеть – net0 или ethernet – eth0 . В таких случаях вы не будете знать IP-адрес во время компиляции.

3. Получение Сетевых Интерфейсов

В этом разделе мы рассмотрим другие доступные API для получения доступных интерфейсов. В предыдущем разделе мы видели только один из этих подходов-статический метод getByName () .

Стоит отметить, что класс NetworkInterface не имеет открытых конструкторов, поэтому мы, конечно, не можем создать новый экземпляр. Вместо этого мы собираемся использовать доступные API для получения одного из них.

API, который мы рассматривали до сих пор, используется для поиска сетевого интерфейса по указанному имени:

Он возвращает null , если для имени нет:

Второй API-это getByInetAddress() , он также требует, чтобы мы предоставили известный параметр, на этот раз мы можем предоставить IP-адрес:

Или если вы конкретны в отношении localhost:

Другой альтернативой также является явное использование интерфейса обратной связи:

Третий подход, который был доступен только с Java 7, заключается в том, чтобы получить сетевой интерфейс по его индексу:

Последний подход предполагает использование API getNetworkInterfaces . Он возвращает Перечисление всех доступных сетевых интерфейсов в системе. Это на нас, чтобы получить возвращенные объекты в цикле, стандартная идиома использует Список :

4. Параметры сетевого Интерфейса

Существует много ценной информации, которую мы можем получить от одного из них после извлечения его объекта. Одним из наиболее полезных является список назначенных ему IP-адресов .

Мы можем получить IP-адреса, используя два API. Первый API-это getInetAddresses() . Он возвращает Перечисление экземпляров InetAddress , которые мы можем обрабатывать по своему усмотрению:

Второй API-это getInterfaceAddresses() . Он возвращает Список адресов интерфейсов экземпляров, которые являются более мощными, чем InetAddress экземпляры. Например, помимо IP-адреса, вас может заинтересовать широковещательный адрес:

Мы можем получить доступ к сетевым параметрам интерфейса, помимо имени и IP-адресов, назначенных ему. Чтобы проверить, работает ли он:

Чтобы проверить, является ли это интерфейсом обратной связи:

Чтобы проверить, представляет ли он сетевое соединение точка-точка:

Или если это виртуальный интерфейс:

Чтобы проверить, поддерживается ли многоадресная рассылка:

Или для получения его физического адреса, обычно называемого MAC-адресом:

Другим параметром является Максимальная единица передачи, которая определяет наибольший размер пакета, который может быть передан через этот интерфейс:

5. Заключение

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

Полный исходный код и примеры, используемые в этой статье, доступны в проекте Github .


Предположим, мы пишем игру для Android, которая подразумевает некое сетевое взаимодействие между устройствами. Причем наши устройства находятся в одной сети и мы хотим, чтобы взаимодействие между ними осуществлялось быстро, а значит вариант с обменом данными через интернет нам не подходит. Ах да, еще одна маленькая ложка дегтя — мы хотим охватить максимально возможную аудиторию, для чего нам необходимо поддерживать Android 2.3.
Что же нам делать? Давайте поговорим об этом, а заодно рассмотрим относительно новые возможности Android SDK для соединения двух и более устройств.

О чем это и для кого это?

Как-то раз, уйдя с предыдущего места работы и погрузившись в заслуженный отдых, я принялся писать сетевую игру, в которую могут играть люди, находящиеся в одной локальной сети. И сразу же столкнулся с тем, что для нормального функционирования подобной игры нам мало соорудить сетевое взаимодействие — нам нужно сделать нормальное и быстрое обнаружение устройств в сети. Собственно, в данной статье я поделюсь своим опытом в реализации решения для данной задачи.
Сразу оговорюсь, что статья предназначена в большей мере для тех, кто имеет опыт Android-разработки, написал несколько приложений и хочет расширить свой кругозор, а также улучшить профессиональные навыки.

Какие возможные способы решения существуют?

    . Простой и эффективный способ обнаружения устройств. На Android Developer есть пошаговое руководство по подключению NSD, есть пример NsdChat, который можно скачать там же. Но есть один существенный минус — данный метод поддерживается только начиная с API Level 16, то есть с Android 4.1 Jelly Bean;
  1. Второе решение, предлагаемое нам на сайте Android Developer — Wi-Fi Peer-to-Peer. Проблема этого метода та же самая — поддерживается он только начиная с API Level 16;
  2. Есть странное решение, которое предлагается некоторыми программистами на Stack Overflow — самостоятельно сканировать локальную сеть на предмет наличия сервера. То есть проходить по всем адресам сети. Это уже сейчас звучит как странный велосипед, а теперь представьте, что порт нашего сервера назначается автоматически. Таким образом, сканирование даже самую небольшой сети становится достаточно долгой и трудоемкой задачей;
  3. Наконец, мы можем обратить внимание на Java-библиотеки и написать что-нибудь с их использованием. Например, JmDNS.

Я вооружился JmDNS и решил попробовать соорудить несколько классов, которые по максимуму упростят написание описанных выше приложений. Но для начала пришлось немного повырезать дубликаты .class-файлов из jar-пакета JmDNS (проблема описана здесь):

Далее я взял исходный код NsdChat с Android Developer и изменил его служебный класс, который отвечает за инициализацию сокетов и организацию сетевого взаимодействия. Также я написал wrapper для JmDNS

  1. startServer для создания сервера и регистрации соответствующего сервиса в локальной сети;
  2. findServers для поиска серверов;
  3. reset для окончания работы с Network Discovery и последующего освобождения ресурсов;
  4. wifiLock для запроса блокировки Wi-Fi.

И, наконец, метод для обнаружения и подключения к серверу:

Как видите, все очень просто. А главное, все это работает в любой версии Android для максимум двух устройств. Но сделать так, чтобы это работало для условно неограниченного числа устройств очень легко, и очевидное решение придет к вам почти сразу после детального изучения класса Connection. Пусть это будет в качестве домашнего задания.
Ах, да, весь код доступен для изучения и использования всеми желающими в моем репозитории на GitHub.. И, конечно, не исключаю то, что некоторые вещи можно сделать лучше и проще, поэтому не стесняйтесь форкать и делать pull request'ы.


Всем привет. Давайте вспомним, что в прошлой статье мы с Вами остановились на поиске сетей Wi-Fi и переносе их SSID-ов в кликабельный список. В этой записи рассмотрим один из способов подключения к необходимой сети из нашего приложения SmartHouse. На самом деле задача оказалась довольно непростой, начиная с версии Android 5.

Наш план действий: – рассмотреть способы подключения к сетям; – изменения в политике безопасности; – способы получения необходимых разрешений; – добавление функциональных кнопок в разрабатываемое приложение. Итак все по порядку.

Для начала добавим проверку включения модуля wi-fi, если выключен — включаем.

Settings.Global.putInt (getContentResolver (), Settings.Global.CAPTIVE_PORTAL_DETECTION_ENABLED, 0); , где CAPTIVE_PORTAL_DETECTION_ENABLED должен быть глобальным параметром, который установкой в 0 избегает проверки (тестирование сервером google) wi-fi на интернет-доступ.

К сожалению в зависимости от версии Android Studio и ОС Android данная константа может быть скрыта и не поддерживаться. Из-за чего может потребоваться использовать напрямую строку «captive_portal_detection_enabled», а не константу:

Settings.Global.putInt (getContentResolver (), «captive_portal_detection_enabled», 0); Но это также может не помочь.

error

Есть возможность использовать adb (для изменения пользовательских настроек) , для чего необходимо иметь root-права . Этот способ я даже не пробовал использовать, т.к. нас интересует только программное решение. Так как у нас приложение должно будет вносить изменения, то нам необходимо получить разрешение WRITE_SETTINGS , что позволяет программе читать или записывать защищенные системные настройки. Данное разрешение было отменено из пользовательских приложений (как в не системных приложениях) в api23.

Итак чтобы использовать WRITE_SETTINGS необходимо:
— Прописать в манифесте <uses-permission android:name="android.permission.WRITE_SETTINGS"/>
Может потребоваться также <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/>. Хотя если есть WRITE_SETTINGS то последнее не требуется. По состоянию на Android 6.0.1 CHANGE_NETWORK_STATE автоматически предоставляется при запросе в вашем файле манифеста. Вышеуказанные проверки WRITE_SETTINGS требуются только для 6.0 ;
- Вызовите Settings.System.canWrite () , чтобы узнать, имеете ли вы право на запись настроек.
— Если canWrite () возвращает false, запустите действие ACTION_MANAGE_WRITE_SETTINGS , чтобы пользователь мог согласиться, и ваше приложение действительно могло писать настройки. Это необходимо сделать один раз.
В файл активности добавим функцию проверки данного разрешения.

write_not

Начиная с android Marshmellow, нам необходимо использовать разрешения во время выполнения, которые направлены на повышение безопасности, или использовать когда это необходимо. Ниже скриншоты проверки и включения:

Дозвіл

write_yes

Разрешение для программы получили. Теперь для подключения к wi-fi используем следующую функцию:

Для подключения к беспроводной сети без интернет соединения во первых мы должны:

wi-fi_esp

Ниже скриншот подсоединения телефона к модулю esp8266 и его свойства в конфигурации телефона.

propert_wi-fi

Подводим итог. В выше написанной статье мы рассмотрели включение модуля Wi-Fi. Получили необходимые разрешения для чтения и записи системных настроек. Рассмотрели изменения в политике безопасности подключения к сетям. Написали и разобрали функцию подключения без интернет доступа. Добавили кнопку освобождения сети. Хочется отметить, что данный код не всегда подключает модуль, например при отсутствии мобильного интернета, приложение не будет подсоединяться. На данном этапе для дальнейшего тестирования приложения и модуля остановимся на данном коде. В будущем рассмотрим стандарт Wi-Fi Direct (Wi-Fi Peer-to-Peer). В следующей статье научимся передавать данные через модуль ESP8266 в микроконтроллер STM32 и обратно. Добавим поле для вывода информации в приложение. На этом сегодня и остановимся. Всем пока.

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

я реализовал часть, показывающую результаты сканирования. Теперь я хочу подключиться к определенной сети, выбранной пользователем из списка результатов сканирования.

Как мне это сделать?

вам нужно создать WifiConfiguration например такой:

затем, для WEP сети вам нужно сделать это:

для сети WPA вам нужно добавить парольную фразу следующим образом:

для открытой сети вам нужно сделать это:

затем вам нужно добавить его в Настройки Android wifi manager:

и, наконец, вам может потребоваться включить его, поэтому Android подключается к это:

UPD: в случае WEP, если ваш пароль находится в hex, вам не нужно окружать его кавычками.

на более ранний ответ работает, но решение на самом деле может быть проще. Цикл по списку настроенных сетей не требуется, так как вы получаете идентификатор сети при добавлении сети через WifiManager.

Итак полное, упрощенное решение будет выглядеть примерно так:

перед подключением Wi-Fi сети вам нужно проверить тип безопасности Wi-Fi сети ScanResult класс имеет возможности. Это поле дает вам тип сети

здесь три типа сетей WIFI.

сначала создайте экземпляр объекта WifiConfiguration и заполните SSID сети (обратите внимание, что он должен быть заключен в двойные кавычки), установить начальное состояние отключено и указать приоритет сети (номера вокруг 40, похоже, работают хорошо).

теперь более сложная часть: нам нужно заполнить несколько членов WifiConfiguration, чтобы указать режим безопасности сети. Для открытых сетей.

для сетей, использующих WEP; обратите внимание, что ключ WEP также заключен в двойные кавычки.

для сетей используя WPA и WPA2, мы можем установите одинаковые значения для любого из них.

наконец, мы можем добавить сеть в известный список WifiManager

кредит @raji-ramamoorthi & @kenota

решение, которое сработало для меня, - это комбинация вышеуказанных участников в этой теме.

и ScanResult здесь процесс.

обратите внимание на unregister на onPause & onStop жить unregisterReceiver(broadcastReceiver);

Если ваше устройство знает конфигурации Wifi (уже сохраненные), мы можем обойти ракетостроение. Просто пройдите через конфигурации и проверьте, соответствует ли SSID. Если да, то подключитесь и возвращение.

установить разрешения:

подключение:

Я сломал голову, чтобы понять, почему ваши ответы на WPA / WPA2 не работают. после часа попыток, я нашел то, что вам не хватает:

требуется для информационной безопасности.

теперь, это работает :)

Читайте также: