Running a timer regardless if the activity is active or not - android

Ive created a timer which counts down and when it reaches 3 it starts vibrating stronger and stronger until at 0 it vibrates fully.
My problem is that if the user turns off the screen the timer becomes unstable, i.e. counting down unpredictably or not at all. After searching around for a while I found that the solution probably is to use the AlarmManager, however this seems very complex for such a simple task.
The timer should be tied to the activity and if set, a notification indicating the time left should also be fired.
Any ideas?

There are a few options that you could consider to do what you're asking, and each one woudl depend on your specific circumstance and what you really want to achieve. A Service, an IntentService (Service subclass), AlarmManager, or a (partial) WakeLock (and maybe some more creative solutions that I'm missing).
I think the easiest thing out of the gate is to use a Partial WakeLock. It's dead simple, and is useful if you want a process to run in your activity even when the screen is off. You have to use it sparingly though, as it will chew up battery life (which is why activities pause when the screen is off).
To use a WakeLock:
Add the permission in your manifest:
<uses-permission android:name="android.permission.WAKE_LOCK" />
In your activity, start the WakeLock when you need it
PowerManager mgr = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
WakeLock wakeLock = mgr.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "WakeLockTag");
wakeLock.acquire();
When you're done with the wakelock (i.e. don't need to run the process any more), release it:
wakeLock.release();

It's clear that timer will be unstable if you implement it in activity. It results from lifecycle of activity. Main activity element it's GUI thread which is not the best place to implements logical elements.
You should use alarm manager or implement your own service to manage action which will properly work in the background. You have problem because when you switch your screen of your app is paused and until you'll restart it you haven't full control about the action inside activity.
I'm a fan of programming using brain, so I give advices, not clear code. But I hope that it will help.

Related

Broadcast receiver vs activity with alarmmanager

I am using broadcast receiver with AlarmManager, but sometimes it takes lot of seconds to wake up, which causes issue in app functionality
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "");
wl.acquire();
and releases after launching activity
I am thinking to change it.
Can you tell what is the best approach?
use broadcast receiver to perform some calculations, and then starts activity (wake lock problem so far in my case).
Start Activity directly, and do calculations weather to continue this activity or terminate before setting content view
I am using broadcast receiver with AlarmManager, but sometimes it takes lot of seconds to wake up, which causes issue in app functionality
I am not aware that any other sort of component will somehow start up faster than a BroadcastReceiver. Certainly I would expect an activity to start up more slowly than does a BroadcastReceiver.
and releases after launching activity
The WakeLock is doing you no good, as there already is a WakeLock in place for the duration of your onReceive() call (assuming that this is a manifest-registered BroadcastReceiver).
The only way this WakeLock will be useful is if you release it from onCreate() of the activity, to try to keep the device awake long enough for the activity to start up.
Can you tell what is the best approach?
That depends on what the "calculations" are. onReceive() is called on the main application thread. Like all methods called on the main application thread, you want onReceive() to return in a couple of milliseconds. If your "calculations" will definitely take only a couple of milliseconds, stick with the BroadcastReceiver. If the "calculations" will take longer than that, you will want to consider delegating that work to an IntentService, and have the IntentService start the activity if needed.
With respect to the "lot of seconds", bear in mind that your AlarmManager events may be inexact, depending on what method you use to set them up, what your targetSdkVersion is, and what version of Android you are running on.

How to keep the application running without using partial wakelock

I have a single started service in my application which keeps my application alive.
I am downloading the data in a thread in my application(may take from 1 minute from 30 minute).
I want my application not to go in sleep state. I dont want to use the PARTIAL_WAKELOCK mechanism to keep the battery life long.
Here, The intention of having some PARTIAL_WAKELOCK like functionality not because of the service,
I want it just for few threads(tasks).
Can AlarmManager help?
I want my application not to go in sleep state.
Then use a WakeLock.
I dont want to use the PARTIAL_WAKELOCK mechanism to keep the battery life long.
You do not have a choice.
Here, The intention of having some PARTIAL_WAKELOCK like functionality not because of the service, I want it just for few threads(tasks).
A WakeLock does not affect a service. It does not affect a "few threads". It affects the device's CPU. The CPU is what goes to sleep, not your service, and not your threads. If you do not want the CPU to go to sleep, you must use a WakeLock.

Will a Handler postDelayed not being fired when CPU sleeps?

I have an activity with some Handlers that are being executed at intervals no more than 5 minutes. The activity is launched from a BroadcastReceiver and may be launched with the screen off waiting for the user to grab the phone and get the user input, when this happens, the activity onPause() is called so for sure CPU is in sleep mode. I have not set the activity to turn screen on because I want to save as much battery as possible.
I've tested it with my phone and works really well, while screen is off all Handlers execute all the code they have to run. If I turn the screen on and off while the activity is open everything works fine.
Now, I've read everywhere that some devices does not work as expected when screen goes off and CPU sleeps, most of the times with accelerometers. Now my question is, do I need to acquire a WakeLock so the CPU does not sleep while my activity is open? I really want to know this because, as I said before, I don't want to 'waste' battery by acquiring an expensive WakeLock.
I would prefer a detailed answer of a person that really knows how this works.
Your goal cannot be stably achieved by your approach. If you use an Handler's postDelayed() method and the CPU goes to deepsleep, the ms counter will stop and will only continue if the CPU wakes up again.
See this for more detail.
So if you want to have some kind of a cron job you will need to use wakelock.
Fortunately there is a Service implementation that does exactly that: Wakeful IntentService
From the doc:
The recommended pattern for Android's equivalent to cron jobs and Windows scheduled tasks is to use AlarmManager. This works well when coupled with an IntentService, as the service will do its work on a background thread and shut down when there is no more work to do. There's one small problem: IntentService does nothing to keep the device awake. If the alarm was a WAKEUP variant, the phone will only stay awake on its own while the BroadcastReceiver handling the alarm is in its onReceive() method. Otherwise, the phone may fall back asleep. WakefulIntentService attempts to combat this by combining the ease of IntentService with a partial WakeLock.

Android: Running service in background forever

I don't know why, but my Service ( started with startService(Intent...) ) keeps closing after a while. I want my Service to check every 2 minutes the position with WiFiSLAM, therefore a TimerTask is running in the Service. I realized that my Service is shutting down after the App is closed (onDestroy) and the screen turned off.
I've read about the WakeLock and tried this:
final PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
WakeLock wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
wakeLock.acquire();
But it still does not work. I don't know what to do. I just want to have my Wifi Positioning Framework to update the position in the background every two minutes.
I also set the return value of onStartCommand() to START_STICKY. Maybe it is running in the background, but I can't see the Logs in the LogCat when it is running for a while, which gives me signals that the indoorLocationManager is still catching new positions.
Someone has an idea?
Android automatically kills applications running in background for long periods (between 30 minutes and 1 hour).
The only way to prevent this is setting your service as foreground service.
To do that, you use the following:
startForeground(messgae, notification);
This will show a permanente notification informing the user that your service is running.
Other option, is to use AlarmManager to start an IntentService every 2 minutes.
Regards.
I have in the past had the ame problem, and you may not want to do this, however it does work for me. I set up 2 Services, the main worker, and a helper. The helper, every so often will make sure the worker is running, and the worker will ensure that the helper stays running. In this example, if one of them happens to get killed by the system, it will be relaunched by the other. I have never had both of them die at the same time.
Again, this is my solution that may not be something that you would like to do.
One solution is to use an alarm that launches you service at two minute intervals, or whatever you decide. However doing this will drain the battery, so keep that in mind.

Screen on and then off too fast when using WakeLock (not remaining on for a few second)

I'm facing a problem using Wake lock through PowerManager API.
Currently, i have a service and a broadcast receiver.
My service has 2 main roles :
First one, it creates an alarm at a specific time (my receiver receives the boot completed intent from system and start the service to create the next alarm)
Second one, the receiver reacts to the alarm (in RTC_WAKEUP mode) and start the service to play a notification by turning on the screen.
I'm using Mark murphy's cwac-wakeful module to achieve that and it works just fine.
The problem is : the screen turns on and off too fast for the user to see it.
Here is what's happening when the alarm intent is launched (for the second role/case) :
OnReceive method of Broadcast receiver is called
It calls WakefulIntentService.sendWakefulWork
My wakeLock is acquired (with SCREEN_DIM_WAKE_LOCK | ACQUIRE_CAUSES_WAKEUP | ON_AFTER_RELEASE flags)
Screen is turned on
The service is launched : The notifications is created and displayed
Service finishes
Wake lock is released
Screen is turned off immediatly (not on after release for a few seconds)
As you have probably understood. The problem is, the lock is released too fast after the service finishes so i can just see the screen turning on and off in less that one second.
I thought that using the ON_AFTER_RELEASE (the doc says : "If this flag is set, the user activity timer will be reset when the WakeLock is released, causing the illumination to remain on a bit longer. This can be used to reduce flicker if you are cycling between wake lock conditions. ") would have solved my problem, but no.
When googling, i found a solution that consists in :
Not releasing the wake lock just
after the service finishes but
launching another alarm in the next
15/20sec (from when service finishes)
that would release the wakelock (via
receiver/service) and turn off the
screen. I don't know if it'a good
solution and it seems complicated to
me for this use case
Then my question is how can i maintain the screen on for a few seconds (say 10/15 sec) like when i receive an sms, what is the best solution to achieve that ?
Any help would be greatly appreciated, and thanks in advance !
I had a similar situation in that my app was shutting down immediately after I released a WakeLock. I think I applied the same logic to it that you did, but I used a FULL_WAKE_LOCK with the other options PowerManager.ACQUIRE_CAUSES_WAKEUP | PowerManager.ON_AFTER_RELEASE. This seemed to do the trick for me in my "GameTime" timer application. I know this was posted a while a ago, but maybe it would provide some help to someone!
There is a line in API documentation that states:
"In addition, you can add two more flags, which affect behavior of the screen only. These flags have no effect when combined with a PARTIAL_WAKE_LOCK." I wonder if SCREEN_DIM_WAKE_LOCK counts as a PARTIAL WAKE LOCK? (undocumented 'feature')
API located here: http://developer.android.com/reference/android/os/PowerManager.html
I think you provide the answer:
Don't release the wake lock
Set a new alarm to occur 10/15 seconds later
Release the wake lock when the second alarm is triggered

Categories

Resources