My app is pinned and after waking up device all network requests that are made right away fail with a connection timeout. Waiting a couple of 100ms or seconds does the trick and everything works normally after that.
I suppose there's a small window of time when wifi is "re-enabled". Whats the best way to detect that event?
Android version 4.4 and wifi sleep is set to "never"
As Augusto Ferrarini points out you can listen for broadcast and handle it accordingly. There is a chapter about it on developer.android which I'd recommend reading together with the link from Augusto Ferrarini.
Related
I'm currently trying to make an Android app that will have some interaction with a BLE device. That device doesn't have the Ibeacon protocol.
What I want to do is auto connect to that device every time it is in range even (and almost 99% of the time) when the app is not in foreground. The only thing I know is that it is a BLE device, I have access to it name and address (00:1E:C0:29:BD:F8).
It is crucial tha the app connect to it every time it come in range. Even if the phone is lock it must connect no matter what (except if the phone is shut down XD). But as soon as the phone has booted and that bluetooth is activated, I must be sure that my app will be able to connect to tha device if it come in range.
I wanted to know what is the best way to do so.
The only way I can think of is to start a service as sticky, that will scan every 15 seconds (or something similar) for the device it already has registered to auto-connect.
The downfall of that method I guess is that it will surely drain the battery, I'm not sure about that but doing a scan for 3 to 4 second every 15 second must use up a lot of battery.
What do you guys think of that ?
Does anybody know a better solution I could use ?
Thank in advance for the help.
I'm looking for a way to detect the disconnection of a Bluetooth device immediately after it has happened (2 second max), typically in a "device too far" scenario or Device battery is dead. Currently I can detect it with a BroadcastReceiver by getting a BluetoothDevice.ACTION_ACL_DISCONNECTED, but it takes about 16 to 20 seconds to fire.
Is there any way to get notified in 2 seconds Max.
I used BroadcatReceiver but it is not fast enough to get alert in 2 seconds Max, so is there any other kind of approach available to get notification quickly that bluetooth is disconnected.
I use this createRfcommSocketToServiceRecord(UUID); to connect a paired device and i am bound to use it using UUID.
I have visited a lot of links regarding this issue, but no one matches with my needs.that's why any help would be appreciated.
thanks.
I think the only way you can reliably sense loss of connection quickly (within two seconds) is via your own application protocol that you use over the Bluetooth connection. For example, your application protocol might implement a heartbeat that occurs every 500ms. If you don't see a heartbeat within two seconds then you could trigger your own event.
Bluetooth is a socket-based stream protocol that is designed to work over an unreliable medium (i.e. radio), and as such has to tolerate errors in (or loss of) packets. For this reason it will take significantly more than 2 seconds before your Bluetooth stack declares it has given up and disconnected the device, as you have found.
I have an application on Play which is designed to talk with an automotive ECU via Bluetooth and my strategy for sensing disconnection is exactly as I suggested in my first paragraph.
Update 20th June 14
I see in your bounty comment and also your comment below that you're asking for a code example, but it's kind of difficult for me to provide one without knowing anything about the application protocol that you're running over the socket connection. Or to put it another way, what exactly is it about my first paragraph (i.e. the heartbeat suggestion) that you do not understand or cannot create code for yourself? The concept of using a heartbeat really is quite simple. You would define a certain message type in your application protocol that represents a heartbeat message. One end of the connection sends this heartbeat message periodically, say every one second. The other end of the connection checks that this heartbeat message is received every second or so and drops the connection after a two-second time-out. It is impossible to be any more specific than that, because I can't see your existing code and I don't know what kind of messages you are currently exchanging over the socket.
After nothing work around!
I got two things to get my work done.
I need to check that is my Bluetooth socket is not in use(Sending Receiving) till 2 to 5 sec I disconnect that and when user wants to send data to the receiver device I connect that again.
Or I'll try to connect the socket after 2 to 5 sec so that if it is not ready to connect means it is already connected, else it will be connected and I refresh the previous socket references.
but first option is more valuable to work perfectly in my problem.
This is a problem with old bluetooth and more hardware than software.
If you want to notice that the connection is broken you need to do polling (a heartbeat), something like "are you alive? are you alive?"... This is bad for battery so... the users will finally uninstall your app.
I recommend you to change to BTLE (bluetooth low energy), devices like Nexus 5 has this.
With BTLE you have a proximity profile which can tell you the quality of the signal, so, you can guess the distance (near, far, out of range) and therefore you can also tell if the devices are disconnected.
Another nice point is that if the devices are out of range but one is again in range you could get noticed as well, so this is really nice for apps to open doors by proximity for example.
Check this:
https://developer.bluetooth.org/TechnologyOverview/Pages/PXP.aspx
In the other hand Apple has invented the concept of iBeacons, devices that are distance aware, and the good thing is that there is also an implementation of iBeacons for Android:
http://developer.radiusnetworks.com/ibeacon/android/
I need to keep a TCP connection established indefinitely (as far as possible). Is not an own server so we cannot change the way it works. This server needs some kind on ping each minute to know that the connection is alive. If the server do not receive the ping after some minutes (less than five), the connection and the session is closed. In this way i need to maintain a TCP connection with the server and be able to send pings at the periods specified.
At the moment i have an Android service with the flag "ongoing" so Android should not kill it (at least by normal procedures). The android service seems to run fine and the pings are sent periodically. However when the service is running on a mobile phone (not emulator) and it gets idle, android seems to freeze the service while the CPU is sleeping, so the TimerTask sending pings stop working and the connection goes down.
I have tried to lock the phone from going to sleep with a partial wake lock and it solves the problem but the phone consumes too battery, what is unfeasible.
I noticed that the AlarmManager may help on this task, so i want to schedule an alarm to update the running service and then send the ping. This will let the CPU going to sleep and also the ping being sent. But schedule an alarm each minute may be also so battery consuming or not?
I have not tested this approach at the moment, but is feasible? is there a better way to keep this kind of TCP connection?. How android services like Gmail solves this kind of issues?
I need to keep a TCP connection established indefinitely with a server.
Why?
For starters, it is technically impossible. Users will switch between networks (e.g., was on WiFi, failed over to 3G), users will leave areas where they have Internet coverage, users will turn on airplane mode, etc.
At the moment i have an Android service with the flag "on_course" so Android should not kill it.
There is no such concept as "on_course" in Android. Android services can and will be killed by users (task killer, force-stop in Manage Services) or by the OS. And, since this will be an everlasting services, your users will kill your service if they do not understand what value it is continuously delivering.
I have tried to lock the phone from going to sleep with a partial wake lock and it solves the problem but the phone consumes too battery, what is unfeasible.
Correct.
I noticed that the AlarmManager may help on this task, so i want to schedule an alarm to update the running service and then send the ping. This will let the CPU going to sleep and also the ping being sent. I have not tested this approach at the moment, but is feasible?
Sure. You will still consume too much battery, IMHO. Please allow your user to control your polling period, with a wide range of options (e.g., 10 minutes, 30 minutes, one hour, never).
How android services like Gmail solves this kind of issues?
They use C2DM, which is part of the OS and took a lot of engineering to get right. There was a presentation on it at the 2010 Google I|O conference -- the video should be on YouTube. Note that they do the heartbeat ping every 30 minutes IIRC, and they optimize for the case where the device is on 3G (to allow the WiFi radio to turn off after inactivity).
If your objective of your permanent connection is to implement a push-style communications channel, please consider using C2DM.
You can wake phone from idle with partial wake lock right before you execute ping and after you do it release wakelock. It will scientifically reduce battery consumption and it will do the job. Also, try to increase ping time as long as you can.
5 Minutes is a little short for the ping time, can you configure the server to hold the connection longer? 30 minute ping or higher would be ideal. Here is an example of an application that holds a background tcp connection and will wake up the device from a deep sleep on incoming tcp traffic. https://github.com/schwiz/android-websocket-example
By default, Wifi sleep policy is "Sleep on screen idle".
With this policy, is it possible for a Background Service at a later time to wake up Wifi using some API?
Am trying the following, but does not work:
When my Background Service wakes up, it calls "ConnectivityManager.getActiveNetworkInfo()" to get active network.
Since, the wireless is off on idle, I tried waking it up using "WifiManager.startScan" on a previously used Wifi connection.
But still dont get Wifi connectivity.
Any ideas?
I preferably do not want to change my sleep policy to "Never".
Thanks
Hemant
There are no real simple solutions for this. To with a high probability ensure you have WIFI connectivity when the phone/screen goes to sleep the best way is to turn it off. Look here for a lot of details - http://wififixer.wordpress.com/
It is important to realize that in sleep mode the Wifi enters a low power mode. This will become tricky then to programmatically check as it might have connectivity to the Wifi but the Wifi connection is too weak or too slow to complete the HTTP request and hence it times out. This would force you to also check the speed of the Wifi connectivity as well as you will have an active network but a pretty lousy one.
Proper handling of the escaping when timeout occurs for the HTTP call you make makes it ok to use but ultimately the only way to have a background thread constantly running to get data is only doable when you have the Wifi mode to never sleep.
It is tricky and not the best way I know. :-( It is however the only path I have found which is reliable enough.
I've encountered a problem with mobile internet connection after phone wake up from sleep mode. There is an application which updates some data periodically. AlarmManager triggers my BroadcastReceiver which starts service. service acquires PARTIAL_WAKE_LOCK and some http requests are sent. Unfortunately when update interval is quite big (5h) service could not send/download anything. Problem doesn't appear when I'm using WIFI connection instead of mobile and WIFI sleep policy is set to never. Everything is OK on mobile connection when update interval is short (less than half an hour). I'm also sure 5h event is received by my BroadcastReceiver because I've checked it.
How such events should be handled. I've tried to check whether connection is established by ConnectivityManager and retry 5 times if not but still same problem appears.
Thanks for any answer in advance
The Android system turns of WiFi a few minutes when the device is suspended (i.e. screen turned off).
When the device turns on again (by acquiring the wake-lock), it will take a few seconds until network connection is re-established (this is also true for 3G data connections, which are also torn-down while device is sleeping).
My suggestion:
- Wait for ConnectivityManager's broadcast that the network is up again. Practice proves that waiting 2-3 seconds after the broadcast is received helps things to settle before starting to send and receive data.
- A bit easier: After grabbing the wake-lock, wait a longer timeout and then try to connect.