I use an alarm to take pictures at regular time intervals. I use a BroadcastReceiver as follows:
#Override
public void onReceive(Context context, Intent intent)
{
Log.d(TAG, "Capturing pic");
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "CAPPIC");
wl.acquire();
capturePicture();
wl.release();
}
The capturePicture() calls Camera.takePicture(...) and then ends. Finally, as you can see, wl.release() is invoked.
Now, the problem is that the call back of the takePicture is very time consuming in my case. In fact, it performs some manipulations on the picture just taken that can take up to 5 seconds on my device.
My question is, since wl.release() is called while the computational intensive task into the takePicture callback is running, is there any side effect? That is, suppose that the device is in standby mode. The alarm starts --> wakelock is activated --> picture is taken and manipulated but in the meanwhile of the computation wakelock is released... is it safe or there is the risk that the device returns to its standby mode before the routines into the takePicture callback ends?
Your setup is wrong in that you should not be doing a lot in the receiver and in that the AlarmManager holds a wakelock while onReceive() runs anyway - and yes you should not release the wakelock while editing. You should delegate to a service and for reasons detailed here this must be a WakefulIntentService. Now in that service you should set up a mechanism for waiting for the processing to finish - maybe using CountDownLatch.
Related
I'm creating an application that needs to keep track of a lot of things the user is doing. This all needs to happen in the background and needs to be running continiously. To mention two: constant tracking of activity with google activity API and location tracking with google's geofence API.
I have created a (Intent)Service for each parameter I am tracking and everything is going well. Even when you kill the application, the service will start again on the background and perform as expected.
MY PROBLEM: As soon as I lock my phone, it stops tracking. As soon as I light up my screen or unlock it works again.
NOTE1: I'm using one main service which controls all other (intent)services sensing the parameters. (I'm not sure if this is the best way to do it or if I should create one big service?...).
What I've tried is the PARTIAL_WAKE_LOCK to keep awake my main service controlling all other services. This didn't work. I've also tried to use the PARTIAL_WAKE_LOCK to keep awake the services sensing the parameters. This did not work either.
NOTE2: I know this should not be done in real applications but it's a must. It's an application for an experiment and will never go in the playstore. Also all users will be notified what will be tracked and how this can effect their battery during the experiment.
#Override
public void onCreate() {
super.onCreate();
...
PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
"MyWakelockTag");
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (! keepCPUOn){
wakeLock.acquire();
keepCPUOn = true;
}
}
Manifest:
<uses-permission android:name="android.permission.WAKE_LOCK" />
Many thanks!
Beginning with Android 6 and its new Doze mode the wake locks don't prevent the device to enter sleep mode, they are ignored
Proposed solution: Your service need to be a foreground service, that's it should call startForeground() and show a non dismissable notification, and you need to acquire a partial wake lock too.
I am also creating app like your. location tracking work in background and UI screen doesn't lock. in which UI screen you are start location service please put below code in that java file.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_current_ride_new);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
PowerManager.WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
"MyWakelockTag");
wakeLock.acquire();
}
This code is working perfectly for me.
I've just add my app in Protected apps in settings my phone Android 4.4 (this flug allow to keep running after the screen is turned off)
In my application, user starts the service it is open and it is called every 5 minutes. it works fine.
But I want to unlock automatically (call WAKE_LOCK ) whenever the service is called i.e. every 5 minutes.
How can I achieve this?
Any body please help me...
Edit 1#
private void handleIntent(Intent intent) { // obtain the wake lock
PowerManager pm = (PowerManager) getSystemService(POWER_SERVICE);
mWakeLock = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, NAME);
mWakeLock.acquire();
}
You have to use the AlarmManager for that.
Set up of the alarm and its receiver : Notification activity called by AlarmManager NOT to pop up when app is closed
Then you have to convert your service to a wakeful intent service and then call WakefulIntentService.sendWakefulWork(context, YourService.class); inside onReceive(context)
At least this was the way to go - the latest android platform seems to support this (kind of) out the box : https://developer.android.com/reference/android/support/v4/content/WakefulBroadcastReceiver.html
I use wakelock to keep the display on.
However, when the app is ended, the display also be turned off.
I want to keep it on after the app is ended.
What should I do?
What you want to do is use the .On_AFTER_RELEASE flag see below.
PowerManager pm;
PowerManager.WakeLock wakeLock;
// Put the next 5 lines in a method that is called when you want to acquire a wakelock //or in the OnREceive() of a broadcast receiver.`
PowerManager pm = (PowerManager)
context.getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wakeLock = pm.newWakeLock(
pm.ON_AFTER_RELEASE|pm.SCREEN_DIM_WAKE_LOCK, "My wakelook");
wakeLock.acquire();
...Do Stuff here
//Override the onDestroy of your activity to release the wakelock when it is destroyed.
#Override
protected void onDestroy() {
super.onDestroy();
wakelock.release;
}
This will keep the screen lit up as if someone interacted with the device (pushed the power button, touched the screen, etc.) right when you release the wakelock. At that point a normal power down will occur if there is no further interaction with the device (screen goes dim, and then it goes dark).
I
Let me know if that helped.
Thx
******************Added*************
If you want to wake up the phone from after the screen goes dark you can create your wakelock with the following flags. This is good if you have a broadcast receiver and want to turn on the screen when an event happens so the user can immediately see a UI (Notification, Toast, Layout,etc.)
PowerManager.WakeLock wakeLock = pm.newWakeLock(
pm.ACQUIRE_CAUSES_WAKEUP|pm.ON_AFTER_RELEASE|pm.SCREEN_DIM_WAKE_LOCK, "My wakelook");
And for how long do you need the display to stay on? Just for some time, or until certain event happen?
Don't release the wakelock when application is ended. You may schedule an event for a period of time you need to keep the screen on. But generally it's a bad practice as holding full wakelock may prevent not only screen but other hardware from going to sleep.
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.
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.