Android devices stop receiving WiFi UDP broadcasts - android

I am building a UDP-based audio streaming system and face a weird behavior with two different Android devices, that I do not understand at all.
I have a server broadcasting UDP packets on my local WiFi to 192.168.178.255. The Android app listens to these broadcasts using a DatagramSocket and receives the packets just fine. A MulticastLock has been acquired, but the app stays in the foreground, so this shouldn't matter.
However, after a seemingly random amount of time (around a few minutes) the app stops receiving the broadcasts. Weirdly enough, this does not only affect my own app, but also any third-party tools which can listen to UDP broadcasts. UDP packets addressed specifically to the device are still received. The device will no longer receive any broadcasts until I disable and re-enable the wifi connection.
What's even more weird: The test packets I send have a sequence number, so I can keep track of the last packet the device has received. I am running this test on two different devices (a Huawai FIG-LX1 phone and a Fire-Tablet) and the devices stop receiving packets at EXACTLY the same packet. I am looking at the network traffic on Wireshark and I can see nothing special about this packet or anything happening on the network.
Any ideas what may be killing broadcast reception on two completely different devices in this way?
Unfortunately neither of the devices are rooted, so I cannot run a network analyzer directly on the device, to determine if -for example- the router might not be forwarding the packets anymore.

Related

Android BLE ACL_DISCONNECTED sometimes delayed

I am developing an Android app (API 23+) that communicates via BLE with a device. There is no pairing / bonding involved.
The happy path of the interaction is that the app connects then sends a message to the device, and the device in turn sends a reply back, then they both disconnect.
While characterizing strange behavior I asked in Android BLE unexpectedly reconnects potentially from PBAP / MAP Bluetooth profiles, I created a simple service to monitor low-level bluetooth connections; it listens for broadcasts of BluetoothDevice.ACTION_ACL_CONNECTED and BluetoothDevice.ACTION_ACL_DISCONNECTED.
While most of the time the connect / disconnect corresponds well between app and device, sometimes the app receives a disconnect notification that can be ~5-20 seconds after both the app and device have closed the connection. I have verified that the device actually closed, and the app logs all show the system properly shutting down the connection.
In these instances, if the app tries to connect again with the device before ACL_DISCONNECTED is broadcast, it will either receive an error or the subsequent connect request is queued and kicked off after the ACL_DISCONNECTED broadcast.
This does not seem to be specific to devices --- I test with a variety of makes and models --- nor the API version (23-25).
Is this known (expected) behavior?
Are there ways to mitigate this issue?...to ensure the disconnect indeed happens in a timely manner?
Is there a more direct way --- e.g., through an API call --- to tell if the connection is still up, as opposed to receiving ACL-related broadcasts?
If the BLE devices stops broadcasting instead of sending disconnect signal this issue happens. If the BLE device didn't send the disconnect signal Android device thinks the that the connection is open and it waits for sometime (5-20 sec) and then calls onconnectionstatechange() with time out status code. If you can make the BLE device send the disconnect signal instead of stop broadcasting it should fix the issues. Hope this helps

Android bluetooth wake up device

I bought myself a smartwatch that has Android KitKat running.
I have connected it to my HTC m9 smartphone using Bluetooth.
I have created an application that is running on both smartwatch(client mode) and smartphone(server mode).
The applications are talking each other over a Bluetooth Socket connection.
When I get a phone call on my phone, I am sending a Bluetooth notification over the Bluetooth socket to the watch and make it vibrate.
All is good as long as the watch's CPU is up and running.
When the watch goes to sleep, and I get a phone call on the smartphone, the notification is not processed by the watch because watch's CPU is sleeping.
Using a partial lock on the watch does the thing but it consumes the battery to fast.
I don't need a partial lock on the phone, because when the phone receives a call, the phone is "magically" awaken, so my application's service is able to send the notification.
I also can't use AlarmManager on the watch, because I need the watch to wake up when I get a bluetooth socket notification, not on regular intervals.
A WakefullRecevier is also not solving the problem because my watch needs to wake up first so that the WakefullReceiver puts the power lock (or have I got this wrong ?!) and runs its code.
So the question is: How does the phone wake up on incoming call? Or on SMS received? It is a hardware thing..an interrupt?
Is there any way of waking up the watch when a bluetooth message is received?
Thank you
For the past few days I've been playing around with the watch making different tests.
I am not answering the original question but since nobody else answered the question I will just write down my own conclusions which are good enough for my application and maybe help others with similar problems.
1. When the paired watch is in Bluetooth range of the phone, a power lock is not needed on the watch.
Any messages sent by the phone are received by the watch.
If the watch stays idle for some time, the 1st Bluetooth message sent by the phone is received with about 1 second delay. Probably Android watch goes into some kind of low power mode but is able run my code when Bluetooth message is received. Of course Bluetooth messages are received almost immediately by the watch while the watch is not idle.
2. Best way to find out if a Bluetooth socket is still connected, is to write into it.
Socket read is a blocking call but it does not throw IOException when watch goes out of Bluetooth range. I wasn't able to find a read timeout property I can change.
So I am just writing a byte into the socket every 60 seconds to detect if socket is not connected anymore. Battery impact is minimum while socket down detection timing is acceptable.
3. When the paired watch is NOT in Bluetooth range of the phone anymore, Bluetooth socket re-connect strategy is required.
Using a partial lock in this case does not seem like a good approach since it keeps the CPU awake. Also trying to re-connect to often to the phone kills the battery.
The re-connect strategy is based on application needs.
I ended up using WakefulBroadcastReceiver and AlarmManager to make a socket connect attempt with a given period.
4. Every now and then, when the watch goes out of Bluetooth range, then comes back into range, then again and again the Bluetooth socket seems to go in some kind of 'zombie' state. Sometimes the socket.connect call just blocks without succeeding or throwing error, some other times the socket.connectcall does not throw error given the impression that connection has been established, but a subsequent write always throws IOException.
Whenever I encounter these kinds of situations I just stop/start Bluetooth adapter which seems to solve the problem.
5. Pay attention to stop/start the Bluetooth adapter. During Bluetooth restart attempt Android can put the CPU to sleep. I wasn't expecting this behavior but it really happens. So if you want to do this as fast as possible without any delay, make sure the application acquires a PARTIAL_WAKE_LOCK during the re-start attempt. Of course don't forget to release the lock as soon as possible.

Is CHANGE_WIFI_MULTICAST_STATE permission and use of WifiManager.MulticastLock required to receive multicast packets on Android?

I have a test app that I'm using to demonstrate whether or not multicast traffic is making it into an Android device. I'm seeing behavior that appears to contradict Google's documentation here and here which implies that two prerequisites need to be in place in order for an app to receive multicast traffic:
Acquire the MulticastLock
Add the CHANGE_WIFI_MULTICAST_STATE permission to the app's manifest
My app is able to receive multicast traffic without either of these items in place. Below is the code snippet that sets up the multicast socket for receiving data.
MulticastSocket multicastReceiveSocket = new MulticastSocket( 18200 );
multicastReceiveSocket.joinGroup( InetAddress.getByName( "232.232.232.232" ) );
byte[] buffer = new byte[ 65536 ];
DatagramPacket packet = new DatagramPacket( buffer, buffer.length );
multicastReceiveSocket.receive( packet );
Should this be happening? Should I be able to receive multicast packets without either of the 2 prerequisites in place? I noticed that the MulticastLock documentation says:
Normally the Wifi stack filters out packets not explicitly addressed to this device
Does this mean that the behavior could be different from one device to another? I'm testing my app on a Samsung Galaxy Note4 (model SM-N910T) running Android version 4.4.4. Any clarification on this issue would be greatly appreciated.
WifiManager.MulticastLock when acquired, would modify the state of Wifi interface on the device (gobally), to allow all apps to receive multicast traffic. your app will need CHANGE_WIFI_MULTICAST_STATE permission if your app wants to acquire this lock.
In your case, if multicast traffic is received without acquiring this lock, it must mean that either
(1) some other app has acquired this lock, due to which, the interface is now parsing/filtering and delivering multicast packets also.
or
(2) manufacturer of the device ignored this android api while developing the device, and interface always delivers all multicast traffic.
The description of the API does not force manufacturers to only allow multicast traffic when an app has acquired this lock.
Regardless, apps must acquire this lock if they want to reliably receive multicast traffic.
MultiCastLock class is used for receiving multicast signals (other than Access point probes) by wifi manager. Those packets can be other wifi enabled devices probe signals and similar packets that are caught by your wifi card.
Here what you describe is a whole different stuff. You merely listen to a specific socket and collect data packets that are flowing inside your connected network.
Like other sad things on Android, it depends on the device.
I could just start receiving UDP BroadCast packets on a Motorola XT890 (RAZRi) with Android 4.4.2 KitKat after adding this permission and acquiring a multicast lock.
With my Samsung and Nexus devices, this was not necessary.
Apparently, other Motorola devices have this issue as well:
Moto G dosent receive UDP packets over WIFI Network

keep receiving packet when the screen is turned off

I am writing a local communication system between Android phones that are connected to the local Wifi Access Point.
In the design of my system, the Android phones should notify the owner once they received an UDP broadcast packet from the Windows server.
The system works just fine when the screen of the phone is turned on. But it is found that, once the screen of Android phone is turned off, the phone just ignored the packet, just like no message is received.
I have tried Google for many time, but still no luck. Actually I really don't know what keyword should I use for doing the searching.
Do any one know how can I do what I want? Thank you very much
You will need:
a WakeLock
a WifiLock
a suit of armor, to better defend yourself from users who do not like it that you are keeping the device awake and WiFi radio powered on

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.

Categories

Resources