最近线上的项目遇到了这样的错误
: WakeLock under-locked target
at $(:2665)
at $(:2627)
at $(:86)
at (:933)"
经过一顿查找资料分析,是由于设置了();默认计数形式唤醒屏幕,这种情况下还需要设置 (false); 不然的话,很容易引起以下异常:
: WakeLock under-locked
原理:
acquire() 函数如下:
public void acquire () {
synchronized (mToken) {
if (!mRefCounted || mCount++ == 0) {
try {
(mFlags, mToken, mTag);
} catch (RemoteException e) {
}
mHeld = true;
}
}
}
release() 函数如下:
public void release () {
release(0);
}
public void release ( int flags){
synchronized (mToken) {
if (!mRefCounted || --mCount == 0) {
try {
(mToken, flags);
} catch (RemoteException e) {
}
mHeld = false;
}
if (mCount < 0) {
throw new RuntimeException("WakeLock under-locked " + mTag);
}
}
}
看到了吗?报错就抱在release(int flags)中,mCount为负数了,抛除了异常
我们再看下:setReferenceCounted(boolean flags);
public void setReferenceCounted(boolean value){
mRefCounted = value;
}
这个函数的作用是是不是需要计算锁的数量,设置为false时,在release()的时候,不管你acquire()了多少回,可以releaseWakeLock掉
这是我的唤醒屏幕工具类,有需要的可以直接使用
/**
* Author : 马占柱
* E-mail : mazhanzhu_3351@
* Time : 2021/9/22 15:46
* Desc : 保证在息屏状体下,CPU可以正常运行
*/
public class PowerManagerUtil {
public static final String TAG = "PowerManagerUtil";
//使用volatile关键字保其可见性
volatile private static PowerManagerUtil instance = null;
private PowerManagerUtil() {
}
public static PowerManagerUtil getInstance() {
try {
if (instance != null) {//懒汉式
} else {
//创建实例之前可能会有一些准备性的耗时工作
(300);
synchronized () {
if (instance == null) {//二次检查
instance = new PowerManagerUtil();
}
}
}
} catch (Exception e) {
();
}
return instance;
}
/**
* @param context
* @return 判断屏幕是否处于点亮状态 true【亮屏】 false【息屏】
*/
public boolean isScreenOn(final Context context) {
try {
Method isScreenMethod = ("isScreenOn", new Class[]{});
PowerManager pm = (PowerManager) (POWER_SERVICE);
boolean screenState = (Boolean) (pm);
return screenState;
} catch (Exception e) {
return true;
}
}
/**
* 唤醒屏幕
*/
@SuppressLint("InvalidWakeLockTag")
public void wakeUpScreen(final Context context) {
try {
if (.SDK_INT >= .VERSION_CODES.M) {
PowerManager pm = (PowerManager) (POWER_SERVICE);
/*
* SCREEN_DIM_WAKE_LOCK CPU:保持运转 屏幕:保持显示但可以是暗的 键盘灯:关闭
* SCREEN_BRIGHT_WAKE_LOCK CPU:保持运转 屏幕:保持高亮 键盘灯:关闭
* FULL_WAKE_LOCK CPU:保持运转 屏幕:保持高亮 键盘灯:点亮
* PARTIAL_WAKE_LOCK CPU:保持运转 屏幕:可以关闭 键盘灯:可以关闭
*
* ACQUIRE_CAUSES_WAKEUP 强制使屏幕亮起,这种锁主要针对一些必须通知用户的操作【慎用,会导致锁屏情况下,来消息屏幕频繁亮起,体验不好!】
* 不能和 PARTIAL_WAKE_LOCK 一起用
*
* ON_AFTER_RELEASE 在释放锁时回收activity的timer计时器【不能和 PARTIAL_WAKE_LOCK 一起用】
* */
mWakelock = (
PowerManager.PARTIAL_WAKE_LOCK
| PowerManager.SCREEN_DIM_WAKE_LOCK, TAG);
/*
* /fengyeNom1/article/details/121373158【详解】
* 在通常的wakelock使用时,会报错:: WakeLock under-locked。
* 这是因为出现了上述release函数末尾if(mCount<0)的情,用 setReferenceCounted(false) 就可以解决这个问题。
* 这个函数的作用:是不是需要计算锁的数量?设置为false时,在release的时候,不管你acquire()了多少回,可以一次releaseWakeLock掉。
*
* 注意这个方法默认为true,意味着一个WakeLock调用acquire()多次,也必须release()多次才能释放,
* 如果释放次数比acquire()多,则抛出异常: : WakeLock under-locked
* */
(false);
();
if (()) {//如果已获得唤醒锁但尚未释放,则返回true。
();
}
// FIXME: 注意:WakeLock的设置是 Activiy 级别的,不是针对整个Application应用的。所以application下有多个activity一定需要注意下!
}
} catch (Exception e) {
}
}
}