4

Im fairly new to Android and have encountered a problem, which i would like to understand. The problem is that the java.util.concurrent.ScheduledExecutorService doesn't seem to issue its tasks while the display of my smartphone is off. I was using a java.util.Timer before which didn't have this issue, but was transitioning to ScheduledExecutorService because of the need to wait for the end of the task execution after stoping the Timer. The Timer is used in a Service running in the background.

Note: Using AlarmManager isn't an option, because i want to understand the problem with ScheduleExecutorService or else will use Timer again (synchronizing the shutdown).

Here is how the task is scheduled:

mScheduler = Executors.newSingleThreadScheduledExecutor();
mScheduler.scheduleAtFixedRate(mTask, 1, 1, TimeUnit.SECONDS);

To furher clarify the purpose: I am trying to update a Notification as well as parts of the User Interface periodically, this doesn't need to be done if the device wants to go into "sleep" mode, but i would need to handle this case. I think understanding why ScheduledExecutorService is behavoring the way it does compared to Timer will help me handle it.

UPDATE:

As recommended by Chris Stratton, i'm using a BroadcastReceiver to receive the Intent.ACTION_SCREEN_ON and Intent.ACTION_SCREEN_OFF Intents to pause/resume the ScheduledExecutorService, which works like a charm. However there seems to be another issue with the ScheduledExecutorService while having a phone call, the execution doesn't stop but seems to be throttled somehow. This is only the case if the screen is turned off due to the proximity sensor (no intents are received in this case either)...

atomicode
  • 581
  • 4
  • 11
  • 2
    This mechanism does not insure that the application processor stays out of sleep mode (or likely even that your process continues executing). AlarmManager will allow it to wake back up. A Wakelock would keep it awake, but that is unwise simply for a time delay as keeping it out of sleep mode wastes battery. So now that you understand the issue, switch your implementation to the proper mechanism integrated with Android power and process management. That mechanism is AlarmManager. – Chris Stratton Feb 20 '14 at 18:16
  • Why are you doing something every second continuously in the background? Why would doing this while the screen is off be in the users' best interests? – CommonsWare Feb 20 '14 at 18:23
  • @ChrisStratton It doesn't explain why it is working if i use a Timer instead of the ScheduledExecutorService, which is what i would like to understand. Also is there a way to be notified by the system that the device wants to go into "sleep"? – atomicode Feb 20 '14 at 18:50
  • There's no guarantee that the CPU will shut down during a given test. Neither method is intended to prevent that, so neither one is appropriate to your purposes. You are going to have to do something integrated with the Android power management, such as AlarmManager or (for very carefully considered purposes) a Wakelock. – Chris Stratton Feb 20 '14 at 18:52
  • @ChrisStratton: I don't want to keep the device awake if it wants to go into "sleep", neither do i want to issue a external "service" like AlarmManager with tasks which don't need to be executed when the device is "sleeping". Foremost i want to understand the behavior and how to deal with it, instead of circumventing it. – atomicode Feb 20 '14 at 19:01
  • The point is that you should not be assuming that any difference in observed behavior meaningfully results from the difference between these two approaches. **Anecdotes are not specifications**, and even actual influences can be indirect and variable under the influence of other unknown factors. – Chris Stratton Feb 20 '14 at 19:10
  • @ChrisStratton I'm not assuming anything, i want to understand the observed behavior because there is no obvious reason why it behaves the way it does. – atomicode Feb 20 '14 at 19:24
  • You are assuming that there is a meaningful connection. More likely it's a weak influence more heavily dependent on a lot of other factors not under consideration. – Chris Stratton Feb 20 '14 at 19:28
  • @ChrisStratton I really don't know what you are trying to tell me, but it doesn't help at all to say that things act the way they do because of unknown factors. I don't want to be rude, but i'm under the impression you're making these statements because you don't know the answer either. – atomicode Feb 20 '14 at 19:38
  • I don't believe there **is** an answer. Unspecified behavior should be expected to differ for **unpredictable** reasons. Do you have **any documentary evidence at all** that these two mechanisms are **specified** to yield a different result? – Chris Stratton Feb 20 '14 at 19:42
  • @ChrisStratton I'm sorry but i can't share your opinion at all. I don't have documentary evidence that these two mechanisms are specified to yield a different result, otherwise i wouldn't have asked, **but** ScheduledExecutorService is specified as a replacement for the Timer/TimerTask combination (as per javadocs), which should imply that the behavior is similar and the result is compatible. – atomicode Feb 20 '14 at 19:53
  • Yes, I expect the behavior is similar. What you are seeing **is not reliably related** to the choice of one vs. the other. – Chris Stratton Feb 20 '14 at 20:06
  • @ChrisStratton Not sure, but there are two differences which at least could be related: Timer is using Object.wait and is running in a single persistent Thread, whereas ScheduledExecutorService (ScheduledThreadPoolExecutor) is using ReentrantLock/Condition to (a)wait execution and a Thread out of a Thread-Pool (even if using Executors.newSingleThreadScheduledExecutor). – atomicode Feb 20 '14 at 21:04
  • Neither of those is able to reliably keep the CPU running. – Chris Stratton Feb 20 '14 at 21:26
  • @ChrisStratton I think you're right. This leaves me with two options: Either i can use a wakelock as suggested by Doctoror Drive, or i find a reliable way to be notified if the CPU is going into sleep state. I really don't want to use a wakelock, because it isn't necessary for the purpose of my application to keep the CPU from sleeping while updating UI the user can't see if the screen is off. – atomicode Feb 20 '14 at 21:32
  • What if you subscribe to the screen on and off broadcasts and not update if the screen is off, until you see it turn on again? http://stackoverflow.com/questions/9477922/android-broadcast-receiver-for-screen-on-and-screen-off An unnecessary update when the screen is off shouldn't be a big deal, especially if it only happens once as a result of not having cancelled your periodic updates when the screen went off, but only declining to then schedule any more. – Chris Stratton Feb 20 '14 at 21:51
  • @ChrisStratton Yes, this is it. I will register the BroadcastReceiver in my Service and let the BroadcastReceiver tell the Service if the screen is on/off, which in turn will suspend/resume the update of the UI. Thank you for taking the time to discuss the problem, even if the original question remains unanswered. – atomicode Feb 20 '14 at 21:55

1 Answers1

1

When the screen is off, if no other applications are holding WakeLock, the CPU suspends.

You should use a PARTIAL WakeLock whenever you need something done while screen is off.

And make sure you release it as soon as you've done all the ackground job.

Yaroslav Mytkalyk
  • 16,950
  • 10
  • 72
  • 99
  • Technically yes, but this is likely to be rather wasteful of battery. One really shouldn't try to do things with high frequency in the background, but rather do low frequency things with AlarmManager or similar. – Chris Stratton Feb 20 '14 at 18:51
  • @Chris Stratton it depends on what atomicode is trying to achieve. If his code is experimental and his intentions are to investigate the behaviour then it's okay to try it with WakeLock. His code doesn't look like something for production anyway. – Yaroslav Mytkalyk Feb 20 '14 at 18:54
  • I don't think using a WakeLock is a good idea, i don't want to prevent the CPU from suspending. Im just wondering why it isn't doing so when using a Timer instead of a ScheduledExecutorService? Also another option would be to handle the suspend, but i don't know if it is possible to get notified if the system wants to go into "sleep"... – atomicode Feb 20 '14 at 18:54
  • @ChrisStratton: As i've stated in my question im learning and want to understand why thinks work the way they do in android. There doesn't seem to be an obvious reason why the behavior is different comparing Timer and ScheduledExecutorService. – atomicode Feb 20 '14 at 18:56
  • @atomicode you will know notified that the system can go to sleep whenever the last of your Activities are in stopped state. Anyway, in Android you don't need to know whether it goes down or not. You either do something and keep it running, or do something only when the user sees it, or do something based on events. – Yaroslav Mytkalyk Feb 20 '14 at 19:00
  • @atomicode - the behavior **is not necessarily different**. Even though you may observe different results in your testing right now, there are many things which can keep the CPU awake, but **neither** of these can be relied on to do so. So neither (by itself) is a proper solution for you. – Chris Stratton Feb 20 '14 at 19:01
  • I've added a clarification in the original question. I hope it helps understand my problem. The updating of the User Interface of the Activity is not a problem, because im able to handle it if the Activity gets paused or is destroyed by the system, but this isn't the case with the notification. The notification will and should be there as long as the service is running, but may not need to be updated if the device is "sleeping". – atomicode Feb 20 '14 at 19:09
  • @atomicode notifications should not normally be updated this often. It should be updated once a state change. – Yaroslav Mytkalyk Feb 21 '14 at 08:51
  • 1
    @DoctororDrive The state changes every second, the notification shows the time as well as the progress of a countdown. I'm using a BroadcastReceiver (as suggested by ChrisStratton) to receive ACTION_SCREEN_ON/ACTION_SCREEN_OFF intents to resume/suspend the update of the notification as well as the update of the activity if it is running. Though i'm still wondering why ScheduledExecutorService behaves different than Timer in that situation, even if it isn't a reliable behavior. – atomicode Feb 21 '14 at 16:22