I am bit confused after going through the questions & answers in Stackoverflow about WakefulIntentService. I just would like to get some knowledge on this topics to make sure my understanding is correct, please feel free to correct me, if I am wrong.
I built a small application, where I am using a background Service that keeps playing music whenever the user shakes the mobile. I tested after the device is locked and screen is turned off and it works as expected.
What I am hearing from this forum, the service might turn off as soon the device goes to asleep. Is that true? In my case, it works always, Am I missing something?
What is the need of WakeFulIntentService? When do we need to use WakefulIntentService?
I tried running a timer in a Service, though the device is locked and screen is turned off and my timer is running pretty much I can say for sure. Because I used to get notification whenever my timer trips.
What I am hearing from this forum, the service might turn off as soon the device goes to asleep. Is that true?
Yes.
In my case, it works always
Then something else on your device is keeping the device from falling asleep. Perhaps use adb shell dumpsys power to see what WakeLocks are outstanding.
What is the need of WakeFulIntent Service? When do we need to use WakefulIntentService?
The device may fall asleep if the user is inactive and nothing is keeping the device awake. A WakeLock is used to ensure the device stays awake. For transactional-type work (e.g., downloading a file), WakefulIntentService combines an IntentService and a WakeLock to make keeping the device awake as long as necessary (and only as long as necessary) relatively easy.
WakefulIntentService is not suitable for use with services that need to run indefinitely, such as a music player. For those, manage your own WakeLock.
I used the code below in an app.
Make sure your service is sticky:
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
//this service will run until we stop it
return START_STICKY;
}
I you want your phone to be awake constantly u can use this code below:
private WakeLock wl;
PowerManager pm = (PowerManager)getSystemService(Context.POWER_SERVICE);
wl = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, "whatever");
wl.acquire();
Don't forget the permissions in your manifest.
<uses-permission android:name="android.permission.WAKE_LOCK" />
Related
I have built an online clock radio for Android which also features an integrated music player that works as a foreground service with notification, and it has its own wakelocks - acquiring when service is started and releasing when the user presses "stop" and finishes the service.
Now I get a warning about hanging partial wakelocks for this app in Google Developer Console. It's absolutely correct to receive this warning, because if someone keeps listening to music for a longer period of time, then also the wakelocks (wifi-manager and power-manager) will be held as long as needed to keep the music playing when the screen is off.
The app works perfectly and plays for hours when the screen is off and/or in power save mode - exactly as intended.
Also:
In Developer Guidelines and best practices they state:
If you must use partial wake locks, follow these recommendations:
Make sure some portion of your app remains in the foreground. For
example, if you need to run a service, start a foreground service
instead. This visually indicates to the user that your app is still
running.
Make sure the logic for acquiring and releasing wake locks is as simple as possible. When your wake lock logic is tied to complex state
machines, timeouts, executor pools, and/or callback events, any subtle
bug in that logic can cause the wake lock to be held longer than
expected. These bugs are difficult to diagnose and debug.
I think I have taken care of this.
They tell me in dev console where the warning appears:
Keep in mind that for some apps, longer wakelocks are required to enable key features such as music streaming.
Due to that I believe everything is fine, but since the warning for "bad behavior" is still shown I would like to get advice.
The questions are:
Can I do anything to avoid getting this warning?
Will I have to fear "punishment" by Google for my app showing "bad behavior" although it's working correctly?
Streaming-service (partial) code:
#Override
public void onCreate() {
...
// WAKE LOCK && WIFI LOCK
powerManager = (PowerManager) getApplicationContext().getSystemService(POWER_SERVICE);
wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "MyWakelockTag");
wakeLock.acquire();
wMgr = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
wifiLock = wMgr.createWifiLock(WifiManager.WIFI_MODE_FULL, "MyWifiLock");
wifiLock.acquire();
...
// notification gets built
...
startForeground(ntfctnId, buildNotification(standardNoti));
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// player here...
...
#Override
public void onDestroy() {
...
// RELEASE WAKE LOCK && WIFI LOCK
wakeLock.release();
wifiLock.release();
...
I have not noticed anything negative - neither from Google, nor users, nor anything or anyone else.
Everything is just fine. If wakelocks cannot be avoided - and that's clearly the case for music apps - you do not need to fear any related warnings about this in the Developer Console.
I set the alarm like this:
registerReceiver(wakeUpReceiver, new IntentFilter("com.example.yay"));
pi = PendingIntent.getBroadcast(getApplicationContext(), 0, new Intent("com.example.yay"), 0);
am = (AlarmManager)(getSystemService(Context.ALARM_SERVICE));
if (android.os.Build.VERSION.SDK_INT>=android.os.Build.VERSION_CODES.KITKAT) {
am.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime()+30*1000, pi);
} else {
am.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime()+30*1000, pi);
}
And it works if the device is awake, but if I turn off the screen, it doesn't turn on the screen (but wakeUpReceiver's onReceive() gets called)
What do I need to put in the manifest? AlarmManager docs don't seem to mention anything relevant to permissions or intent filter or anything like that. Maybe I'm just misunderstanding the docs as usual?
And yes, I've read all the other similar questions, but they're not helping.
You can use Wakelock to achieve this:
Different Levels Wake Locks:
FULL_WAKE_LOCK - Keep the screen at full brightness, keyboard
back-light illuminated, and the CPU running. SCREEN_BRIGHT_WAKE_LOCK -
Keeps the screen at full brightness and the CPU running.
SCREEN_DIM_WAKE_LOCK - Keeps the screen ON but lets it dim and the CPU
running. PARTIAL_WAKE_LOCK - Keeps the CPU running
Android permission for Wakelock:
Since wake locks has huge impact on battery life your application needs to request WAKE_LOCK permission in order to create them.
Create Wake Locks
To create a wake lock call newWakeLock on the Power manger as follows:
PowerManager.WakeLock wakeLock ;
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
wakeLock = pm.newWakeLock( PowerManager.SCREEN_DIM_WAKE_LOCK, "My wakelook");
Release Wake lock
wakeLock.release();
Its very important to release wakelock or else it will drain the battery.
As answered above use wakelock create WakeLock in onReceive().
Or I suggest you to use WakefulBroadcastReceiver.
This will make sure that ur phone is awake during service.
WakefulBroadcastReceiver is the best option for the 2nd thing, about wakelocks - u can check on google some examples that show how to use alarm manager with wakelocks.
Ofc, ur service can done it's work, but sometimes sleep can occour, so I suggest you to implement it even if ur tests don't show the problem, better too keep it safe.
Are you sure onReceive() being called? Create some logs and do some tests. For now there can be 2 problems: or sleep is not calling onReceive() (here check the power managment options on your phone, I had problem with "Stamina" on my phone, which was blocking my alarms) or your phone is falling asleep before u do your work (then wakelocks/WakefulBroadcastReceiver).
Also AlarmManager will not "light up" ur screen, only CPU.
To turn on the screen use getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
or android:keepScreenOn="true" in layout.
The method suggested by another user SCREEN_DIM_WAKE_LOCK was deprecated in API level 17, keep it in mind!
For more:
https://developer.android.com/training/scheduling/wakelock.html
Envrionment: Eclipse
Language: Java (Android)
I have a bit of a problem, which I didn't realise until I tested my application out on a device. I always thought that services would continuously be running in the background, even when the phone's sleeping. I found out that this is not the case, so, my question is that does the service start up again once you wake your device up? And if not, how would I cause the service to start-up again.
Would I be able to wake the phone every 5 minutes or so, just to run my service, which will last 30 seconds to 1 minute. And then make the phone sleep again?
Thanks in advance.
EDIT: I am very new to Android programming and would really appreciate if someone would tell me how to use WakefulIntentService.
I have a service that is searching for the user's GPS Location every so often, and when the phone goes to sleep, I want my service to still look for their location. How would I go about using the WakefulIntentService for this? And would I be able to use it in this scenario.
Thanks.
You need to hold the processor lock to keep your service running
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "TAG");
wl.acquire();
// When you are done
wl.release();
And if your service is using Wi-Fi, you need another lock as well
WifiManager wm = (WifiManager) getSystemService(Context.WIFI_SERVICE);
wifiLock= wm.createWifiLock(WifiManager.WIFI_MODE_FULL, "TAG");
wifiLock.acquire();
// When you are done
wifiLock.release();
Remember to add android.permission.WAKE_LOCK in your manifest
I have a service that is searching for the user's GPS Location every so often, and when the phone goes to sleep, I want my service to still look for their location. How would I go about using the WakefulIntentService for this? And would I be able to use it in this scenario.
WakefulIntentService is inappropriate here, as it is designed only to keep the device awake for a short period of time to do some work. It is not designed to keep the device awake for an indeterminate time, such as the time it takes to get a GPS fix.
I have a LocationPoller project that handles your scenario a bit better.
I am very new to Android programming
What you are trying to do is not a suitable project for somebody with your Android experience level, IMHO.
I don't know what your service is doing exactly, but if it's down/uploading data to a server you might want to consider using a Sync Adapter.
Unless you need exact timing this is less of a burden on your system than AlarmManager.
I you are doing something else, you might want to look into the JobScheduler API.
Anyway if you really want to stick to AlarmManager just know that Inexact Repeating is already a lot better than Exact Repeating.
I used AlarmManager, I looked at WakefulIntentService and that gave me an idea on what to do.
Thanks again for the help everyone.
I am recording sensor data such as Accelerometer, Orientation, Gyroscope. This data writes to a file onSensorChanged update every so often.
My problem is when I put the phone into standby that the sensor data stops writing to file. So I done some research and decided to set it up using PowerManager and using the wake lock
PARTIAL_WAKE_LOCK: I just can't get it working.
SCREEN_DIM_WAKE_LOCK: My code will work grand.
From what I read up on there seems to be a problem with using PARTIAL_WAKE_LOCK.
I can't seem to find a definite answer on whether or not there is a problem with it still or there isn't. I even tried some of the hack approaches people have suggested such as using an itent to capture when screen is off and then unregistering the sensors and registering them again. But this solution didn't work. From what I can gather it seems inconsistant if it will work or not and seems phone dependant. I have tried my code on both a HTC Wildfire running Android2.2 and Nexus S running Android2.3.
My application is an app that is basically ran in the background with a long running service. So having PARTIAL_WAKE_LOCK is important with battery life.
This is only defined to work as of Android 2.3. Prior to that the platform would explicitly turn off all sensors when the screen turns off in order to reduce battery use.
This is a pretty old question, I'll still answer it as pretty much all the devices today are beyond 2.3
Create a background service and use the Partial Lock Wake in the following manner:
First take care of the permissions (in the manifest file):
<uses-permission android:name="android.permission.WAKE_LOCK" />
Then, most preferably use this in the Application file, or wherever:
PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
PowerManager.WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
"MyWakelockTag");
if(/*condition*/) {
wakeLock.acquire(); //keep CPU awake
} else {
wakeLock.release(); //disable keep CPU awake
}
Although it is a pretty cool feature, it drains your battery life, hence use it responsibly.
When the screen turns off, my application service is paused.
I start my service with the following code:
if (mSharedPrefs.getBoolean("prefAutoUpdatesMain", false)) {
Intent svc = new Intent(this, MyService.class);
startService(svc);
}
How can I can avoid the service pause?
What I have to do in MyService is to download some data from Internet. If I have understand the process I have to follow is:
Acquire wakeLock
Download data
Release wakeLock
In downloading data method there are no reference to wakeLock, it is the application to have the wakeLock, is it correct?
Wake locks are reference counted by default. I think it is better a wakeLock without reference counting, to be sure to release it, am I wrong?
A partial WakeLock is what you want. It will hold the CPU open, even if the screen is off.
To acquire:
PowerManager mgr = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
WakeLock wakeLock = mgr.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "MyWakeLock");
wakeLock.acquire();
To release:
wakeLock.release();
WakeLock also supports reference counting so you may have multiple things in your service that require wake functionality, and the device can sleep when none of them are active.
Things to watch out for:
If you use reference counting, make sure all control paths through your application will properly acquire/release...finally blocks come in handy here.
Also be sure to hold WakeLocks infrequently and for short periods of time. They add up in terms of battery use. Acquire your lock, do your business, and release as soon as possible.
You need a partial wake lock.
Detailed example here in a previous question:
Wake locks android service recurring
I'm just using a foregrgound service.