3

Android lint warns on the following with [Wakelock]:

public static void acquire(Context ctx, long timeout) {
    if (wakeLock != null) {
        wakeLock.release();
    }

    PowerManager powerManager
        = (PowerManager) ctx.getSystemService(Context.POWER_SERVICE);
    wakeLock = powerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK |
                    PowerManager.ACQUIRE_CAUSES_WAKEUP |
                    PowerManager.ON_AFTER_RELEASE, 
                    Common.TAG);
    wakeLock.setReferenceCounted(false);

    if ( timeout <= 0 ) {
        wakeLock.acquire();
    } else {
        wakeLock.acquire(timeout);
    }
}

public static synchronized void release() {
    if ( wakeLock != null ) {
        if ( wakeLock.isHeld() ) {
            wakeLock.release(); 
        }
        wakeLock = null;
    }
}

It gives the warning for the first occurrence

[lint] [...]/WakeLocker.java: Warning: The release() call is not always reached [Wakelock]

Yet, it does not really need to be released every time, as there is a timeout.

The default solution of wrapping this in a try-catch-block, as for example in android-wakelock-not-released-after-getactivenetworkinfo, or in @rainash's answer below, do not address the problems that led to using this approach, namely that the device can go back to sleep.

How is this fixed? Or should it be ignored?

Community
  • 1
  • 1
serv-inc
  • 35,772
  • 9
  • 166
  • 188

3 Answers3

3

use try-catch block wrap task you execute when device awake

PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
    final WakeLock wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "tag");
    wakeLock.acquire();
            try {
                do something
            } finally {
                wakeLock.release();
            }
    });
rainash
  • 864
  • 6
  • 15
  • The solution above is for when the device gets an alarm, but does not always react, because the timeout passes too fast, see http://stackoverflow.com/questions/6864712/android-alarmmanager-not-waking-phone-up. – serv-inc Jul 06 '15 at 14:22
  • @user1587329 I don't know what your comment talking about, I met the warning before, if the task you excuted throws an exception when you wake up the device,.release() is not always reached – rainash Jul 06 '15 at 14:31
  • to summarize the link: sometimes you want a small class that **only** acquires a wakelock, because otherwise your device can go to sleep while the class doing the handling is loaded. I had this problem. Can you propose a solution that deals with that (major) and answers this lint-question (minor)? – serv-inc Jul 06 '15 at 14:33
  • upvoted for effort ;-) (and yes, this comment is not a real comment) – serv-inc Jul 10 '15 at 08:42
  • Can we `release` wakelock in a separate function? Or does it have to be at the same callsite as `acquire`? – IgorGanapolsky Apr 28 '20 at 13:50
2

Indeed this seems to be a long forgotten problem. In fact this bug was reported to google already back in 2013 here, but seems to still be there.

As one commenter states:

The following code get the warning:

try {
    wakeLock.acquire();
    ...
} catch (Exception e) {
    ...
} finally {
    wakeLock.release();
}

Results in:

The release() call is not always reached (via exceptional flow)

However, if you throw the Exception in a method, no warning is reported:

private void makeMistake() throws Exception {
    throw new Exception();
    ...
    try {
        wakeLock.acquire();
        makeMistake();
    } catch (Exception e) {
    ...
    } finally {
        wakeLock.release();
    }
}

To disable this warning, rather do it in your apps build.gradle file, for easy access, rather than inline as suggested by @user.

...
lintOptions {
        disable 'Wakelock'
}
serv-inc
  • 35,772
  • 9
  • 166
  • 188
not2qubit
  • 14,531
  • 8
  • 95
  • 135
1

As @tyczj hinted:

[Lint] also flags issues that may or may not be a problem depending on the context.

So think about the warning, and

If you've manually verified that an issue is not a problem, you may want to mark the issue as verified such that lint does not keep pointing it out.

To remove the warning in this case, use

@SuppressLint("Wakelock")
public static void acquire(Context ctx, long timeout) {

with

import android.annotation.SuppressLint;
serv-inc
  • 35,772
  • 9
  • 166
  • 188