I am evaluating Google Nearby connections2.0 more specifically evaluating the synergy effect of it. For this I am evaluating it against Wifi, Bluetooth and BLE in totally offline scenario, without any router.
Scenario
One device is advertising, all others (8 devices in total) are discovering. On successful connection, I am sending simple Files of 20B, 200B and 33KB sizes for 30 secs straight to each connected device.
I am using android Samsung S6 SM-G920F devices with android version: 6.0.1 and playservices version 12.8.74
I have following issues/questions
Q1: First of all at max 3 to 4 devices could be connected simulatenously more than this results into disconnect event of other devices. Even if only 3 devices are connected, and I am continuously sending message for 30seconds, one of them disconnected ? In simpler words, cannot sustain connectivity with any device for more than 45 secs. usually disconnection occur between 25 - 45 secs
Q2: I cannot send message/file continuously for 30 seconds like we can do with the Wifi like this
While(30sec){
bluetoothSocket.outputStream.write(bytes)
}
Because if I try to do this then I got the exception of too much work.I have to wait for the the callback in onTransferPayLoadUpdate()
Q3: If I try to send the file of 1MB or more to other peers, peer received the file successfully in onPayloadReceived callback but server/sender receive the successful status after too much delay. In my case it's between 1 mins to 5 mins after client callback. And I cannot send new file until I got the success callback on server. If I try to send it before getting the callback, nothing happens. Literally nothing. So In essence I can only send file of 1MB once then I have to resent both the devices to send another file.
This should be broken up into 3 separate questions. It helps future developers search easier. So if you get the time to do that, let me know and I'll split up my answer as well. But anyway, let's get into it!
A1: Nearby Connections has 3 separate strategies. The more limited the strategy, the more types of mediums we can use. So with that in mind, and with no router involved, P2P_CLUSTER will only use Bluetooth. It's the most general strategy, so it has the fewest mediums available.
All Android devices use mobile Bluetooth chips, which are unfortunately weak (but small and power sensitive), and that causes them to have a theoretical 7 device limit but a practical 3~4 device limit. To make things worst, that limit is eaten up by smart watches and paired headphones as well. That's why you're running into problems.
P2P_STAR and P2P_POINT_TO_POINT are both much more limited, because you can't connect in any direction. You need to choose who the host is beforehand and have everyone scan for and connect to that host. But you get the added benefit of WiFi hotspots, which have higher bandwidth and a larger number of simultaneous devices supported. I've seen 7 devices happily connected to a Lollipop device.
If you want to go beyond that, into the 10s and 100s, and a router isn't available, you'll have to build a mesh network. I can link you to examples of how to do that if you're interested. We don't offer support for that within Connections, but others have built meshes on top of us so we can point you in the right direction.
A2: Can you include a stack trace of the error you're seeing? Payload.Type.STREAM was built for continuously sending data. The other payload types should also work too, baring some rare but potential issues like BYTE payloads filling up the phones RAM.
A3: Both devices need to wait for onPayloadTransferUpdate(SUCCESS). onPayloadReceived is only a header, and means that there's an incoming file or stream but that the data hasn't been received yet. For byte payloads, we actually send the full byte payload inside the header so that's the only time data is immediately available.
Related
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.
I'm developing an offline photo transfer app using Nearby Connections 2.0. Advertising, discovery, sending byte payloads, Google sample apps(RockPaperScissors and WalkieTalkie) all work fine but I have 2 issues.
First and most importantly, after successful connection initation between devices, I send a byte payload to give 'take picture' command from advertiser device, the discoverer receives the payload and takes a photo, then sends that photo to the advertiser as a file payload. The problem occurs here, as the devices often disconnect when the discoverer sends the file payload, before even the advertiser's onPayloadReceived method is called. I tried reducing the size of the photos, to as low as 30kB's, that rarely solves the problem. When I switch devices, making the old advertiser the new discoverer and the old discoverer the new advertiser, the problem doesn't occur often, even without reducing the size of the payload (payloads around 30kb almost never give me this issue with devices being switched). The only log I get from Nearby is this:
.
First line is logged when the connection initiates, second line is logged when the devices disconnect.
Secondly, the discovery and connection initation sometimes take up to minutes, but rarely exceed 30 seconds.When they do, I get this error on log:
Both devices run on Android 6.0.1, and are on the same network. I use star strategy. The problematic device is Lenovo P1A41, other device is Lg X-screen(K500).
Could you try and run our sample apps on these devices to see whether they work as expected? We regularly transfer 10s of MB of data on Nearby Connections, so I'd like to rule out any hardware issues on the phones you're using.
BTW, which phones are you using (and which one of these is the more problematic of the 2)?
P.S. Being on the same network isn't need in Nearby Connections -- we're completely offline and P2P.
I'm having trouble maintaining a Bluetooth connection (from Android to a device I'm developing) for longer than a few minutes.
The scenario is:
Device is paired successfully.
Device transmits to Android for somewhere between 1-7 minutes (varies by device or possibly Android version).
Android stops receiving bytes although device is still transmitting.
So: why does Android BT stop receiving?
This is very similar to the issue/observation described in bboydflo's answer to this question:
Application using bluetooth SPP profile not working after update from Android 4.2 to Android 4.3
Some more background:
The BT device I'm working with continually emits measurement packets containing ~200 characters, once per second. I am certain that the device-side is still transmitting when the issue occurs.
This sympom happens in my app on two Android devices: an Android 5.0.1 Acer tablet, and an Android 7.1.1 Moto Play X
I've tested with an app called Serial Bluetooth Terminal. This app does not experience the same issue; the connection is stable for as long as I've tested. Therefore, this issue is probably caused by something in my application code.
I've seen various responses to Android BT questions directing the user to use asynchronous streams rather than polling for received bytes. This seems to be a red herring; if you feel that the threading model is causing a probelm in this case, please clearly describe why switching to async would resolve this issue.
I would like to pre-emptively address reasons that this question may be closed:
This is not a duplicate. There are other questions on SO about BT connections dropping (i.e. Real-time Bluetooth SPP data streaming on Android only works for 5 seconds) but this is not the same issue. I have already added a keep-alive outgoing char transmitted every 1s, and my issue remains.
I'm not asking about an issue specific to my application; at least one other user on SO has encountered this problem.
I've reviewed the Android Bluetooth documentation in detail, and I can't see any obvious reason for this to happen.
I'm not asking for an opinion; I'm asking for an objective answer as to why the bytes stop being received.
Ok, I have a partial answer for this one. First, a bit more background:
I was running the BT stream polling on a thread which executed a runnable every 2s
The buffer being used to read the stream was 1024 elements long
I had a suspicious that this might be some background buffer running out of space. So, I changed the 2s to 500ms and the 1024-length to 10024. Now, I've had about 20 minutes of connectivity without any trouble (and still going).
It would be nice to find the smoking gun for this. I initially thought that stream.Available() would be sufficient to tell if a buffer was getting filled up, but in this scenario, stream.Available() is actually returning 0 when the Android device stops receiving. So I'm not really sure which queue to check to prove that this issue is related to a buffer becoming filled.
I'm currentily developing an application which uses Bluetooth Low Energy to communicate with a BLE device. The problem is that the project require an high continuous exchange of data for working.
Currently i've developed 4 fragments which share the same BluetoothGatt istance and the same data array. When i connect to the BLE device, i set the connection priority to high, then i start a writing loop which writes the data, usually just 4 bytes, every 50 mls.
At the same time i start reading and i update my interface.
I've noticed that if i stop the writing i receive a packet of data every 50 mls, but if i let the writing loop working the reading time increase from 50mls to 100 or more.
That's not a real big problem but it reduce all the sistem performances.
I looked on the internet for solutions but i didn't find nothing, except the connection priority that already helped me a lot, i'd like to know if someone have never managed such problems and how he did it. thanks
BLE Device that you are using has something which is called "connection interval". It is set in firmware of device. Minimal value for it is 7.5ms, but usually is set to 30ms or more (iOS even will not work with intervals lower than 20-30ms or it will simply miss the packets).
So when BLE device firmware is designed, connection interval is set to some value which is safe and will work with most mobile devices, and also very important to save the battery.
Al this means that you can transfer to, or from device once per connection interval, no mater if it is read, write or notification.
Some devices has configuration settings which allows changing of connection interval, but if you just wanted to know what happens, thats it.
I do have a Bluetooth LE remote controlled car. Therefore i need to write periodically to a drive characteristic on the car. My microcontroller (AtmelXMega128A1 # 32Mhz + nRF8001) should be able to handle up to 122 connections per second # 7,5ms connection interval.
My Android App is based on cordova and a bluetooth low energy plugin: https://github.com/randdusing/BluetoothLE
I am running this on a Nexus 5 with Android v4.4.4.
I have a timer which sends values for steering and acceleration to the car each 175ms. I would like to send each 50ms but that does not work. I cannot tell where the problem is but i guess it is the android implementation of GATT (I get the pending command error at some level).
If i write more than it can handle the car executes all commands in a row but time shifted. Some queue hickup obviously and this is not the Microcontroller as it operates much faster.
I am doing a timing change which seems to be successful. I tried turning WiFi off as i hoped it would help but nothing changed.
Is there any experience on periodical writings to a GATT characteristics on Android? Examples would be great.
First of all you should make a robust design. Data should be driven by callback from the Android BT Stack telling when it's ready to accept more data (when the previous transmission is done). Do not use a timer. There will always happen need for retransmissions on the lower stack level so you cannot rely on an exact transfer interval and throughput.
The 7.5ms is the shortest possible connection interval however the default is usually much slower (48.75ms on my Nexus 5 with Android L) So from your peripheral you should try to request a faster connection interval once connected. This will speed up your throughput and responsiveness.
Some Android BT stacks refuse if you try to force a very fast connection interval. You should be handling that intelligently. Like trying with 7.5ms (parameter = 6) and increase it if it failed. iOS design guideline say you must not use a lower value than 20 (*1.25ms) and the upper request value should be at least 20 higher than the lower. You will get a faster connection parameter though if you request values min=10, max=20 and end around 18ms or something.
For android it seems most will accept the 7.5ms (value 6) but again you should not force it because the stack might cancel the connection then.
I made experiments on Android L, requesting connection intervals from the peripheral side when connected. Android rounded off requests so only every 3rd step gave a difference.
6=7.5ms, 9=11.25ms, 12=15.0ms, ..., 39=48.75ms which seems to be the default value on Nexus 5 running Android L.
Bluetooth is a shared resource in the broadcom chipset most are using on the smartphone side. Wifi, BT Classic, BT Low Enegy and sometimes GPS shares bandwidth. You will see hiccups and must be tolerant about them. Make a robust design.
Something else you can try is to renegotiate MTU-SIZE if you need larger data packages than the default. This is by specification an optional BLE feature however Apple broke it completely in iOS7 where they use it as a mandatory thing to boost up throughput. This broke all BLE devices which didn't implement the response handler and so it crashed and could never be used with iOS devices until a SW update was made. Baaaaaad. For android this is not a problem though.