栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

【唤醒屏幕总结】java.lang.RuntimeException: WakeLock under-locked target

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【唤醒屏幕总结】java.lang.RuntimeException: WakeLock under-locked target

最近线上的项目遇到了这样的错误

java.lang.RuntimeException: WakeLock under-locked target
	at android.os.PowerManager$WakeLock.release(PowerManager.java:2665)
	at android.os.PowerManager$WakeLock.release(PowerManager.java:2627)
	at com.driving.driver.android.kepplive.PowerManagerUtil$1.run(PowerManagerUtil.java:86)
	at java.lang.Thread.run(Thread.java:933)"

经过一顿查找资料分析,是由于设置了mWakelock.acquire();默认计数形式唤醒屏幕,这种情况下还需要设置 mWakelock.setReferenceCounted(false); 不然的话,很容易引起以下异常:

java.lang.RuntimeException: WakeLock under-locked

原理:

       acquire() 函数如下:

            public void acquire () {
                synchronized (mToken) {
                    if (!mRefCounted || mCount++ == 0) {
                        try {
                            mService.acquireWakeLock(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 {
                            mService.releaseWakeLock(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掉


这是我的唤醒屏幕工具类,有需要的可以直接使用
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 {
                //创建实例之前可能会有一些准备性的耗时工作
                Thread.sleep(300);
                synchronized (PowerManagerUtil.class) {
                    if (instance == null) {//二次检查
                        instance = new PowerManagerUtil();
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return instance;
    }

    
    public boolean isScreenOn(final Context context) {
        try {
            Method isScreenMethod = PowerManager.class.getMethod("isScreenOn", new Class[]{});
            PowerManager pm = (PowerManager) context.getSystemService(POWER_SERVICE);
            boolean screenState = (Boolean) isScreenMethod.invoke(pm);
            return screenState;
        } catch (Exception e) {
            return true;
        }
    }

    
    @SuppressLint("InvalidWakeLockTag")
    public void wakeUpScreen(final Context context) {
        try {
            if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
                PowerManager pm = (PowerManager) context.getSystemService(POWER_SERVICE);
                
                PowerManager.WakeLock mWakelock = pm.newWakeLock(
                        PowerManager.PARTIAL_WAKE_LOCK
                                | PowerManager.SCREEN_DIM_WAKE_LOCK, TAG);
                
                mWakelock.setReferenceCounted(false);
                mWakelock.acquire();
                if (mWakelock.isHeld()) {//如果已获得唤醒锁但尚未释放,则返回true。
                    mWakelock.release();
                }
                // FIXME: 注意:WakeLock的设置是 Activiy 级别的,不是针对整个Application应用的。所以application下有多个activity一定需要注意下!
            }
        } catch (Exception e) {

        }
    }

}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/530705.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号