I couldn't produce this example which iam about to explain, so i post this here to give me more info about it.
Lets say that we want to make an http request to receive a JSON object from a server. We hold no wakelocks nor we make our app a foreground. We make the connections and we wait for our response from server.
What if the device goes to sleep at that very moment (waiting for the
JSON object). Do we get the object when the device awakes or we get a
timeout exception?
NOTE
Do not involve doze mode in this example. Just that device goes to sleep.
Thank you
When an Android is kept idle, the device locks and then it goes to
deep sleep mode. In deep sleep mode the Android system, closes the
existing network connections like TCP or UDP. If your app is connected
to a server, it loses connection to the server and tries to reconnect
based on the reconnect attempt methods configured for the client. But
if your app is the server, all the client will lose connection to the
server, and you have to start the socket again in server and try to
connect once again from the clients.
From https://stackoverflow.com/a/33366487/806328
retrofit just "listens" for network connection, when it loses it - connection time out error after specified time
In this case, your device will got to sleep and you will get Activity Life Cycle Method Call back that is onPause() and onStop while your service will be running. This process will not make your webservice call stop. Once you get response from server your app will get call back (if you have implemented). And nothing bad will happen until you have killed your app before going to sleep. If after web service you may be accessing some variables belonging to activity that started web service. This will lead crashing.call. When you undo sleeping state you will get call back of onStart and onResume That means when your device went to sleep it did not kill your activity.
Related
We are currently creating an application that periodically retrieves data from the server.
When charging or in active state, data can be obtained correctly via Wifi, but when entering DOZE mode and entering sleep state, data cannot be obtained via Wifi and times out.
By the way, I put the application I am creating in a whitelist that does not optimize the battery, and I am going to get data from the server with the startup condition of Worker every 15 minutes.
By adding it to the whitelist, I think that Worker startup is secured, but I guess that Wifi is in sleep state and timed out.
If you look on the internet, you will find examples of task execution using the alarm mechanism. If it is started from the alarm, will the sleep state of Wifi also be canceled? Also, in that case, I would appreciate it if you could give me the URL of the HP where the example code is posted.
I implemented a chat application in Android with websockets. However when the user closes the application, the websocket connection to the server is lost and no new messages can be received.
I am essentially lost and do not know where else to turn, how can I setup the service in the app to stay connected to the server as the user logs in as well as after the app has been stopped?
As we're all aware, continuous background code execution is not feasible on Android; different ROMs will man-handle your background services without any guarantees (e.g. START_STICKY will not get your service restarted on some devices), so we need to do the best we can with the code that is reliably executed.
In this situation, you have a websocket server delivering continous information to your client. When your app is in the background, it may miss out on some data. When your app returns to the foreground, your information may be out of sync, so you need to synchronize again with your server, and then reconnect to your websocket.
In my chat app I achieve this by checking whether my websocket service is running onResume in an activity which is a superclass of all the activities that I want to have access chatting data (i.e. not login/registration activities). If the service is not running, I synchronize my data by pulling the changes from an endpoint and then restarting the service. This way, even if the service is killed in the background I will still get the latest data and real-time experience once the app returns to the foreground.
I read the Last Safe Method to be called before killing the application in Android is OnPause.
Suppose I have client running on Android that is a part of location based Client/Server application. I have some design issues:
When I create the main activity I though it is logicall to start a service that connects to the server (running on my computer) and updating it in with the user location.
Now, when the application is active I want to present the user some information. Even if the user paused the activity I want the service keep running in the background and update the server. I also want the server to know when user disconnected.
Now because OnPause is the last safe method guaranteed to be called by the system, I don't know where it's best to notify the server of user disconnection.
I want my application to be connected to server though the mobile connection, yet allowing the device to go into sleep mode. I expect it to wake up when IP packates arrives.
How can this be done? How to receive "interrupts" from the Internet without draining battery?
When you are blocked on a read from a tcp stream the device can go into a deep sleep and when tcp traffic comes in it will briefly wakeup the device, as soon as a bit is read in you start a wakelock until you have received the whole transmission then release it.
Here is an example with web sockets, I've ran this app for over 12 hours in the background with no battery impact.
https://github.com/schwiz/android-websocket-example
The client is here, the blocking read is in the start method.
https://github.com/schwiz/android-websockets/blob/master/src/com/codebutler/android_websockets/HybiParser.java
I've been using long living TCP connections on Android without a wake lock for some years now.
My experience is that when data arrives on a TCP connection and the device is in deep sleep, it will be woken up for a short period of time at least. Waking up the device could take up to ~2 minutes sometimes, but it's usually done within a few seconds.
Now that the device is awake, the receiving process has some time too process the data. Now either the process is able to do so before the device is put back into deep sleep, or the device will be put into deep sleep suspending also the process. The important thing here is that the data is not lost, it remains in the memory and the process is able to resume the work processing the data the next time the device leaves deep sleep. Of course, this means that if the sender awaits an answer to his data, it may take some time, until he gets it.
You could take a wake lock as soon as your network library notifies you that a new message was received. But if you done, then make sure to handle the lock properly, i.e. ensure that it is released at some point and in every code path. I personally never experienced the need for a wake lock, the Android device was always long enough awake to process the request. But your millage may vary.
So this is very old but i ended up testing the behaviour #Flow described and just wanted to confirm that there seam to be arbitrary delays sometimes between the arrival of the data and the wakeup of the device.
I tested using a tcpClient implementation and an mqttimplementation. The idea was to see if there is an requirement of instantly getting the wakelock since this delay appeared in my mqtt implementation.
Test steup:
we have 2 services one running the tcpclient and one running the mqttclient in different apps
Both Services run on the same phone with the same permissions in the background.
The Server sends in both cases an "ping" message.
Our client implementation acquires a wakelock as soon as possible and reads the current Date.
for the tcpclient this is instantly
for the mqttclient the wakelock can only be acquired after the arriving data has been propagated through the networking libraries
we send back an response pong message including the read date
this send happens after wakelock release to see if this further delays the response time
the server logs incoming messages with the arrival and the read date
It appears that in both implementations there sometimes is an arbitrary delay to the call to our code. This makes it most likly that there is a delay to the wakeup of the device and not to the acquire of the wakelock.
this delay can be sometimes seen on all devices(tested on huaweip20light, HMD Global#Nokia 7.2, samsung#SM-N960F)
this delay seams more likly to happen on the HMD device higher api and victim of the stricter battery optimisations android established
Google Cloud Messaging might be what you are looking for:
http://developer.android.com/guide/google/gcm/index.html
I'm an android noob that is looking for some advice on how to properly use a service in Android. I am building an app that will connect to a server on the Internet to get a data stream via TCP. That data then needs to get send out to another device that is connected via a bluetooth serial port. I want this to continue to function in the background while the user looks at a different activity.
The app will be a NTRIP client, which pulls real time RTK correction data from the Internet and sends it to a RTK GPS receiver that I connect to via bluetooth. The data rate will be about 500 bytes/second. The user interface is a single button to connect or disconnect the data stream and some text to show status of the GPS receiver. There are also a few settings that will need to be configured by the user such as the IP/port of the server to connect to and the bluetooth device to communicate with.
I think I need to have the main activity spawn a local service, and then have the service spawn a thread for the TCP stream and another thread for the bluetooth connection. Does this sound right?
What is the best model for the service in this scenario?
-Start(bind) the service every time the activity starts, and have the connect/disconnect button send commands to the service to start/stop the threads. If I go this route, the service will continue to run after the user disconnects and goes to another app. The service would need an inactivity timer to terminate itself.
-Start and stop the service when the user presses the connect/disconnect button. The service only runs when data is moving. If I do this, the activity will need to see if the service is running when the activity starts, in order to know if it should bind to the service or tell the user that the link is disconnected.
Thanks.
I'd go with your second option. Checking if a service is running or not is an easy task and also you won't consume unnecessary processing time which will be better for the battery life.
Just because you can run a service for a long time in the background doesn't necessarily mean that you also should do that. At least not all the time.
As android supports more than one entry point into the app, you could define two entry points in the Manifest.xml.
<category android:name="android.intent.category.LAUNCHER" /> defines, that this class could be started from the launcher. I guess that would work for a service, too. I would do two entry points. One which spawns the activity first and gives the user some configuration control. And another which simply spawns the service.
As you have no control over the lifetime of an activity i would not suggest to do anything which should not be ended by the system. If you have an incoming call your activity would simply die.
If the user starts the service you could create an widget with the button. If the user starts the activity you could start the service and the widget.
And if the user starts the widget, the user decides, what should happen with the service.
I'm not a Java or Android programmer so take what I say with a grain of salt. The normal way to handle blocking IO in Java is to use threads. It sounds like the data flow is unidirectional but for maximum flexibility I would create 3 threads, one for the UI, one for the TCP connection and one for the bluetooth connection. Communication between the UI and two worker threads could be done using shared variables (need to careful about synchronization, race conditions, etc). I would pass the data NTRIP data to the other worker using a multi-threaded queue data structure.
The worker thread for the NTRIP data would be roughly:
while (app running) {
if (connection enabled) {
if (not connected) {
c = connect to remote
}
data = get data from c
queue.put(data)
if (options reconfigured) {
close c
}
}
}
For the bluetooth thread:
while (app runnning) {
data = queue.get()
if (UI settings changed and connected) {
close connection
}
if (not connected) {
c = connect to remote
}
send data over connection
}
In the normal state, both workers are blocking on IO and will be consuming essentially no CPU time. Based on my experience, I would recommend you write your code to handle communication errors. For your code to work well in the real world you have to handle connections closing, hanging, etc. Making it robust will likely be the most time consuming part of the development.