How to keep an Activity running/active when the screen shuts off?
You will need to use a PARTIAL_WAKE_LOCK to ensure that your activity is kept active. android.permission.WAKE_LOCK must be requested in your manifest. However, battery will drain faster, so do remember to release the wakelock as soon as possible.
Alternately, use a Service instead
In the onCreate of your Activity, put the following lines:
Context mContext = getApplicationContext();
PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
final PowerManager.WakeLock wakeLock = powerManager.newWakeLock(PARTIAL_WAKE_LOCK,"motionDetection:keepAwake");
wakeLock.acquire();
//Place this where you no longer need to have the processor running
wakeLock.release();
After you press the power button, the activity should still run if that's where you closed it.
If you were like me, and you were collecting accelerometer data, be sure to remove the default sensorManager.unregisterListener(this); from the onPause part of the app.
There is also a good way.
I found this some months ago and it save a little bit the battery life ;)
http://thinkandroid.wordpress.com/2010/01/24/handling-screen-off-and-screen-on-intents/
Be sure you don't have ' android:noHistory="true" ' in your manifest file for any of the activities. It kills the activity when the app goes off the screen or screen shuts off.
If you want your app stay active even if the screen is off I don't think you need to do anything extra: My application doesn't have any extra code for it and when I turn the screen off and on it is still there. But! Android OS probably kills it after a while when the screen is off, so you should probably use WAKE_LOCK in your manifest file. Or you can add ' android:keepScreenOn="true" ' to the manifest file to keep the screen ON all the time when your app is running.
Related
I develop a small app, this one have to run always over all when the device is sleep or deep sleep (press right button to turn off the screen) I read many posts about it, and all tell me that the way is use PowerManager, and my question is if I use fine this command, my structure is> myActivity.class, ReceiverBoot.class and ServiceBoot.class, I use the POwerManager class on myActivity.class like this:
PowerManager mgr = (PowerManager)this.getSystemService(Context.POWER_SERVICE);
PowerManager wakeLock = mgr.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP , "MyWakeLock");
on onCreateMethod after of this one put
wakeLock.acquire();
and after of this one I have a
super.onCreate(savedInstanceState);
this.mTimer.scheduleAtFixedRate(
new TimerTask(){
#Override
public void run(){doTask();}
} , 0, 1000);
wakeLock.release();
on Manifest XML code I have
<uses-permission android:name="android.permission.WAKE_LOCK" />
and on layout XML code have
android:keepScreenOn="true"
but after to 10seg the creen es OFF always but the app is running, jut with wifi.
the app work very fine with wifi conn, but when change to 3G conn, the app is gone, I use fine this command?? the problem is the kind of conn to Internet??? thanks a lot!
I'm not 100% clear on your issue. Whether its the data issue, or the screen issue. (Or if the screen issue is what you are doing to try and fix the data issue?).
For the screen
You are not using the right lock to keep the screen on. PARTIAL_WAKE_LOCK only requests that you can use the processor. To keep the screen on your app use one of SCREEN_DIM_WAKE_LOCK, SCREEN_BRIGHT_WAKE_LOCK or FULL_WAKE_LOCK depending on what you want. This lock should be held for as long as you need the lock. Currently you are releasing it in onCreate(). Keep in mind that if the user presses the power button though that your lock is released (with PARTIAL being the exception to this).
If your intent is just to keep the screen on when a view is active then it's better not to use the lock at all. The wake lock needs an extra permission. You can do it by adding this to your onCreate override:
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
This is the same effect as using android:keepScreenOn="true", which you already seem to be doing. I can't however tell why that isn't working from your snippets. Make sure you are inflating the right layout.
For your data
The device will likely be switching off 3G data when the screen is not active (and no lock is present). Again, don't release your lock if you need it (Though don't keep it forever either, that's just going to suck up phone battery).
I'd like to switch on the screen from a service and immediately let the default system timeout take over (i.e. not hold a wakelock for a specific time, but just hand over control to the system). I've tried WakeLock.acquire() followed immediately by WakeLock.release() (with a SCREEN_BRIGHT_WAKE_LOCK), but that doesn't even switch on the screen at all. Is there any way to achieve this from a Service (short of launching a new WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON-dummy-activity)?
I think this is what you are looking for. You need to use
PowerManager.ACQUIRE_CAUSES_WAKEUP
I want to take pictures from the Android device's camera periodically over a matter of hours, to create a time lapse video effect.
I set an Alarm Manager with an AlarmManager.RTC_WAKEUP flag set to start up a service every few minutes.
The service holds a partial wakelock, does some work, and then calls a Broadcast Receiver through the Alarm Manager which starts up an Activity.
The activity is created (or is resumed), turns on it's own wakelock, and sets up the camera preview surface. Once the surface is setup the SurfaceHolder listener's surfaceChanged() method is called, which finally takes a picture.
If the device is awake, everything works perfectly as expected. But if the device is asleep, once the Activity's onResume() method is finished the Activity is instantly paused. The camera's preview surface never finishes initializing, and no picture will ever be taken.
So the questions I have are:
Is there any way to wake up the phone programmatically? I even try using:
PowerManager powerManager =
(PowerManager)this.getSystemService(Context.POWER_SERVICE);
powerManager.userActivity(SystemClock.currentThreadTimeMillis(),false);
But that doesn't wake up the phone if it is asleep.
Is there any way to take a picture without using a preview surface view?
Is there a way to take a picture that doesn't rely on asynchronous callbacks? Can I put all the code in the Activities onResume() method to take a picture?
Is there any way to keep the Activity's onResume() method running long enough so that the camera's preview has enough time to initialize and call all the listeners?
I am using the wakelocks correctly, and I have all the permission's set properly in the manifest file. My activity isn't kept awake long enough for the asynchronous listeners to properly work.
And to compound the issue, I'm trying to keep everything Android 1.6 compatible, because that is the only test device I have access to.
This is frustrating stuff!
I have finally gotten somewhere now.
I have to create a wakelock using these two flags
PowerManager.SCREEN_BRIGHT_WAKE_LOCK|PowerManager.ACQUIRE_CAUSES_WAKEUP
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
wl = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK|PowerManager.ACQUIRE_CAUSES_WAKEUP, "bbbb");
wl.acquire();
Then the device wakes up, and starts at the keyguard screen.
But the only way I can get past the keyguard screen and take a picture is to use these flags on the Activity's window:
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN
| WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
| WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
But this is only available with Android 2.0, and doesn't work in 1.6.
You can also disable the Keyguard screen with
KeyguardManager km = (KeyguardManager) getSystemService(KEYGUARD_SERVICE);
km.newKeyguardLock(TAG).disableKeyguard();
provided you have the DISABLE_KEYGUARD permission.
That's available since API Level 1.
Are you doing something like this in your onResume method
.... onResume() {
....
WakeLock myWakeLock = .....;
...
}
If so, as soon as the method exits, the WakeLock is released, and the device is free to do whatever it feels like doing ( which is likely to go back to sleep )
and you will need to store the WakeLock in the class somewhere, not as a function local.
How do I prevent an Android device from going to sleep programmatically?
If you just want to prevent the sleep mode on a specific View, just call setKeepScreenOn(true) on that View or set the keepScreenOn property to true. This will prevent the screen from going off while the View is on the screen. No special permission required for this.
One option is to use a wake lock. Example from the docs:
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "My Tag");
wl.acquire();
// screen and CPU will stay awake during this section
wl.release();
There's also a table on this page that describes the different kinds of wakelocks.
Be aware that some caution needs to be taken when using wake locks. Ensure that you always release() the lock when you're done with it (or not in the foreground). Otherwise your app can potentially cause some serious battery drain and CPU usage.
The documentation also contains a useful page that describes different approaches to keeping a device awake, and when you might choose to use one. If "prevent device from going to sleep" only refers to the screen (and not keeping the CPU active) then a wake lock is probably more than you need.
You also need to be sure you have the WAKE_LOCK permission set in your manifest in order to use this method.
I found another working solution: add the following line to your app under the onCreate event.
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
My sample Cordova project looks like this:
package com.apps.demo;
import android.os.Bundle;
import android.view.WindowManager;
import org.apache.cordova.*;
public class ScanManActivity extends DroidGap {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
super.loadUrl("http://stackoverflow.com");
}
}
After that, my app would not go to sleep while it was open. Thanks for the anwer goes to xSus.
android:keepScreenOn="true" could be better option to have from layout XML.
More info: https://developer.android.com/training/scheduling/wakelock.html
Set flags on Activity's Window as below
#Override public void onResume() {
super.onResume();
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
}
#Override public void onPause() {
super.onPause();
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
}
From the root shell (e.g. adb shell), you can lock with:
echo mylockname >/sys/power/wake_lock
After which the device will stay awake, until you do:
echo mylockname >/sys/power/wake_unlock
With the same string for 'mylockname'.
Note that this will not prevent the screen from going black, but it will prevent the CPU from sleeping.
Note that /sys/power/wake_lock is read-write for user radio (1001) and group system (1000), and, of course, root.
A reference is here: http://lwn.net/Articles/479841/
what #eldarerathis said is correct in all aspects, the wake lock is the right way of keeping the device from going to sleep.
I don't know waht you app needs to do but it is really important that you think on how architect your app so that you don't force the phone to stay awake for more that you need, or the battery life will suffer enormously.
I would point you to this really good example on how to use AlarmManager to fire events and wake up the phone and (your app) to perform what you need to do and then go to sleep again: Alarm Manager (source: commonsware.com)
If you are a Xamarin user, this is the solution:
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle); //always call superclass first
this.Window.AddFlags(WindowManagerFlags.KeepScreenOn);
LoadApplication(new App());
}
I'm using Wakelock in my application to prevent the phone from sleeping when the app is visible.
The problem comes when there is an orientation change and the system destroys and re-creates the app in landscape mode. If the wakelock timer has expired in the background the system takes the release of wakelock as an opportunity to switch off the screen.
Edit: I should mention that I am setting Wakelock onResume, and releasing onPause - as I understand it, it's necessary to release then to prevent the app from leaking the wakelock.
I need wakelock to continue through the orientation change.
Below I've outlined a solution to this. Is this the preferred way to handle it, and are there any alternatives?
Create a service which holds wakelock (rather than the activity) and when the activity unbinds the service starts a countdown timer (for say 10 seconds) in which it will release wakelock when the timer expires if the activity does not rebind. If it was a simple orientation change the activity will rebind within that 10 seconds and so maintain wakelock, if it doesn't, wakelock will be released.
Thanks.
Instead of a WakeLock, try getWindow().setFlags() using the WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON flag.
If the wakelock timer has expired in
the background the system takes the
release of wakelock as an opportunity
to switch off the screen.
It shouldn't. By definition, the user has interacted with the device, so the screen should stay on for that reason, independent of anything else.
Here's how I did it...
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
wl = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK|PowerManager.ON_AFTER_RELEASE, "DoNotDimScreen");
Followed by...
wl.acquire();
... when you need to actually activate the wake lock.
The 'PowerManager.ON_AFTER_RELEASE' flag pokes the user activity timer so the screen stays on for a little longer when this wake lock is released, which will be the case when your activity is Destroyed on a change of orientation.
Works OK for me!
I did it by actually never releasing the wakelock. Instead, I acquire it with timeout.
private PowerManager.WakeLock wl;
protected void onStart(Bundle savedInstanceState) {
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
wl = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "Words counter");
// disable reference counting, as acquire/release calls are not paired
wl.setReferenceCounted(false);
wl.acquire();
}
protected void onStop() {
// acquire for few seconds to keep lock until onStart is called with new orietnation
wl.acquire(3000);
}
Advantages over other methods:
Usable with the SCREEN_DIM_WAKE_LOCK
Simple (no need to play with isFinishing() etc.)
Does not poke user activity after orientation change. I.e. dimmed display stays dimmed
If you release (e.g. the time is over but the user remained in the activity), it's released immediately. No need to wait for default timeout.