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

8.8k views Asked by At

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.

3

There are 3 answers

5
CommonsWare On BEST ANSWER

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.

0
Michael P On

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.

0
Brant On

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) {
                }
            }
        }
    }