Trying to understand if I need WakeLock - java

Disclaimer: My app already working without any Wake Locks for 1+ year and all is well for most devices.
I'm tracking GPS and it works like this:
AlarmReceiver starts Service every 5/10/15 minutes (as user wishes)
Service subscribes for Location updates and waits MAX 1 minute for good GPS.
Wrap up, send data to server and shut down service.
Due to bad connections and bad locations - whole thing take up to 2-3 minutes sometimes. And it works. No matter if phone is sleeping or not.
Now I'm reading about WakeLock and it doesn't make sense to me. How come my stuff is working? Is that coincidence?

How come my stuff is working?
A combination of things, including a dollop of luck. :-)
First, as Joel noted, the device wakes up briefly courtesy of your alarm, but the OS is only guaranteed to hold a WakeLock for the duration of onReceive() of a BroadcastReceiver.
It is possible that, at least on some versions of Android, requesting GPS updates causes the OS to acquire its own WakeLock. This is undocumented behavior AFAIK, and I have never relied upon it personally. If it does, though, and you are doing the rest of your work ("Wrap up, send data to server and shut down service") before removing location updates, that would explain the behavior.
There are still potential gaps in your approach (e.g., if you delegate to a Service to do the work and are not holding a WakeLock as part of passing control to that service). Statistically speaking, it may fail occasionally but work a lot of the time.
Personally, I recommend using a WakeLock, in case the undocumented behavior changes. That's what I do in LocationPoller.

Well reading from the AlarmManager documentation..
The Alarm Manager holds a CPU wake lock as long as the alarm
receiver's onReceive() method is executing.
Further...
Note: The Alarm Manager is intended for cases where you want to have
your application code run at a specific time, even if your application
is not currently running. For normal timing operations (ticks,
timeouts, etc) it is easier and much more efficient to use Handler.
So based on that.. I think it makes sense that it currently works; correct me if I'm wrong.

Related

Run a TimerTask or a Handler ALWAYS correctly

I have a problem (that's why I'm here :P):
I am running a TimerTask and/or a Handler. They should do something every second, no matter if the screen is on or not (standby). The problem is, after some time (2 to 10 hours) this process becomes weird timed. Sometimes it takes 10 seconds, sometimes 4 hours etc.
Now, I've read that you can use a Partial Wake Lock to solve this issue. Tried it, but it has not solved my issue (Maybe you should know that another library is also using a WakeLock which gets released after some time, but mine never gets released by me).
Maybe you should also know that the task/runnable runs on an asynctask (so on it's own thread). The wakelock is created from outside.
Edit:
Maybe it's good to know that it's a device owner app. Also, I know of the battery drain problem, but I still need it. The app really has to process this every second. I just need a solution for it, any, no matter which.
Edit 2:
Here's my current WakeLock code, which is started when my custom application reaches onCreate. As I said, it is never released.:
PowerManager mgr = (PowerManager)getApplicationContext().getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wakeLock = mgr.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,"CustomWakeLock");
wakeLock.acquire();

Run a clock or timer even when app closes - Android

Ever played Candy Crush? Know how you run out of lives and have to wait 30 minutes to regenerate a new life and up to a maximum of 5? That is idea I am trying to implement in my app but I am uncertain on how to have code running even when the user closes app and/or phone.
My question is how to have a timer constantly running in the background of phone until the timer hits X minutes. Would I use the Timer class for this? Because I am familiar with that class and already have a form of it implemented in my app.
There are two pieces to your question:
To actually have a timer running so that you have an action taken after a certain period of time, use the AlarmManager. This should only be used if you are going to proactively interrupt or notify the user.
Your scenario doesn't actually need a timer, and it's more efficient not to use one unnecessarily. Instead, store a timestamp. When your app is opened again, compare the current time to the timestamp and calculate the effect. In the regenerating-lives example, you'd compare timestamps, see that 100 minutes have passed, divide by 30 minutes, and add 3 lives (maybe keeping the extra 10 minute remainder).
If you want timer to run in background you may use AlarmManager. You can set Alarm at specified intervals or you can set it in service if you want single shot alarms. Also while using AlarmManager beware that if your phone goes down then all alarms you've set will be vanished. So take care that you are saving alarm times before phone goes off. Take a look at:
http://developer.android.com/reference/android/app/AlarmManager.html
While using AlarmManager, use correct PendingIntent flags or you could lose previous alarms. If you still want more information you can raise here or have a google.
I don't think you can keep a timer running for you application even when the application is closed. Here is an idea i think about:
You need to start a timer when the life is gone and your application is running.
On your application close event, save that timer value in a persistent storage such as file
On appliction start, read the timer value from the persistent storage, and restart the timer for the remaining time
Once timer expires, generate a new life.
Hope it helps!
I found this answer that might be of great help. Hope it helps others.
There are several different approaches.
You can make use of the System's AlarmManager.
You can make your own Service.
You can make your TimerObject persist.
Check the link for the complete answer and links.

Android: ACTION_TIME_TICK in AppWidget

I've got a clock in my widget that I'm making and I want it to update every minute in sync with the system clock. ACTION_TIME_TICK seems like the perfect solution however much of my research says it's impossible in an AppWidget while others say there are workarounds but their very vague.
I'd prefer not to do an AlarmManager as I'd have to update very frequently to make sure that it changes minutes when the system clock changes minutes and that would drain the battery more.
Is there a workaround for ACTION_TIME_TICK or what's the best way to update every minute in sync with the system clock with minimal battery drain?
Is there a workaround for ACTION_TIME_TICK
ACTION_TIME_TICK can only be registered via registerReceiver() from something that is already running. In your case, that "something" would need to be a constantly-running Service, and that's generally an anti-pattern. Users and the OS can get rid of that service when desired.
I would find a way to lightly relax the "in sync with the system clock" requirement, then use AlarmManager. After all, Android is not a RTOS, so nothing will be "in sync with the system clock" in any guaranteed sense.
Using AlarmManager, you would specify the first alarm to be the "top" of the next minute, with a period of 60 seconds and setRepeating(). Or, you would set(), scheduled for the "top" of the next minute, then schedule the next one via set() as part of your own processing, if you think you can manually correct for drift better that way.
if you just need to display it when your app runs then just update it using asyncTask
but if you need it's value even in the background then using service would be the best idea

design patterns for persisting state on android app

For android I am trying persist state if onDestroy() is called. I'm wondering what are common design patterns used to do such a thing so that the actual app functionality is decoupled from the persistence functionality? For example, I have a for loop that iterates through all of the players in the game. This update happens at the end of each round in the game. Would it be possible that the app gets destroyed half way through the update? If that happened, what kind of logic would i need to include to remember which player was updated.
You have two main options for saving state. If you are concerned with instance variables, then override Activity.onSaveInstanceState The answer to this question provides a good sample of how to do this.
For persistent data, you can either store it in SharedPreferences, the SQLite database, or write it to a file. This article should help you get started: http://developer.android.com/reference/android/app/Activity.html#SavingPersistentState
Your app can be killed half way during the update if users switch to another app such as receiving a phone call.
Considering such cases, you may need to persist your state in onPause() instead of onDestroy() since onPause() is the last method which is guaranted to be called when your activity is killed by the system.
And in onPause(), you can start a background service to do the update which can give your process higher priority so that it's less likely to be killed by the system when you are doing the update.
See more details in the Activity lifecycle and the Process document.
Android is not very nice about killing apps. You may or may not get onPause or onDestory. You may or may not be able to receive a hook onShutdown of the VM. Basically your app can die at any time (low memory pressure), user kills it, or etc and you won't get any warning. Basically it is best practice to assume that you can die at ANY time and store or update critical state as soon as you get it.
Basically I would either make a SQLitedatabase or use shared preferences for this.

Android app components - a word of advice needed

I am a complete newbie to Android development;
Basically, I am about to write an application, that will let the user to take photo, which (with a bunch of extra data) will be submitted to the remote webservice.
So I'm guessing I will need:
A Photo-taking application (Activity) that will gather all the extra data and put in the SQLite DB.
A background service looking up the DB in time intervals and sending the data over the Internet, optionally making web requests with current GPS location (I'm trying to keep in mind, that sometimes network would not be accessible).
A receiver object that will run the service at boot, and optionally check if the service needs to be restarted.
My concerns are:
Do I really need to monitor the service and care about anything bad that could kill it.
Will the battery last for at least 12 hours with a non-stop running service, making some networking/GPS actions in, let's say, 30-minute intervals. (G1/Dream)
What else should I be careful about?
Any ideas/suggestions will be appreciated.
a word of advice needed
Rutabaga.
Oh, wait. You're probably looking for something related to Android. OK, carry on.
A receiver object that will run the
service at boot, and optionally check
if the service needs to be restarted.
Yuck. Use AlarmManager and have your service behave more like a cron job/Windows scheduled task.
Do I really need to monitor the
service and care about anything bad
that could kill it.
Not if you use AlarmManager and have your service behave more like a cron job.
Will the battery last for at least 12
hours with a non-stop running service,
making some networking/GPS actions in,
let's say, 30-minute intervals.
(G1/Dream)
If you use AlarmManager and have your service behave more like a cron job, a 30-minute interval should be OK. Just make sure you shut down the GPS radio when you are done with it. Note that using the GPS radio from a cron job sort of task is a bit tricky, since it takes a while to get its first fix. You will also want to take a look at using PowerManager.WakeLock to keep the device awake until your work is completed.
What else should I be careful about?
Mynd you, moose bites kan be pretti nasti.
Beyond that and what I wrote above, you should be in OK shape. Note that what you are diving into is not exactly "newbie" material.

Categories