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

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)

Related

How can I speed up Nearby Connections API discovery?

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.

Android SPP Bluetooth: Implement a Background connection attempt

I would like to minimize the need for user involvement in working with SPP medical devices. The user should only have to pair the device and then connections happen automatically when the device becomes connectable. HDP classic devices are like this and so are BTLE devices (the latter takes work on Android).
So the obvious solution is after pairing, create the RFCOMM Socket and invoke the connect() method (and perhaps all the workarounds to handle the various bugs).
However, this blocking method times out after 12 or so seconds according to the documentation so if I really want to continuously be ready for the device when it 'comes on-line', I need to do this in a while-loop until the connection succeeds.
So the question is if I do this, will this continuous 'pinging' for the device overload the system and drain the battery? Given that something like this happens for HDP implementations on Android, they must also do something like this but maybe they reduce the frequency of pinging so it isn't so resource demanding.
Does anyone have any experience with attempting to do continuous monitoring for SPP devices? Thanks!
I have used Bluetooth SPP connection for industrial devices and had a similar problem. It does not seem a good idea to have a service trying to connect all the time, as it will need to always run on the background and drain more battery.
My solution would be if possible to have the SPP medical device to ask for connection once powered to the paired device(your android), or when you try to connect to the medical device, automate the connection procedure which should take about 1-2 seconds (if you can filter the devices by their MAC address(preferably) or name in your app)
Based on the bluetooth chip in your medical device, you should have plenty of connectivity options from this end, but if not you can try to connect on demand.

Android: Auto-reconnect BLE devices

My goal is to get the Android device to reconnect to a BLE device that it has previously connected to without user intervention in the same way it does for a classic BT paired device does (even works through power cycles).
One of the ideas of BTLE devices is that one saves service, bonding, and enabling states such that a reconnect is VERY fast and consumes very little power on the peripheral.
What I have done seems to work but it works poorly.
The first step is to connect or pair and connect to a new device setting the 'autoconnect' parameter to 'true'.
When the device disconnects, do not call gatt.close(). Everywhere I look I see that one should call gatt.close(). But if I do call gatt.close() the Android central app never reconnects. I have tested this many times.
If I have not called gatt.close() and have not power cycled the Android, the auto-connection usually happens. Sometimes it can take a long time, especially after version 5.0. It is, however, unreliable and it may be unreliable due to a very low-duty scan cycle and the device quitting advertising before a scan cycle actually detects the advertisement. I am not sure because there is no way to detect the scanning operation like there is advertisements! It is also possible the scanning stops after a certain amount of time but there is no documentation on that.
So what I think I need to do is to somehow set the background scan rate used by the Android to a higher duty cycle (only possible in 5.0 and up) when auto-connect has been set but I do not know how to do this. I do not want to start my own scan but somehow set the background scanning rate used by Android for the reconnect. Does anyone know how to do this? Does anyone really know how autoconnect and gatt.close() are to work?
Maybe the auto-connect was NOT meant to re-connect as I indicated above?
Well after many trials and tribulations this is how I best get the Android to auto connect with the only user action being to first select the device (if using the settings menu then first pairing).
You have to trap the paired event in a BroadcastReceiver and do a BluetoothDevice.connectGatt() setting the autoconnect to true. Then when the device disconnects, invoke a gatt.connect().
Update: While the above approach works in general, it is sometimes agonizingly slow probably because the pending connection uses extremely conservative scan rates. The other downside is that for each device you want to auto-reconnect to you have to keep a BluetoothGatt object performing a pending connection. In the embedded world this is insane. Instead what one does is continuously scan and connect to a desired device by inspecting its advertisement. One saves only the minimal amount of data about the device (the services, its paired state and keys, etc.). When an advertisement is captured you see if it is one of your known devices and connect to if it is.
I tried the equivalent on Android. Scan all the time (low power rate) and connect to advertisements of interest, and maintain a class representing a known device. There are some annoying details in this approach (like turning off scanning while connecting and restarting after connected) but it basically works without the overhead of maintaining connections. BUT there is one exception I do not understand. One pre-paired device's advertisements are never seen by the scanner. However, if I invoke a pending connection to this device, I re-connect. I do not understand this at all. On my embedded platforms it works as it should.
If anyone else has tried this approach for auto-reconnecting, please share your experiences!
I have discovered the reason the pre-paired device is not seen by Android. Android only reports scan results IF the device responds to a scan request. Once paired, this device only emits advertisements and ignores scan requests, so the Android system does not pass up its advertisements in the ScanCallback. Thus in order to work using the scan approach, I have to use the pending connect approach for those specific devices. It just seems like you can't win!
============= UPDATE 2020
Many years have passed and I have a lot more experience with the background scan approach. If one keeps the supported platforms 5 and up, one can use only the newest scanner APIs and use filters, eliminating the need to decode the raw advertisements yourself. I have also found that connection and re-connection is snappier if you DONT turn off scanning while connecting. I know it goes against all documentation, but it works and on some platforms allowed connections to happen that otherwise did not. Also, to date, I have found only one (health) device that needs pending connects. Disclaimer: All I have ever worked with is health devices.
This is how I was able to do it for my application.
I first stored the address of the device in a SharedPreference then in gattClientCallback funtion of my BluetoothLeService
else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
intentAction = ACTION_DISCONNECTED;
DeviceActivity.runOnUI(() -> {
sharedPreferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
String name_dev_1 = sharedPreferences.getString("Dev_1", null) ;
connectToDevice(name_dev_1);
disconnectGattServer();
});
}
}
What this does is if your device is disconnected it will keep on trying to connect to it until a connection is established.

Android. connect bluetooth devices

I'm attempting to write an app that involves connecting two android devices via bluetooth.
It is my understanding that one device acts as a server, listening for incoming connections while the other acts as the client, and initializes the connection using the server's MAC address.
Consider the following:
I have my android phone in my pocket, I start working on my android tablet. I want to connect the tablet to the phone (via bluetooth) without taking the phone out of my pocket (I do not want to pull out the phone and manually start listening for incoming connections).
What would be a good way to achieve this? It seems like I would have to make the phone the server, constantly listening for connections 24/7. However, my gut says this will violently drain the battery.
Any suggestions?
You are right, you could make your phone (or your tablet) the server. But it ought not use that much battery; once you set up a server socket and start accepting connections the code simple blocks and waits for an incoming connection. In my experience I haven't found this to be too much of a battery drain (but I have no hard figures to back that up).
If there is a UI involved with the server you'll want to split out the server socket into a separate thread so as to not block UI events.
Typically phones behave this way - i.e wait for incoming connections from paired devices. Waiting / Scanning for incoming connections is less power hungry than trying to find or connect to devices in a poll mode. Many bluetooth chips have low power scan which implements power efficient scanning.

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