How can I speed up Nearby Connections API discovery? - android

I am attempting to connect two Android devices close-range without a 3rd party service to transfer two small json payloads back and forth before closing the connection. Think adding nearby contacts.
I am using the P2P_POINT_TO_POINT Strategy and have both devices advertising and discovering using the code found here: https://developers.google.com/nearby/connections/android/get-started. It consistently works, however it repeatedly takes 10-15 seconds to find the connection and prompt to accept the connection.
Ideally I could get this below 10 seconds.
I read that having one dedicated to advertising another dedicated to discovering helps but it does not work for my use case.
Is there a way to improve the connection rate?

Unfortunately, the best you can do is to try to connect in one direction. That should lower the connection latency to 2~7 seconds. When both devices connect to each other at the same time, that causes thrashing and while we do our best to handle it gracefully, it will cause increased latency.
Stopping discovery before calling request connection would help too, but not by much. We already do it internally during the most sensitive operations.
Our advertising and discovery stack is based off of Bluetooth, and we've experimented with other technologies to compliment it. But they typically have harsher limitations than Bluetooth does (needs a router, needs a very recent Android phone, can't handle simultaneous connections, can't advertise and discover at the same time). Of all the technologies I know of, only mDNS would be faster while still allowing bi-directional connection attempts, and that requires both phones to be connected to the same router (and that the router hasn't disabled mDNS). Typically this means it only works at home. If that's a reasonable limitation for you, then I can pass that on to the team.

Related

Android NearBy API terribly slow (~10+ seconds for discovery and connection)

I'm trying to setup a communication channel between two Android phones.
Unfortunately, Google decided to block developer access to Bluetooth adapter MAC address, effectively disabling the entire NFC to Bluetooth handover process (Simple Secure Pairing).
Side note: why? privacy/security gain is minimal to none, especially
if you randomize it! you could simply randomize it when an app requests the MAC and that's it!
This SSP process used to take roughly 1-3 seconds at max and generated great user experience.
Currently, I'm stuck with NearBy which generates a terrible user experience (who's gonna wait 10 seconds just for the initial connection?)
The only options we have left:
Improving NearBy API somehow (~10 seconds average to discover and connect! why Google, why?)
WiFi hotspot - setting an agreed-upon ID as the name, discovering and connecting (~8 seconds average)
Bluetooth - requires a popup to be approved each time, a bit faster but results in bad UX.
Internet - just use the Internet and fall back to local wireless methods (when 4G internet connects much faster than local wireless Android NearBy, you know Google has definitely failed with the implementation).
Is there some secret sauce I can pour onto NearBy to improve it, to be, at least as fast as Apple AirDrop (~4 seconds average)?
Do I have any other options I'm missing?
Thanks!
The definition of absurdity:
Two phones that are 1 meter away from each other with several direct wireless options (Bluetooth/BLE/WiFi) take an average of 10 full seconds just to connect (before data is sent).
Two phones that are 20km away from each other, communicating over cellular data (3G/4G/5G) fully connect after an average of 1.7 seconds! Even after traveling through GSM BTS, proxies, cache, firewalls, BGP routing and other filters.
Google has to do something to fix that (after they disabled the only method to make this faster, using BT SSP, handing over NFC to BT - as they disabled BT MAC address exposure).
My solution right now is to use Internet by default while simultaneously trying to connect via NearBy, as I need a fallback ready to work for some of my clients that don't have a good cellular signal.

Android Nearby Connections - How to prevent overlap with connections and discovery

I am using the Nearby Connections API. From what I've read, one should not be discovering while simultaneously being connected to a device because this reduces bandwith and causes possible dropped connections.
However, I am building an application where each phone tries to relay any message it receives to as many other phones as possible. As such, it is best to always be discovering in order to maximizing the number of endpoints.
What is the best method for ensuring that discovery time does not overlap with actual connection time? Should I be entering discovery mode on a regular preset interval? Is there a way to store discovered devices for later (so I can connect to them after I have discovering all local devices)?
You can connect to discovered devices even after calling stopDiscovery, so one solution is to scan for a fixed duration, and then connect to the devices that were found. (Note: If you're trying to do something in the background, try to synchronize the devices by advertising on the start of the hour since discovery can drain a lot of battery.)
Alternatively, you can try to keep the devices continuously connected to each other, by forming 2~3 connections per device, and flooding the network by updating all of your connected peers, who then do the same, until everyone sees the message. (Note: Being connected drains battery, although not as much as discovery does)

Is there a way to communicate reliably via Bluetooth?

I have to exchange data between two bluetooth devices, one of them will be an Android device. For simplicity's sake you can assume the other device will be a generic linux device running bluez producing data similar to the data a fitness tracker would produce.
The scenario seems a straightforward use case for Bluetooth Low Energy. The problem i am currently running into comes from the fact that communication has to be reliable (reliable in the way TCP is reliable). This means:
no losses
no corruption of data
order needs to be preserved
no duplicates
no phantom packets
While losses are prevented at link layer level, the order for instance seems not to be explicitly preserved when working with Low Energy (using indications would probably achieve this).
Not having done a lot of work with Bluetooth I am currently overwhelmed quite a bit with the amount of options while at the same time no option seems to fit the bill nicely.
Is there a "best-practice" for setting up reliable communication between two bluetooth devices? A Bluetooth Low Energy solution would be preferable, but is not mandatory.
Once your Bluetooth connection is setup its reliable. So you don't have to be worried about data loss or corruption.
So the things you're worried about can be easily handled in your side. You'll get proper connection and disconnection callback while setting up a BroadcastReceiver for your BluetoothAdapter.
In case of any disconnection you may have to restart the procedure for connection again and once its established properly you may resend the data.
I don't know about your purpose yet, but one thing I need to mention here is, I would not recommend Bluetooth communication if you're holding the connection for long time. Some devices disconnects the connection automatically after some time if there's no continuos transmission.
Android has Bluetooth support, but it only allow to send ot receive data from stream. There is a very good sample project from Google: https://github.com/googlesamples/android-BluetoothChat . The only drawback of this sample is that it use Handler to nitify about Bluetooth events. I changed it a bit so it use another Thread and from it calls methods of interface you set, take a look at project: https://github.com/AlexShutov/LEDLights . This is ordinary Bluetooth, not BLE, hope it will help
Android's BLE stack is as good as the link layer specification. So you can use "write without response" in one direction and notifications for the other direction. Just make sure your peripheral side does not drop incoming writes.
BLE uses 24-bit CRC. for the amount of data transmitted using BLE the CRC is quite robust and the possibility of corruption is very low ( note that TCP CRC is 16bit and the Ethernet CRC is 32bit, please see http://www.evanjones.ca/tcp-and-ethernet-checksums-fail.html).
The ordering issues in wired network is a result of routing packets through different routes to the same destination ( plese see If TCP is connection oriented why do packets follow different paths?) . This is partially due to the use of sliding window acknowledgement protocol, which allows a number of packets to be transmitted before being acknowledged.In BLE there is no routing and the acknowledgement scheme is a variation of stop and wait ARQ scheme(2-bit lazy acknowledgement), this means that it is not possible to send a new packet without being acknowledged. These two factors makes the possibility of having an out of order transmission highly unlikely.

Android Bluetooth Chat sample app - multiple connections

Is it possible to set up the Android Bluetooth Chat sample app to connect more than one person at a time, and have a mini chat room? What would that entail?
tl;dr version: Bluetooth sucks for this, don't use it, use wifi instead, probably backed by a web backend.
I have investigated this issue thoroughly throughout the years in the interests of a social wireless network research project. My general advice is: it doesn't work with more than two / three people. Bluetooth just isn't designed with wireless peer to peer networks in mind.
In general, it seems that the cheap Bluetooth controllers included on Android devices (especially HTC's devices, iirc) don't really handle any more than two or three connections at a time. I'm unsure if this is a hardware or firmware problem, but I can recount some basic anecdotes. I was working to implement this idea at the SDK level (i.e., without firmware modifications) around the beginning of 2011, and was able to get a peer to get two additional connections (i.e., three devices, each connecting to the other two) to work for a period of a few minutes to an hour before the connections would suddenly die and the socket would become unusable, requiring reconnection. Unfortunately, 20 minutes was an upper bound, and generally it was impossible to get connections to more than one other device at all reliably.
The goal of the project was to support multiple people interacting with each other silently in the background, but this never materialized, instead we ditched Bluetooth and went with wifi instead, which worked much much better. In the abstract, I think people view Bluetooth as a possible medium for reliable peer to peer communication, but it wasn't really designed that way: it's more of a medium used for short range communication between small devices (think headsets).
Be aware that if you want to do this, the maximum number of devices to which you can connect is fixed, because as per the Bluetooth spec, a piconet supports a maximum of seven devices. (See the wikipedia article.)
The required change is simple: you use a different UUID for each device. This can be implemented a number of ways, using an out of band exchange mechanism, or simple scheme where you assign UUIDs in an increasing fashion and when connecting to the network, try each in succession.
Here are some relevant Google groups threads:
Bluetooth peer to peer networks
Multiple connections on Android Bluetooth
I remember posting a more elaborate one detailing how to do this (with code) that I might dig up as well.., if I can find it. It should be from late 2010 or early 2011.
So the answer is, in the abstract, yes, you can try to do this, by using multiple UUIDs (after you use one, that's it, and you have to try another using some assignment protocol). However, in practice, after a lot of trial and error, this doesn't really work for what you probably want to use it for, and it's a lot better to go with an internet backend instead. By the way, this is also good for another reason, most users don't really like to turn on their Bluetooth for fear of their battery being drained..
Leaving this here, in case it helps someone else.
I was able to make my custom chat room following official bluetooth tutorial and modifying it a little.
Unfortunately, I cannot provide most of my code, but main idea is:
Every device is acts both as server and as a client. When Chat is started, device starts its server thread. Server thread is the same as official but doesn't ends when accept connection. It just keep listening.
Client thread is identical as in tutorial.
Both server and client thread manages connection same. I created separated threads for accepting messages following this tutorial and one for sending them.
private void manageConnectedSocket(BluetoothSocket socket) {
//create thread responsible for sending messages.
SendingThread w = new SendingThread(socket);
MainActivity.addSendingThread(w);
//Creates listener for messages to accept.
MainActivity.addListener(socket);
}
Now in main activity always when user click send button, for each worker (sending thread) send message to remote device. Listening is running asynchronously.
IMPORTANT:
You need to handle exceptions when message send fails and remove sending and recieving thread for device when you detect it is disconected. In my case I used well known UUID "00001101-0000-1000-8000-00805f9b34fb". For every device.
You need to wait 3 second between atempts to connect as client because some devices has weak bluetooth hardware and it is refusing connect as client.
Bt connection is supporting up to 7 -10 connections. So you will be limited in that range. I think it is designed for extensions of main device and not for random comunication
Source: search "bluetooth programming" on google

Do Android devices scan *actively* for WiFi networks?

i am programming for google android and i wonder if the scans for wireless 802.11 networks are done passively or actively? i mean: does the device actually emit a beacon request signal on WifiManager.startScan() or does it just listen for beacons sent periodically by the access points?
Android does passive scans, it listens for beacons. Doing an active scan can create a lot of congestion on the network by sending out probe requests and waiting for probe responses.
Even though this question is 11 years old, it still has relevance today and so I thought I'd give it an up-to-date answer:
Yes, Android devices do search for APs actively. Passive scanning requires for the device to listen for beacons for a longer time, which is energy consuming see this paper by Freudiger for more details
Active scanning only requires sending probe requests and then waiting for the reply on the corresponding channels. This takes less energy as it requires for the radio to be turned on for a much shorter time span. Unfortunately, active scans require for the device to identify itself somehow, and this makes it easily trackable. Mitigations in place are e.g. MAC address randomisation with every burst, randomised MACs during connection with an AP, randomised Sequence Numbers, omission of unnecessary fields and more. It all doesn't seem to be enough as people still find way to optimise their algorithms to improve tracking via Probe Requests. ;-)
Rain Ma replied that Probe Requests contain SSIDs, this is technically not true for all devices anymore. The only reason for SSIDs in Probe Requests is to find hidden networks. In Android devices, newer OS versions don't transmit SSIDs at all anymore, save for when scanning for hidden networks. Up until Android 8, all manually added networks were automatically assumed to be hidden networks. Starting with Android 9, one has to explicitly mark a network to be "hidden" for the device to probe with SSID.
iOS does automatic detection of hidden networks, and they say they don't probe with SSID at all unless they detect a network to be hidden.
The answer is YES
Actually, using omnipeek to capture packages from Android/iOS devices, we can get the result below:
Most Android devices always try to send Probe Request Frame every few minutes. They keep a list of SSID you used to connect, and always try to send probe request frame with SSID to see if they are available now. I guess one of the reason is 802.11 pre-authencation , and some other reason may be: enhance the wifi list display speed.
They are working in a active.
iOS devices seldom do active scan
If you wanna konw more about the rules, you'd better read "802.11 Wireless Networks The Guide"
You can refer to the pciture : Packages captured by omnipeek

Categories

Resources