Android- wifiDirect - android

I am developing a simple wifiDirect chat app.My app does peer searching and once peer's list is available one can select a particular device, the one to connect with. Then my code calls connect() which sends a notification to the other device (2nd phone) about connection (default). Once the second phone agrees to the connection then 1st phone becomes group owner while second phone running my app does nothing.
So my question is do I need to call connect() on both devices? Also when is this intent action WIFI_P2P_THIS_DEVICE_CHANGED_ACTION broadcast?
Need help, read android.developers.com and other official sites but couldn't figure out.

No, you only need to call connect() on one device. Note that this does not mean that the device that calls connect() will be the group owner. The system will decide the group owner itself. You can only suggest your preference through config.groupOwnerIntent = x; where x is from 0 to 15, 0 representing least intention to become owner while 15 represents the highest.
WIFI_P2P_THIS_DEVICE_CHANGED_ACTION event will be fired when the status of the device has changed.
Use the following code to fetch the updated details of the device.
(WifiP2pDevice)intent.getParcelableExtra(WifiP2pManager.EXTRA_WIFI_P2P_DEVICE));

Related

Which method is called when someone tries to connect using WifiP2PManager.connect(Channel, WifiP2pConfig,ActionListener)?

I am tring to setup WIFI P2P on 2 devices using
manager.addLocalService(channel, service, ActionListener)
and then connect both devices using
manager.connect(channel, config, ActionListener).
I would like to know which method is called before the popup to accept/reject connection is shown on the target device. All I was able to find was onConnectionInfoAvailable(WifiP2pInfo p2pInfo), but it is called after the connection is established.
I basically want to receive the "instance name" of the device trying to connect to me using WIFI P2P and then reject the connection request without showing system dialog(that allows the user to accept/reject connection).
I can't anything that can help me do this on docs or any other place. If anyone knows how to do it or can point me in the right direction then please let me know.
I solved it. I can put the instancename and devicename (of device I want to connect to) in Map that is passed when setting up service. From other device I can retrieve map of all devices available using this and find the instancename of one I need.

How to find Wifip2p groups in android

I'm trying to use WiFi-Direct for connecting multiple devices over wifi in a master-slave style (one to many)- one client creates a group using the "createGroup" function, and all the other clients should connect to the group (manually).
when a client press on a "Discover peers" button, i want to give him a list of all the master peers.
And here is the problem- I can't find a way to differentiate between slave peers and the master peer (the one who initiate the createGroup request).
is there any way to filter out all the slave peers and keep only the master peers?
You should be discovering services rather than peers, though the API does work better if you also do peer discovery, thus here's my proposal for your logic:
With slave:
Start peerDiscovery
When you get Peers changed event, start service discovery (for service_type defined by your master)
Add the discovered services into a selection list as they come (note that they come one by one, and I've seen max 5 seconds between discovered services)
With Master
createGroup
Add local service to advertise that you are the master
Start Peer discovery, and make sure by monitoring the Discovery state changes that it stays on (if it goes off, your service advertisement likely will not be seen by the slaves)
A simple way to achieve this is to do the following: You can set which device to be Group Owner (Master device) by setting the groupOwnerIntent to 15.
WifiP2pConfig config = new WifiP2pConfig();
config.groupOwnerIntent = 15; //Value between 0-15
You also need to change the master's device name to something like "Master"+itsCurrentName. (To change the WiFi Direct device name, check my answer on how to set interface device name of wifi direct)
Now, whenever a new device scans for peers, the results will show which devices are GroupOwners from their name that starts with the word "Master".
This is a simple way to filter out master from slave peers.

How to start a method in the same time on 2 devices

I have 2 android phones phones, both connected to the same wifi, both with bluetooth.
I want some method that syncs somehow the phones and starts a function on the same time on both phones.
For example playing a song at the same time.
I already tried with bluetooth but its with lag, sometimes 0.5 secs. I want something in +- 0.01sec if possible.
Someone suggesting playing it in the future with 2-3 seconds, sending the time-stamp, but how do you sync the internal clocks of the devices then ?
Before calling that particular method, try to measure the latency between the two devices:
1.First device says Hi(store the current time)
2.Second device receives the Hi.
3.Second device says back Hi !!
4.First device receives the Hi.((storedTime - currentTime) / 2 )
Now you have the latency, send your request to second device to start your particular method and start it on first one after the latency.
Try to measure the latency 5 to 10 times to be more accurate.
you have a way to transfer data between the devices right ?
if so you can send a time-stamp which is in the future,
ex: if the present time stamp is 1421242326 you send 1421242329 or something and start the function at that time on both devices.
Basically use #Dula's suggestion (device 1 sends command to device 2 and gives a "start time" which lies in the future). Both devices then start the action at the same time (in the future).
To make sure that the devices are synchronized, you can use a server-based time sync (assuming that both devices have Internet access). To do this, each device contacts the same server (using NTP, or HTTP-based NTP, or contacts a known HTTP server, like www.google.com and uses the value in the "Date" header of the HTTP response). The "server-date" is compared to the system clock on the device, and the difference is the "time-offset from server-time". The time-offsets can be used to synchronize on the "server-time", which is then used as the time base for the actual action (playing the media, etc.).
If your WiFi router allows clients to talk to each other (many public hotspots disable this), you could implement a simple socket listener on one (or each) device and have the initiating device broadcast a message.
For more complicated things and network flexibility, I've had good success with connected sessions using AllJoin. There is a bit of a learning curve to do interesting things, but the simple stuff is pretty easy once you understand the architecture.
Use a server to provide a synchronous event to just the two clients who have decclared their mutual affinity (random as a parm and pair serializer Partner-1 or Partner-2 which they share prior to their respectve calls for the sync event).
Assume both clients on same subnet (packets from 2 events serialized on the server , arrive across the network at the 2 clients simultaneously client-side) This provides synchronous PLays by 2 , bound clients.
The event delivered by server is either a confirm to play queued selected track OR a broadcast( decoupled, more formal)
The only tricky thing is the server side algorythm implementing this:
Queue a pair of requests or error
Part1, part2 with same Random value constitute valid pair if both received before either times out.
On a valid pair schedule both to the same future event in their respective , committed responses.
OnSchedule do the actual IO for 2 paired requests. Respective packets will arrive back at respective clients at same time, each response having been subject to equal network latency
Ng if two diff carrier 4G or lte networks involved. (Oops)
This thing is possible via socket, you will send a event via socket then the other device receive that event. For learn socket io chat
maybe it's not the answer you are looking for but i think that due to the high precision you are wanting , you should look for a push technology, i advice you to take look at SignalR. It's real time technology which gives you abstraction of sending methods , it have a built-in methods like Clients.All.Broadcast that fit your needs.
You can try to use some MQTT framework to send message between two device, or into a set with more number of devices.

How to setup Wi-Fi Direct with PIN on Android

I want to require entering a PIN when connecting two Android devices to ensure they are talking to each other.
There is a sample project in the Android SDK 17 called "WiFiDirectDemo". It establishes a Wi-Fi Direct connection but it lacks the PIN authentication.
I don't know how to specify WiFiP2pConfig.wps.setup in the class DeviceDetailFragment around line 71. Do I specify the action on the current device (I want to show a auto-generated four-digit PIN), i. e. config.wps.setup = WPSInfo.DISPLAY, or should I specify the action on the peer, i. e. config.wps.setup = WPSInfo.KEYPAD?
How can I detect the connection request on the other peer? I guess there is something I can listen to, e. g. in the BroadcastReceiver, but I cannot find it.
I'm an experienced iOS developer but Android is very new to me, maybe the the answer is obvious to you. Thanks for your help.
you need to specify the action on the device which sends the connect request ... and for pin i think this should work
p2pconfig.wps.setup = WpsInfo.DISPLAY;
p2pconfig.wps.pin = "0000";
On connect, PIN is displayed on local device and requests user to enter same PIN on remote device; once PIN is entered, connect completes successfully.
Check this https://groups.google.com/forum/#!topic/android-platform/hN5WfXRzXpI read the 5th post
p2pconfig.wps.setup=WpsInfo.KEYPAD(don't specify p2pconfig.wps.pin) works fine for me.It displays a dynamically generated key on the device from which we are trying to connect to be entered on the other device.
In this case you don't need to listen on any b'cast receiver to detect the connection.The wpa_supplicant takes care of it and prompts you to enter the pin.For a clear picture, look at the logcat(I use adb from ADT(sdk+eclipse) to see the logcat) of wpa_supplicant while connection is in progress.

How can I avoid or dismiss Android's Bluetooth pairing notification when I am doing programmatic pairing?

I have an app where I am programmatically controlling Bluetooth pairing and unpairing. I can pair before connection and unpair afterwards. The reason I need to do this is specific to my application and not in the scope of my question.
Basically what I am doing is:
Get a reference ib to IBluetooth object as described in this answer
Register a BroadcastReceiver for android.bluetooth.device.action.PAIRING_REQUEST
Call ib.createBond(address)
Wait for BroadcastReceiver to trigger
Convert user pin into bytes with convertPinToBytes()
Call ib.setPin(address, pinBytes) from within BroadcastReceiver
Anyways, this approach works great, except for the fact that when I do the pairing, I get a notification in the Status bar requesting that the user enter a PIN to complete the pairing. But this is in fact unnecessary, because by the time the user sees this, my app has already used setPin(). I'd really like for that notification to either a) not appear at all, or b) be dismissed automatically somehow.
I realize this may not even be possible, but I thought I would ask in case someone has a creative idea.
Try setting the confirmation first in the PAIRING_REQUEST
BluetoothDevice device = intent.getParcelableExtra("android.bluetooth.device.extra.DEVICE");
device.getClass().getMethod("setPairingConfirmation", boolean.class).invoke(device, true);
device.getClass().getMethod("cancelPairingUserInput").invoke(device);
This worked for me between two Android devices using RFCOMM but I'm not entering any PINs
Since Android API 19 Google switched these Methods to public Methods, so there is no need for Reflection any more. :)
Do this in the PAIRING_REQUEST notification event:
BluetoothDevice localBluetoothDevice = (BluetoothDevice)intent.getParcelableExtra("android.bluetooth.device.extra.DEVICE");
Class localClass = localBluetoothDevice.getClass();
Class[] arrayOfClass = new Class[0];
localClass.getMethod("cancelPairingUserInput", arrayOfClass).invoke(paramBluetoothDevice, null)).booleanValue();
But you gotta tell me how did you pair your remote device without the user to enter Passkey/PIN? off course, you know the PIN for the remote device which is trying to pair to your device but how did you provide that PIN to the remote device.

Categories

Resources