Wifi direct android api

История создания библиотеки для группового общения андроид-устройств через Wi-Fi Peer-to-Peer соединение

Предыстория

Мотивом написания данного приложения послужила курсовая работа по дисциплине «Компьютерные системы и сети». Честно говоря, эта одна из самых мной нелюбимых сторон в компьютерных технологиях, и я решил «подстраивать» курсовой проект под свои интересы, а именно, под Андроид-разработку.

Было решено создать библиотеку для соединения Андроид-устройств по средством Wi-Fi Direct технологии и передачи данных между ними (Wi-Fi Peer-to-Peer соединение осуществляется как раз с помощью технологии Wi-Fi Direct).

Почему Wi-Fi Direct?

После одобрения идеи о локальном соединении устройств передо мной встал вопрос: С помощью какой технологии собираюсь я это осуществить? Рассматривались следующие варианты:

  • Bluetooth
  • Wi-Fi Hotspot
  • Wi-Fi Direct или Wi-Fi Peer-to-Peer

Bluetooth

Wi-Fi Hotspot

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

Однако с помощью Wi-Fi Hotspot можно добиться максимальной скорости передачи данных (приложения Portal, SHAREit).

Wi-Fi Direct или Wi-Fi Peer-to-Peer

Данный подход решает все вышеупомянутые проблемы:

  1. неограниченное кол-во клиентов (если не так, прошу меня поправить)
  2. большой радиус действия
  3. соединение с устройствами по средством Wi-Fi без создания точки доступа
  4. технология поддерживается с API 14 (Android 4.0)

Но сразу закрадывается сомнение, мол Wi-Fi Peer-to-Peer, тогда как мы собираемся создать группу с владельцем и клентами, и тем более, чтобы все друг с другом общались. Это как раз-таки и является основной причиной написания данной статьи.

Wi-Fi Aware

Начнем с проблем

Скажу честно, предоставляемая документация by developer.android.com давалась мне нелегко. И я начал искать сэмплы. Перебрав кучу материала, наткнулся на наиболее интересный sample by Google.

Никогда не думал, что на официальном сайте от Google можно найти говнокод, но это как раз тот случай. Однако даже этому стоит отдать должное, так как благодаря данному ресурсу я реализовал то, что хотел.

В сэмпле продемонстрирован пример чата двух устройств, которые нашли друг друга в списке, отображающем рядом находящиеся Wi-Fi Direct устройства с запущенным приложением чата. При выборе партнера непосредственно открывается ChatActivity.

Очень важным моментом является поиск собеседников: в списке не будут отображаться такие Wi-Fi Direct устройства, как телевизор или какая-нибудь гарнитура. Отображаются только устройства с запущенным Chat-приложением.

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

Что было реализовано для демонстрации работоспособности библиотеки

Приложение представляет следующий функционал:

  1. выбор роли в процессе работы с приложением (для примера были созданы «Мафия» и «Мирный житель»)
  2. создание группы
  3. присоединение к существующей группе
  4. общение между устройствами (при нажатии на кнопку меняется ее цвет как у инициатора, так и у всех остальных, соответствующих текущей роли (либо broadcast))

Описание экранов слева-направо:

  • стартовый экран с выбором действия и роли
  • список присоединившихся устройств к текущему владельцу группы
  • список активных групп, к которым можно присоединиться
  • сеттинги приложения (логин устройства, название группы, пароль для вхождения в группу)
  • «игровой» экран
Читайте также:  Лаке патчер для андроид полная версия


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

Основная концепция работы библиотеки

Логика построена на основе архитектуры клиент-сервер. Сервером является владелец группы, клиентами — подсоединившиеся пользователи.

В приложении присутствуют собственные Serializer/Deserializer для преобразования передаваемых данных в массив байтов и обратно. В передаваемых данных хранится следующая информация:

  • кому отправить (мафии, мирным жителям, всем)
  • какого рода данные (например: изменение цвета кнопки)
  • сами данные (сериализованный Object)

Первый пункт «кому отправить» не совсем корректен, т.к. отправляются данные всем. Сначала серверу, потом сервер отправляет этот пакет всем клиентам. А вот клиент уже сам решает, стоит ему обрабатывать эти данные или нет. Сделано это по той простой причине, что сервер не знает ролей его клиентов. Таким образом было достигнуто равноправие в группе. Владелец отличается от всех остальных только тем, что его обременили заниматься передачей данных всем его клиентам.

Компоненты библиотеки

Самая сложная проблема во время разработки

Когда проект дошел до стадии тестирования мультиплеера (> 2 устройств), тут-то и началась жара. Два устройства как и прежде у меня соединялись без проблем (для чего впрочем и создан Wi-Fi Peer-to-Peer), однако при подсоединении третьего звена почти всегда происходил треш. При нажатии на кнопку у «владельца» (позже поймете, почему в кавычках) цвет менялся только у того клиента, с которым «владелец» последний раз общался.

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

До этого я считал, что тот девайс, который подсоединяется к другому, всегда будет клиентом… а это далеко не так. При соединении устройств рандомно передавались права владельца одному из них, что и побудило меня на поиск настройки config’a, который бы исправил эту ситуацию, и сделал подсоединяемое устройство клиентом.

При соединении двух устройств прописывается специальный config, который в себе содержит:

  • адрес устройства, к которому мы хотим присоединиться
  • wps.setup позволяет установить, как мы будем соединяться: с паролем или просто по нажатию кнопки
  • groupOwnerIntent — вот он (споймал!), тот, кто решил мою проблему; целочисленное поле, значение которого варьируется от 0 до 15 (0 — хотим быть клиентом, 15 — хотим быть владельцем); по умолчанию -1, что дает системе право самой выбрать роль в этой связи

Status’ом (enum) выше является текущее положение устройства, если он создатель группы — GroupOwner, иначе — Client.

Необходимые доработки

Пока не существует решения по проблеме восстановления соединения. Например, при выходе из приложения, например, чтобы совершить звонок, после возвращения нас ждет… ничего. После дестроя активности необходимо опять подтягивать клиентов себе, а клиентам — владельца.
Также хочется ввести понятие по передаче прав владельца одному из клиентов на тот случай, если владельцу группы необходимо покинуть игру.

Защита. Для входа в определенную группу было бы неплохо реализовать авторизацию.

Заключение

Не думаю, что я реализовал что-то новое или революционное, однако данный проект послужил хорошим примером неординарного использования Wi-Fi Peer-to-Peer соединения. Мною была успешно построена сеть между устройствами с помощью Wi-Fi Direct, что позволило беспрепятственно общаться между ними.

Читайте также:  Nokia android или windows

Это моя первая статья, поэтому судить строго. Спасибо за внимание.

→ Ссылка на GitHub
(модуль wifidirect может быть без проблем перенесен в любой андроид-проект)

Источник

Simplifying Android Development…

Blog by Kaushal D

Local networking in android – WiFi direct

In my earlier blog post I discussed data sharing between two android devices in same network using NSD. In this post I will explain communication between two non-connected android devices (can be connected to same or other network, doesn’t really matter) via WiFi direct. Devices should be in WiFi range. I will start with a bit of theory about WiFi direct and then we will see how it is implementable using android APIs (Sample app source code git link is at the end of this post).

Same as earlier post the problem addressed is sharing IP and port information. Communication again will be socket communication.

WiFi direct is a WiFi certified standard enabling devices to connect with each other without requiring a wireless access point (a.k.a router or WiFi hot spot). Using this, devices can communicate with each other at typical WiFi speeds, unlike ad hoc wireless connections (which allows two or more devices to connect and communicate, and has a limit of 11 Mbps) or Bluetooth, setup required for WiFi direct is much simpler. Here each member is assigned a limited access point and other members connect to it as regular clients. WPS and WPA2 are used for encryption and keep the communication private.

The peer device acting as current access point is said to be assuming a group owner role in WiFi direct group. A WiFi direct group consists of 1 group owner and devices or peers connected to it as clients (P2P clients). The group owner device sets properties for communication like operating channel, whether the group is persistent, encryption type etc. Any compatible device with right hardware and android ICS or above (API 14+) can assume group owner role. After role negotiation (group owner or P2P client), devices assume their decided role, and group owner starts operating in access point mode (this access point will not be visible under available networks of mobile devices).

Now coming to android. Android’s WiFi P2P framework complies with WiFi direct certification program. It consists of:

  • Methods that allows us to discover, request and connect to peers ( android.net.wifi.p2p.WifiP2pManager ).
  • Listeners that notifies us of success and failure of WifiP2pmanager’s method calls.
  • Intents to notify specific events, such as new peer joined, connection dropped etc. (like WIFI_P2P_PEERS_CHANGED_ACTION and WIFI_P2P_CONNECTION_CHANGED_ACTION )

Discovering peers

You need the following permissions for using WiFi direct for communication

Internet permission is required for using sockets anyway.

The above method is all you need to start the WiFi direct peer discovery. If you get a callback in failure method, check the reason code for it.

Getting peer list

Getting peer list is tricky, as WifiP2pManager will not give you that. This is done via broadcast receivers registered dynamically (not in the manifest file).

The second filter action in above code (the image) is what is triggered when a new peer has joined (or left). When broadcast with this action is received we can request peers from WifiP2pManager. It takes a callback to return entire peer list not just the new ones, so if you are displaying a list, clear the list and add all the peers received in the callback. here is the broadcast receiver’s code:

Читайте также:  Android studio listview xml

The callback that is overridden will be called asynchronously. Peer list can be extracted from there.

So now we have the peer list. We can display this list to user or call connect with each peer. Once the peer is discovered we need to send a connection request to connect and form a WiFi direct group.

Connecting with a peer

This step requires WiFi mac of the device. It is received as a part of peer info in discovery step. Here are the properties of WifiP2pDevice:

The WifiP2pDevice list that we received in OnPeersAvailable() method of PeerListListener callback has exactly what we need to make a connection request.

Here is how to make a connection request using WifiP2pManager.

Just create a config object set channel properties and call the connect method. The group owner intent value is for setting the probability of the device to become group owner. It’s value varies from 0-15 . 15 means highest chance of the connection request sender device to become group owner. But whatever code you write, you must handle both group owner and a regular P2P client scenario.

Once the request is sent to a device, the device user must accept the connection request from system prompt. After that role negotiation happens and devices move to their decided roles. After successful connection, a connection info request can be issued via WifiP2pManager. Which sends callback to WifiP2pManager.ConnectionInfoListener. It has only one method:

This connection info object WifiP2pInfo contains the IP information of group owner. Check below:

So now, our first problem is addressed, here we got the IP address of the group owner. And we also know whether the current device is group owner or not. So basically every peer in the group knows the group owner’s IP address.

The remaining problem is sharing the port it is listening on. I couldn’t find any proper solution for this, I solved it by prefixing the port, then sharing the dynamic port data with clients, and then clients can share their own info and dynamic port. So first communication happens over the fixed port and after that, then dynamic port data number is transferred, and then it is regular socket communication. Check out my sample app for this.

Even this problem can be solved using the WiFi direct service discovery. Watch out for my next post on this topic.

One last thing to cover in this post is method called createGroup(). This method is for supporting the legacy devices with no WiFi direct hardware. This basically an access point and any device with WiFi capability can connect with it like a regular access point and share data like we did in my previous post. On top of that it can work as expected in WiFi direct scenario, so support both types of devices.

Let me know what you think. Got any questions? shoot below in comments.

Источник

Оцените статью