App seems to stop working when the screen goes to sleep - android

I have a CPU intensive long-running operation (a few hours) that I am using AsyncTask to perform. As it continues, it updates a progressbar on the screen to show what percentage of the task is done.
I discovered that when my screen goes to sleep (time-out) the task seems to stop. Not sure whether this is happing because the AsyncTask stops or it gets stuck at trying to update the screen (latter I am thinking).
Other than never letting the screen sleep, how else can I prevent my AsyncTask to stop executing? And if that is the only way, then how do I make sure that the screen doesn't sleep?
EDIT: I must add that I know this sounds like a non-user-friendly app as commented by someone below. This does a very specialized task (processes thousands of image files to compare processing on different systems) and is to be used by a few users internally, not for public release.

That's expected behavior. The idea is that the phone's battery is not supposed to drain because of bad apps. If the screen is off, the user generally expects the phone to sleep.
If you need your app to run, you can use a WakeLock to keep the phone running (with the screen off): Documentation here and here.
Note that a wake lock requires the WAKE_LOCK permission, and again, you need to make it clear to the user that your app will drink the phone's milkshake while it's off.

Not sure if anyone will read this as the OP is several years old but I am in the same boat in that I need to use a wakelock for an app for internal use, and leaving the screen on was not ok (I just needed the cpu on so I could run some metrics queries) I simply used a partial wakelock; ie:
public class my_frag extends Fragment {
WakeLock wl;
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
setRetainInstance(true);
PowerManager pm = (PowerManager) this.getActivity().getSystemService(Context.POWER_SERVICE);
wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "MyWakeLock");
//I happen to have it in a button click event based on an async task
//Side note: I should probably be using a Loader for my Async task but this works fine
connectButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
if (metrics_task != null)
{
Status s = metrics_task.getStatus();
if (s.name().equals("RUNNING")){
if (metrics_task.running){
metrics_task.cancel(true);
connectButton.setText("Start");
metrics_task.running = false;
wl.release(); <--releases it on async stop
}
else{
metrics_task = new start_metrics(ae);
metrics_task.execute();
wl.acquire(); <--starts it on async start
}
}
else{
metrics_task = new start_metrics(ae);
metrics_task.execute();
}
}
else{
metrics_task = new start_metrics(ae);
metrics_task.execute();
}
}
});
This worked great with no issues

My 2 cents on this old post, in case it might help someone. If all you want is to prevent your screen from going to sleep, there's a simple solution that does not require a permission from the user - and it's just 2 lines of code:
// prevent the screen from sleeping
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
// do your stuff
// don't forget to re-enable the screen time-out so it won't stay awake from now on
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
An important note: it can only be called within an Activity - not from other app components. more details can be found here.

Related

Prevent app from going on OnPause when turning screen off using partial wakelock

I'm trying to catch the volume Up/Down button press with the screen off, but despite acquiring a wakelock the app doesn't stay in the foreground when pressing the lock button. I have a breakpoint in the OnPause method and it gets hit when the screen turns off, and I can confirm that the wakelock is on through ADB terminal with the command:
adb shell dumpsys power
I omitted the volume buttons events since they're not relevant, but they do work when the screen is on.
I don't know what I'm missing, maybe I'm missunderstanding how the wakelock is supposed to behave?
I'm testing it in an emulator with Android 6.0 and in a physical phone with Android 7.1.2.
Thanks in advance for any help..
Button getLockBtn;
PowerManager _powerManager;
PowerManager.WakeLock _wakeLock;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
RequestWindowFeature(WindowFeatures.NoTitle);
SetContentView(Resource.Layout.Main);
getLockBtn = FindViewById<Button>(Resource.Id.GetLockBtn);
_powerManager = (PowerManager)GetSystemService(PowerService);
_wakeLock = _powerManager.NewWakeLock(WakeLockFlags.Partial, "MyTag");
getLockBtn.Click += (s, e) =>
{
if (_wakeLock.IsHeld)
{
_wakeLock.Release();
getLockBtn.Text = "Get lock";
//Remove the notification
}
else
{
//Here I show a notification
_wakeLock.Acquire();
getLockBtn.Text = "Release lock";
}
};
}
So how do apps like Google Maps achieve that behavior
When the screen is locked, the volume control comes from the system, and it is not the time to apply the control itself.Google Maps do nothing with the volume.
Your problem may not be the use of the volume button under the lock screen, but the program can still work when you lock the screen.
If you want a task to continue running, even when your Activity is not active, you need to use a Service. https://developer.android.com/guide/components/services.html.
Also can and a Notification to show something on the lock screen. https://developer.android.com/guide/topics/ui/notifiers/notifications.html

Wake up Android Wear from a service when in sleep mode?

I am working on Android Wear app that is somehow a timer that displays a notification when the time is elapsed and then start again. The notification displays a message on the watch and make the device vibrating.
The app is working fine except when the watch is in sleep mode. In this case, the user needs to touch the screen in order that the watch vibrates and the timer starts again.
The notification is created and displayed from a WearableListenerService. I tried many solutions such as Wake locks. The code is written in C# with Xamarin.Android but i think any java dev will also be able to read:
static PowerManager.WakeLock sWakeLock;
static object LOCK = new object();
void DisplayNotification()
{
//create the wake lock
lock (LOCK)
{
if (sWakeLock == null)
{
// This is called from BroadcastReceiver, there is no init.
var pm = (PowerManager)GetSystemService(Context.PowerService));
sWakeLock = pm.NewWakeLock(
WakeLockFlags.ScreenBright | WakeLockFlags.Full | WakeLockFlags.AcquireCausesWakeup, "My WakeLock Tag");
}
}
sWakeLock.Acquire();
//display the notification
//....
//release the wake lock
lock (LOCK)
{
//Sanity check for null as this is a public method
if (sWakeLock != null)
sWakeLock.Release();
}
}
My issue is that the watch will wake up at some point (after few minutes) but not immediately when requested. I tried to put a delay on the release of the wake lock or to make an sWakeLock.Acquire(2000) in order that the wake lock is automatically released after 2 secs. Then, I also tried other solutions with the WakefulBroadcastReceiver and the AlarmManager but I still have the same behaviour.
I've done something like that on mobile just by adding one line in onCreate of the activity i was calling by service.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//add this below getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD|WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
}
I would avoid Xamarin for Wear as it might cause some conflicts and not work well as it wasn't designed to.
Also if you created Service that is triggered on Android Wear - I would say Message API is correct way to do it, you should have no problem with a creating notification (on a watch itself) with vibrations (without need to touch screen) and update notification from your Service - to update timer value.
No wake locks needed.
Might help: How can I create notification that is different on device and wear?

Timer stops every time the phone sleeps

I'm creating this incredibly simple app, since I'm just starting with Android and I have no experience with Java what so ever. Anyhow, all I have is a timer and a button. Obviously the button starts the timer which counts down from 60 ( 1 minute ) and then vibrates when it's done. All worked fine up until the point I decided to press the lock screen button to put the phone to sleep. I found out that the timer in my app stops going until I unlock the phone. This also happens if I set the auto sleep time to less than 60 seconds and the phone falls asleep on it's own. My question is - how can I have that chronometer running even when the screen is not active?
You need to make this using BroadCastRecievers for system-calls. (Related Helpful question)
You can also play off the life-cyles of the Activity using the PowerManager.
Example using PowerManager:
#Override
protected void onPause()
{
super.onPause();
// If the screen is off then the device has been locked
PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
boolean isScreenOn = powerManager.isScreenOn();
if (!isScreenOn) {
// The screen has been locked
// Continue your timer
}
}

Android - Wake lock not acquiring properly, app needs to keep running in standby

In my app, in the onCreate() method of the main activity I am creating a wake lock so that the CPU will keep running if the phone goes on standb/screen turns off.
Also in the onCreate method I have an intent to create a service that uses the accelerometer. This service needs to be continuously running while the app is open and monitoring accelerometer values (I know this isn't good for battery but I need it to do that). Here is my code at the moment and the service starts fine.
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
PowerManager pm = (PowerManager) getSystemService(POWER_SERVICE);
PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "Howaya");
wl.acquire();
if (appStart == true)
{
Intent AccelService = new Intent(this, Accelerometer.class);
AccelService.putExtra("unreg", false);
startService(AccelService);
}
appStart = false;
}
I have the following permission set in my manifest -
<uses-permission android:name="android.permission.WAKE_LOCK" />
I have tried this with different locks - dim screen and full brightness to no avail too. My output on logcat is here -
F/PowerManager(15628): android.util.Log$TerribleFailure: WakeLock finalized while still held: Howaya
F/PowerManager(15628): at android.util.Log.wtf(Log.java:260)
F/PowerManager(15628): at android.util.Log.wtf(Log.java:239)
F/PowerManager(15628): at android.os.PowerManager$WakeLock.finalize(PowerManager.java:329)
F/PowerManager(15628): at dalvik.system.NativeStart.run(Native Method)
I have seen people saying that partial wakelocks don't work like they should do, such as this link Google standby error page but this was released and closed last year so I don't know is that the case, can anyone help here please? I have a HTC Desire as regards that last point too, Thanks.
Problem occurs because your WakeLock object is a local scoped variable inside OnCreate method. After method being executed - WakeLock object is no more referenced - thus eligible for garbage collection. If Dalvik GC occurs - object is ready for finalize - and finalizer internal code warns You, that WakeLock is still held - and active - but will be GC'ed. You have to obtain new WakeLock object and assign it to a field of class type WakeLock in Your activity derived class. Read about Object Oriented programming and Garbage Collector - You will understand the issue.
In my app, in the onCreate() method of the main activity I am creating a wake lock so that the CPU will keep running if the phone goes on standb/screen turns off.
Please use android:keepScreenOn on one of the widgets in your layout instead. That is far, far safer for activities than manually dealing with a WakeLock. Plus, you don't need the WAKE_LOCK permission then, IIRC.
My output on logcat is here
That error is because you never release the WakeLock. Please do not leak WakeLocks.
Now, you managed to write all of this prose and include all of these listings, and you forgot one little thing: actually telling us what your question is. This is a rather important item for a question-and-answer site like StackOverflow. And, no, "can anyone help here please?" does not count as a question when you never define what "help" it is you are looking to receive.
As #Michal P said, you acquire a wakelock in onCreate method, but you never release it.
When GC scan this zero referenced object, call default finalize method, but actually it is active.
#Override
protected void finalize() throws Throwable {
synchronized (mToken) {
if (mHeld) {
Log.wtf(TAG, "WakeLock finalized while still held: " + mTag);
Trace.asyncTraceEnd(Trace.TRACE_TAG_POWER, mTraceName, 0);
try {
mService.releaseWakeLock(mToken, 0);
} catch (RemoteException e) {
}
}
}
}

How do I prevent an Android device from going to sleep programmatically?

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());
}

Categories

Resources