Android peer to peers

Wi-Fi Peer-to-Peer

In this document

See also

Wi-Fi peer-to-peer (P2P) allows Android 4.0 (API level 14) or later devices with the appropriate hardware to connect directly to each other via Wi-Fi without an intermediate access point (Android’s Wi-Fi P2P framework complies with the Wi-Fi Alliance’s Wi-Fi Direct™ certification program). Using these APIs, you can discover and connect to other devices when each device supports Wi-Fi P2P, then communicate over a speedy connection across distances much longer than a Bluetooth connection. This is useful for applications that share data among users, such as a multiplayer game or a photo sharing application.

The Wi-Fi P2P APIs consist of the following main parts:

  • Methods that allow you to discover, request, and connect to peers are defined in the WifiP2pManager class.
  • Listeners that allow you to be notified of the success or failure of WifiP2pManager method calls. When calling WifiP2pManager methods, each method can receive a specific listener passed in as a parameter.
  • Intents that notify you of specific events detected by the Wi-Fi P2P framework, such as a dropped connection or a newly discovered peer.

You often use these three main components of the APIs together. For example, you can provide a WifiP2pManager.ActionListener to a call to discoverPeers() , so that you can be notified with the ActionListener.onSuccess() and ActionListener.onFailure() methods. A WIFI_P2P_PEERS_CHANGED_ACTION intent is also broadcast if the discoverPeers() method discovers that the peers list has changed.

API Overview

The WifiP2pManager class provides methods to allow you to interact with the Wi-Fi hardware on your device to do things like discover and connect to peers. The following actions are available:

Table 1.Wi-Fi P2P Methods

Method Description
initialize() Registers the application with the Wi-Fi framework. This must be called before calling any other Wi-Fi P2P method.
connect() Starts a peer-to-peer connection with a device with the specified configuration.
cancelConnect() Cancels any ongoing peer-to-peer group negotiation.
requestConnectInfo() Requests a device’s connection information.
createGroup() Creates a peer-to-peer group with the current device as the group owner.
removeGroup() Removes the current peer-to-peer group.
requestGroupInfo() Requests peer-to-peer group information.
discoverPeers() Initiates peer discovery
requestPeers() Requests the current list of discovered peers.

WifiP2pManager methods let you pass in a listener, so that the Wi-Fi P2P framework can notify your activity of the status of a call. The available listener interfaces and the corresponding WifiP2pManager method calls that use the listeners are described in the following table:

Table 2. Wi-Fi P2P Listeners

Listener interface Associated actions
WifiP2pManager.ActionListener connect() , cancelConnect() , createGroup() , removeGroup() , and discoverPeers()
WifiP2pManager.ChannelListener initialize()
WifiP2pManager.ConnectionInfoListener requestConnectInfo()
WifiP2pManager.GroupInfoListener requestGroupInfo()
WifiP2pManager.PeerListListener requestPeers()

The Wi-Fi P2P APIs define intents that are broadcast when certain Wi-Fi P2P events happen, such as when a new peer is discovered or when a device’s Wi-Fi state changes. You can register to receive these intents in your application by creating a broadcast receiver that handles these intents:

Table 3. Wi-Fi P2P Intents

Intent Description
WIFI_P2P_CONNECTION_CHANGED_ACTION Broadcast when the state of the device’s Wi-Fi connection changes.
WIFI_P2P_PEERS_CHANGED_ACTION Broadcast when you call discoverPeers() . You usually want to call requestPeers() to get an updated list of peers if you handle this intent in your application.
WIFI_P2P_STATE_CHANGED_ACTION Broadcast when Wi-Fi P2P is enabled or disabled on the device.
WIFI_P2P_THIS_DEVICE_CHANGED_ACTION Broadcast when a device’s details have changed, such as the device’s name.

Creating a Broadcast Receiver for Wi-Fi P2P Intents

A broadcast receiver allows you to receive intents broadcast by the Android system, so that your application can respond to events that you are interested in. The basic steps for creating a broadcast receiver to handle Wi-Fi P2P intents are as follows:

  1. Create a class that extends the BroadcastReceiver class. For the class’ constructor, you most likely want to have parameters for the WifiP2pManager , WifiP2pManager.Channel , and the activity that this broadcast receiver will be registered in. This allows the broadcast receiver to send updates to the activity as well as have access to the Wi-Fi hardware and a communication channel if needed.
  2. In the broadcast receiver, check for the intents that you are interested in onReceive() . Carry out any necessary actions depending on the intent that is received. For example, if the broadcast receiver receives a WIFI_P2P_PEERS_CHANGED_ACTION intent, you can call the requestPeers() method to get a list of the currently discovered peers.
Читайте также:  Теми для андроид весна

The following code shows you how to create a typical broadcast receiver. The broadcast receiver takes a WifiP2pManager object and an activity as arguments and uses these two classes to appropriately carry out the needed actions when the broadcast receiver receives an intent:

Creating a Wi-Fi P2P Application

Creating a Wi-Fi P2P application involves creating and registering a broadcast receiver for your application, discovering peers, connecting to a peer, and transferring data to a peer. The following sections describe how to do this.

Initial setup

Before using the Wi-Fi P2P APIs, you must ensure that your application can access the hardware and that the device supports the Wi-Fi P2P protocol. If Wi-Fi P2P is supported, you can obtain an instance of WifiP2pManager , create and register your broadcast receiver, and begin using the Wi-Fi P2P APIs.

Request permission to use the Wi-Fi hardware on the device and also declare your application to have the correct minimum SDK version in the Android manifest:

  • Check to see if Wi-Fi P2P is on and supported. A good place to check this is in your broadcast receiver when it receives the WIFI_P2P_STATE_CHANGED_ACTION intent. Notify your activity of the Wi-Fi P2P state and react accordingly:
  • In your activity’s onCreate() method, obtain an instance of WifiP2pManager and register your application with the Wi-Fi P2P framework by calling initialize() . This method returns a WifiP2pManager.Channel , which is used to connect your application to the Wi-Fi P2P framework. You should also create an instance of your broadcast receiver with the WifiP2pManager and WifiP2pManager.Channel objects along with a reference to your activity. This allows your broadcast receiver to notify your activity of interesting events and update it accordingly. It also lets you manipulate the device’s Wi-Fi state if necessary:
  • Create an intent filter and add the same intents that your broadcast receiver checks for:
  • Register the broadcast receiver in the onResume() method of your activity and unregister it in the onPause() method of your activity:

    When you have obtained a WifiP2pManager.Channel and set up a broadcast receiver, your application can make Wi-Fi P2P method calls and receive Wi-Fi P2P intents.

    You can now implement your application and use the Wi-Fi P2P features by calling the methods in WifiP2pManager . The next sections describe how to do common actions such as discovering and connecting to peers.

    Discovering peers

    To discover peers that are available to connect to, call discoverPeers() to detect available peers that are in range. The call to this function is asynchronous and a success or failure is communicated to your application with onSuccess() and onFailure() if you created a WifiP2pManager.ActionListener . The onSuccess() method only notifies you that the discovery process succeeded and does not provide any information about the actual peers that it discovered, if any:

    If the discovery process succeeds and detects peers, the system broadcasts the WIFI_P2P_PEERS_CHANGED_ACTION intent, which you can listen for in a broadcast receiver to obtain a list of peers. When your application receives the WIFI_P2P_PEERS_CHANGED_ACTION intent, you can request a list of the discovered peers with requestPeers() . The following code shows how to set this up:

    The requestPeers() method is also asynchronous and can notify your activity when a list of peers is available with onPeersAvailable() , which is defined in the WifiP2pManager.PeerListListener interface. The onPeersAvailable() method provides you with an WifiP2pDeviceList , which you can iterate through to find the peer that you want to connect to.

    Читайте также:  Андроид acer liquid z530

    Connecting to peers

    When you have figured out the device that you want to connect to after obtaining a list of possible peers, call the connect() method to connect to the device. This method call requires a WifiP2pConfig object that contains the information of the device to connect to. You can be notified of a connection success or failure through the WifiP2pManager.ActionListener . The following code shows you how to create a connection to a desired device:

    Transferring data

    Once a connection is established, you can transfer data between the devices with sockets. The basic steps of transferring data are as follows:

    1. Create a ServerSocket . This socket waits for a connection from a client on a specified port and blocks until it happens, so do this in a background thread.
    2. Create a client Socket . The client uses the IP address and port of the server socket to connect to the server device.
    3. Send data from the client to the server. When the client socket successfully connects to the server socket, you can send data from the client to the server with byte streams.
    4. The server socket waits for a client connection (with the accept() method). This call blocks until a client connects, so call this is another thread. When a connection happens, the server device can receive the data from the client. Carry out any actions with this data, such as saving it to a file or presenting it to the user.

    The following example, modified from the Wi-Fi P2P Demo sample, shows you how to create this client-server socket communication and transfer JPEG images from a client to a server with a service. For a complete working example, compile and run the Wi-Fi P2P Demo sample.

    On the client, connect to the server socket with a client socket and transfer data. This example transfers a JPEG file on the client device’s file system.

    Источник

    История создания библиотеки для группового общения андроид-устройств через 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, что позволило беспрепятственно общаться между ними.

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

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

    Источник

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