5

The problem: I'm making an offline-multiplayer android game, where people can create or join a room and play together via Wi-fi. Consider the situation when a user creates a room and he (of course) has to inform all other users that there is a room available. So the question is "How?".I've read about 1000 times this and this. It's written there that in order to send some data to another device, one of them should be a server and the other one a client. Client sends some info to the server, server accepts it. So, does it mean that I have to make all "players" servers and the "room creator" should become a client? This sounds crazy. Please help, may be I'm reading the wrong docs?

Bartek Lipinski
  • 30,698
  • 10
  • 94
  • 132
Sergey Maslov
  • 758
  • 1
  • 8
  • 22

2 Answers2

14

First of all you need to remember that if you do decide to use WiFiP2P in your project you will need to prepare yourself for some difficult time. Unfortunately (as you already might have noticed :)) WiFiP2P Android's official documentation is not that great. Different devices behave in different ways (e.g. they call some WifiP2P events in different order) and docs don't cover it at all. Achieving a stable connection requires introducing unconventional and sometimes drastic measures. Obtaining a WifiP2P connection is inseperably linked with displaying a system window (asking if you really want to connect to a device).

There are few things you need to consider before you start implementing a WifiP2P solution:

  1. Will players of your game be able to connect to more than one room simultaneously?
  2. Will players of your game be able to detect new room while connected to another?
  3. Will players of your game be able to name their rooms with "human-readable" names? And those names would be used by other users (not the creator of the room) to choose a room to which they would like to connect to?

Scenario A:

If you answered "Yes" to question 1. or 2., you seriously need to consider if you really want to use WifiP2P. WifiP2P (Android's implementation of Wifi-Direct) does not really fit your needs. Using WifiP2P would probably mean that a room owner creates a WifiP2P-group and any person who wants to join the room must connect to this WifiP2p-group. The problem is Android does not allow for a single device to join multiple groups at the same time (which also means it does not allow to create multiple groups at the same time). Detecting changes in available WiFiP2P devices around is also problematic (when you are already connected to a device).

If you really want to use Wifi-Direct you would probably need to use one WiFiP2P-group and connect all devices to it. This group would act just like a regular network, and all game-room-related stuff would have to be managed by one node acting as a typical server (or maybe not a typical server but some other network solution).

If you don't really need WifiP2P use just a regular Wifi. Connect all devices to one network (maybe even start a hotspot on one of your devices), and whole connection process can be relatively simple, performed in background without user being directly involved in it. Human-readable room names are not a problem, since you can send anything from your server.

Scenario B:

If you answered "Yes" to question 3. and you really need to use WifiP2P, you will need to find some way to broadcast your "human-readable" names to other devices.

You probably think it's super easy: you connect to other device, tell the name of the room you've created, and you're done. Not that simple. As I said before:

obtaining a WifiP2P connection is inseperably linked with displaying a system window (asking if you really want to connect to a device)

So the whole process would be more-less:

  1. Device A: initiate connecting to Device B (this step can be performed by device B as well)

  2. Device B: ugly system window appears asking you if you want to connect to Android-ao12ij219sa (some PROGRAMMATICALLY UNCHANGEABLE system device name)

  3. Device B: accepting

  4. Device B: waiting for connection result

  5. Device B: connected, waiting for information about Device A's room name

  6. Device A: connected, sending room's name

  7. Device B: Device A's room name obtained, disconnecting (future connection request will also result in showing system window)

While steps 1-7 are being performed no other device can connect to Device A (so during that time no other device can obtain room's name).

What could be done:

  1. Use WifiP2P Service Discovery. It allows for broadcasting some information without the need to obtain a connection. Unfortunatelly it's even worse docummented than WifiP2P itself, and it might be even less reliable (subjectively). If you want to make a reliable solution based on that you will need to spend hours of testing and finding different cases in which it might not work. I know from experience that it's possible, but will require from you a number of workarounds to be implemented so it can always obtain a stable WiFiP2P connection.

  2. Send to your devices, a mapping between those (unchangeable) WifiP2P names and created room names, in some other way. For example through your server api or something...

Bartek Lipinski
  • 30,698
  • 10
  • 94
  • 132
  • Thank you very much for your reply! I have just one question left: you said that service discovery could be less reliable. What does it mean? It disconnects frequently? And what causes this problem? Hardware or software? Thank you! – Sergey Maslov Apr 22 '15 at 07:24
  • Maybe *reliable* wasn't the best word. What I meant was: usage of Service Discovery produces tons more of unusual device behaviour cases that you need to foresee to make sure that your application works properly. So that your game rooms always get detected, so that your clients always can connect to a room, and so on, and so on... – Bartek Lipinski Apr 22 '15 at 07:33
  • @BartoszLipinski in your answer you said that with WifiP2P Service Discovery I can broadcast some information without the need to obtain a connection, could you explain me how I can do that? I mean if I have a service on my device how can I broadcast that something changed? I would appreciate it very much, – zer0uno Oct 13 '15 at 07:26
  • @Bartek Lipinski you can use setDeviceName method of WiFiP2pManger that is annotated with `@hide` via reflection. I tried to use it to change devices name and it works perfectly. But still discovery process goes with some strange issues. For example, Device A continues to receive WIFI_P2P_PEERS_CHANGED_ACTION intent wich contains device B in peers list even if wifi on device B is turned off. – Niakros Mar 21 '16 at 11:11
  • @Niakros I always try to avoid using reflection. It can get really unreliable especially if you're messing around with some methods that developers (Google developers in this case) didn't want you to. If a method is not a part of a public api, it can be changed from build to build. And there won't be any information about it. – Bartek Lipinski Mar 21 '16 at 11:24
  • @Bartek Lipinski i'm absolutely agree, but tell me please. What are you doing with persistent wifi-direct groups on invited devices? Every moment when host device creates new group, and invites peers, new group is stored on invited devices after device is connected (which can be seen in wifi - direct setting in android wifi menu). Calling removeGroup on peer devices does not removes this group. Just diconnects from it. I'm currently using `@hide` deletePersistentGroup method to remove groups after disconnection. Shouldn't i do this? – Niakros Mar 21 '16 at 11:42
  • @Niakros, I don't think I was doing anything with them. I don't think they were an issue in my case. Sorry I can't really help you with an answer. – Bartek Lipinski Mar 21 '16 at 13:14
  • @BartekLipinski i'm sorry for being annoying, but couldn't you help me with one more issue? I implemented the discovering / broadcasting system like you described here: http://stackoverflow.com/a/31641302/3106249. And i have an issue: when host device invites a peer, the system dialog appears on peer device asking to accept connection (peer status become "INVITED" and doesn't change until wifi is rebooted), but it never appears on host. Do you have any thoughts about this issue? – Niakros Mar 22 '16 at 11:24
  • @Niakros what do you mean exactly by "it never appears on host"? – Bartek Lipinski Mar 25 '16 at 12:39
  • @BartekLipinski i mean that after i confirm connection on invited device, on host device nothing happens at all and no wifi_p2p ivent appears in my receiver, despite that the same connection acceptance dialog should appear. I'm waiting up to 60 seconds for event WIFI_P2P_CONNECTION_CHANGED_ACTION, which appears after both sides confirmed connection, may be i should wait longer ? – Niakros Mar 25 '16 at 13:06
  • @BartekLipinski didnt you never see before WifiP2pService: Invitation result INFORMATION_IS_CURRENTLY_UNAVAILABLE ? - this is what i see in logs when acceptance dialog doesn't appear on host device. – Niakros Mar 30 '16 at 13:01
  • @Niakros The problem is, it's been quite some time since I've been last working with `WifiP2p` (most of my posts about `WifiP2P` are from the first part of last year) and to be honest I just can't remember everything I encountered with it. Did you try reseting wifi before messing around with WifiP2p at all? – Bartek Lipinski Mar 30 '16 at 15:42
  • @BartekLipinski yes, i tried. And then the issue repeats – Niakros Mar 30 '16 at 16:05
  • @Niakros Then I don't think I will be of much help. Keep trying mate, and let me know if you manage to fix your issue. Good luck! – Bartek Lipinski Mar 30 '16 at 16:13
3

Basically, your design as I see it has very simple solution for the design with Wifi Direct.

Basically when creating "a room" that other can join, simply create a group, then do add local service to advertise the room.

note that you might need to start peer discovery, in order to be visible with your local service, at least my experience has been that, you do need to be active somehow, or you are not discoverable.

Then with clients, simply do service discovery and once you find the "room" simply connect to the it.

Then as the connections are initiated by the clients, the acceptance dialogs should be shown in Group owners side.

Dr.Jukka
  • 2,346
  • 2
  • 15
  • 20
  • Thank you so much! Could you please just make this clear: server CAN send data to all connected peers, right? – Sergey Maslov Apr 21 '15 at 08:38
  • Basically your "server" this time would be the Group owner of the Wifi Direct group. All clients would be connecting to the Group owner, thus the Group owner can communicate with them. – Dr.Jukka Apr 21 '15 at 08:55
  • 1
    Then again, the Group info, only has Group owner IP address, thus easiest way to start communication, would be to start it from the client. – Dr.Jukka Apr 21 '15 at 08:56