Android - Battery impact for simple background thread that periodically wakes up - android

I'm trying to implement a timeout mechanism for a user's login session in my app
ie. If user has not interacted with my app for say 10 mins then when he uses the app next (regardless of whether the app was previously in the background or currently in the foreground) he should be taken to the login screen.
My current implementation uses:
- a singleton instance of a Java Thread (call it 'TimeoutThread') from my 'BaseActivity' (all my activities except the LoginActivity extend BaseActivity)
- so the singleton 'TimeoutThread' will be started only the first time any post-login activity starts up.
- 'TimeoutThread' will simply keep track of the 'lastUserInteractionTimeStamp' inside a while() loop with a Thread.wait()...
so it wakes up every 2 secs, checks if the (currentTime-lastUserInteractionTimeStamp) is greater than say 10 mins and if yes then it'll trigger some callback if callback object is not null (the callback is made null whenever the app goes into background, etc)
This method works fine right now.
My concern is that since this thread wakes up every few secs (Thread.wait() inside a while(true) loop) even when the app goes into the background (eg. user presses Home button), it will cause a battery drain.
I've been unable to find a good link to explain the effects of keeping such a thread.
I did find links for power optimization, scheduling recurring tasks etc (pasted below) but couldn't directly find my answer there.
https://developer.android.com/training/monitoring-device-state/index.html
Scheduling recurring task in Android
Can anyone critique this approach / suggest a better one ?

Related

Android - use a service as a timer?

I've read and re-read the documentation but I'm still now sure if using a service (and how) is the right way to keep a timer running.
I basically want to have a countdown timer, but I want it to run uninterrupted even if the app gets closed (and show up as an ongoing notification). When a certain activity in the app gets opened (resumed, opened, launched from clicking on the notification), I want it to be able to get the current value from the timer (no more frequent than once per second). If the app got closed, I still want the timer to be able to use/launch activities or other services (or access the database) of my app.
So if I understood the Android developer docs correctly, I should use a service that is started (because when started it should be able to do its thing even in the app gets closed) and bound (so an activity can get data from it). Then I searched Stack Overflow for similar topics and some people are recommending using IntentService (but can it send data to an activity?), or Handlers or even AlarmManager.
I'm really confused and I'd prefer to be able to pick the right approach from the start (rather than finish the app and then realize my approach wastes a lot of battery or something). The problem with documentation is it answers questions it thinks I have, so I have to ask a real person.
My suggestion is:
When user starts your timer save current system timestamp.
In your UI: Every N milliseconds just read saved value and compare it to current timestamp. This give you a diff = elapsed time.
You do not need any timer/service/alarm manager. Every time user has return to your app you just do step №2 to show elapsed time.

android: Timer for Quiz app

I'm involved in developing a Quiz app for android. Each collection of questions should be answered within a specified period of time. This period of time can be measured using an android CountDownTimer.
However, CountDownTimer pauses when the app is no longer in focus.
What should I do if I want to timer to continue running, even if the app is closed? (If the app is reopened and the timer has expired, the app should display a suitable message).
Use the lifecycle of your Activity
http://developer.android.com/reference/android/app/Activity.html#ActivityLifecycle
Override OnPause() method (called when activity loose focus)
stop the timer
store the current time
Override OnResume() method (called when activity returns in foreground)
compute the elapsed delay
if the timer has expired : display message
else restart the countdown timer with remaining seconds
Just listing down possible ways it could be implemented (best one first):
user2553764' s answer of just saving & calculating timer value based on system. (Best suited, it is simple & requires no background services or threads).
Using handler, see How to set a timer in android. (Official documentation suggests it use for timed operations, though seem overkill for your use case).
Using a Service (bindservice), Implementing a Count down timer using Service in the background. (But services can go out of memory, in that case might have to use it with 1st approach).
AlarmManager, dunno if it should be below binded service but it can be used none the less.
How to run a method every X seconds, suggests use AlarmManager for >10min intervals else Handlers. (Also mentioned in android documentation as you stated above).
You want to create an Alarm using AlarmManager. They run regardless of what activity is on screen, and even runs when the phone is asleep.

Good Design: Worker Threads and Activity Restarts

It is well known that Android places our application components (Activities, Services) under threat of being killed at any moment. This makes things really complicated if you want to provide a robust, non-leaky solution, while at the same time keeping the code clean and addressing separation of concerns.
Problem:
An activity starts a time-consuming task (in form of a Runnable, AsyncTask or whichever other mechanism). A progress dialog should be displayed. The task will open several connections, but it should have a means of updating a progress bar, and it might need to display a choice dialog half-way to completion. It also should be able to close the dialog and show a Toast when an error occurs, or when it completes.
When an Activity is killed and later a new instance is recreated, I can think of two options:
Try to kill the running task as well, and spawn another task instance when a new substitute activity instance is created. This is not an option for a long running task, as it is unacceptable from a user point of view to start the task and see the progress bar indicator going from 80% back to 0% with no apparent reason. This however is the approach followed in the Shelves example by Romain Guy. Apparently this is the approach recommended in the official Developer Guide.
Keep the task running: So we could have an activity subscribing to (and possibly starting) the task for updates at onResume, and unsubscribing (and possibly pausing) it at onPause.
Following the second option means that we should prevent the task of being collected in case the activity is temporarily destroyed. For instance, we could declare it inside a custom Application class, or even offer it as a service to the rest of the application (using a Singleton? an Android Service?) I'm no fan of this, though, since the task is used only by the activity, so it doesn't make sense to make it available to other classes. Android Services on the other hand also have to deal with life cycle.
Option #2 also involves ensuring the old activity is not leaked. We should not try to update the GUI if no activity is present. The whole think should be thread-safe. Finally the task should not remain in memory after we are sure it is no longer needed. But at the same time, if the initial activity is destroyed, the task keeps running, and a new substitute activity kicks in, the task has to be around to update the GUI immediately and display the task current status (or result in case it completed).
The fact that the task might be running when no activity is shown is another problem to deal with, since we could need user interaction (choice dialog) synchronously at some point. This could be solved if the activity had the ability to immediately pause the task when reaching onPause, but the task could take some time to pause itself or even be unable to do so.
I know similar questions has been asked before, but I'm not asking specifically about how to solve the problem, but about what design would be recommended in order to achieve loose coupling and isolate the activity from the task as much as possible.
In short:
- This is a recurring problem in Android development and someone has probably come up with a clever design before. Is there a design pattern, or a well tested library that simplifies this?
- If you were to implement #2, which class would you choose to for the task (Runnable, Service, etc) and how would it communicate with the activity?
P.S. Please refrain from posting solutions based on the "orientation | keyboardHidden" hack XD. Other than this, any help would be appreciated.
UPDATE:
My first attempt has got a bit messy. The app is a bluetooth printing utility, which involves Detecting BT status (and asking the user to enable it if it were disabled), retrieving paired devices (and asking the user to pick one if there were more than one), then sending the data and finally inform the user about the result. As this task was 80% IO code, 20% GUI-related operations, I had to group the GUI code at the beginning and end of the task, then moving it out of the task back to the activity. I have an IntentService that does the heavy lifting, then reports back to the activity via BroadcastReceiver. This solves most of the problems but there are a few issues with such a design. First, there are all those constant strings used as keys to put and retrieve fields from the input and output Intents, which are introducing semantic coupling. I'd have preferred type-safety in the activity<->service communication. And I yet have to solve how to pass complex custom objects to the service in the Intent, by now I'm stuck with Parcelables and primitive parameters. Finally, both the activity and the service are using the same API (bluetooth), I'd have preferred to have al the BT-related code in a single class. I think I'll throw away this design, and try again with a custom printing queue based on threads, despite it will make harder dealing with killed activities.
why not have your activity start a service to host the long running task? a service is your best-bet for keeping things running long term. you can provide hints to the OS to leave it running. see startForeground() and START_STICKY.
you can communicate back to the activity by broadcasting from the service. have your activity programmatically register a broadcast receiver to listen for those intents. if the activity is paused, unregister your receiver, that way you won't respond when when you aren't in the foreground.
if the OS destroys your service, then it's killing the process, so your task is doomed anyway. the best you can do is restart it. anyway, this won't happen except in the most extreme conditions if you consider the above.
EDIT: summarizing some thoughts captured in the comments ... keeping a long running worker processe and automatically restarting it is almost always the wrong thing to do. mobile devices do not have the power source to make this feasible. the author stated this he has a special condition that negates this concern ... that would only be true if the device is connected to a power source almost always.
the android model is to provide a robust set of intents (notifications) to which your application can listen. these intents wake up your device / application when it's time to do something. your app should handle the notification, and then allow the device to go back to sleep immediately.
if there's no stock intent that maps to your event, you can use Google Cloud Messaging to wake up devices from a server. in other words, let the long-running processes run on the server, and wake up the device when required.
if you can do that, an alternative would be to use AlarmManager to wake up periodically and check some state. even if you did this frequently (e.g., every 5 minutes, which is also a no-no), it'd be much better than keeping the device awake always as is being suggested. also, make use of inexact wakeup intervals (see documentation linked above).

On Android how would I be able to execute some code for a few seconds after a user either quits or uses another app and then comes back?

Basically,
I need to for a queue collection to persist about for about 15 seconds after a user either shuts down the app or switches to another application and then, presumably, comes to the app.
I'm looking to either save the items in the queue or process in some other way the items during the 15 seconds that they persist.
Is this possible? Can anyone point me in the right direction?
This is my second android app and the first time I have to do this so any help would be appreciated.
You can use onResume() to run commands when they com back from another task.
As for running something X seconds after they quit the application, that would require to include a "service" in your application, which could be called by your task onStop()
Although it is possible for your activity to remain active in the background you should not depend on it, as different devices will be more or less agressive with resource reclamation.
Using a service is the only sure fire way to run something in the background while orhter applications run.
http://developer.android.com/reference/android/app/Activity.html
http://developer.android.com/guide/topics/fundamentals/services.html

Android Connect to Running Thread

I am creating an app that has a UIThread and a background thread. The background thread is basically being used as a timer - every second it sends a message to the UIThread to update the UI. When the user exits the app by hitting the backbutton, the thread continues to run. I want this to happen since the user may want to open another app while the timer continues to count down.
My question is when the user comes back to my app. I want to connect to that background thread that is running to display the current state of the app - how much time is left, etc. My question is how to hook back in to the thread that is still running in the background. I have tried using Thread and AsyncTask, but the same issue occurs.
Thanks for any help that you can provide.
Your thread is still turning by sheer chance - your application is in fact still running but it and the thread will be shut down when Android decides it needs the resources.
However what you want to do is well-provided for in Android - you need to implement a Service to have a process that runs in the background separately from your application. You can even have a Service start at boot and run whether or not your application is started.
This http://developer.android.com/reference/android/app/Service.html has most of what you need to know. To communicate between the Service and a foreground Activity you'll need to bind to a service interface, which is fortunately very easily done.
First thing that comes to mind is to change your timer thread to a Service and have apps interested in it bind to that service. Based on the Android documentation and suggested app design, you cannot depend on that thread to not be killed by the OS whenever it deems necessary.
http://developer.android.com/guide/topics/fundamentals/services.html
The android system provides a broadcast event every minute, it's call TIME_TICK.
You should:
Create a service. This is the recommended way to have a part of the app running in the background
Listen to the TIME_TICK event. This will consume less battery. (It won't wake the phone, though, so use an ALARM, too)
Add an alarm (to wake the phone if necessary)
Let the UI and the service interact. You need a callback via rpc (see the last callback example on the api page)
You should also ensure that the phone can sleep during the timeframe. You thus may want to compute the state as a delta between the starting point and now, instead of updating the state all the time.

Categories

Resources