22

pmkeepScreenOn变量是全局定义的。

我在 OnCreate 方法中获取 PowerManager.WakeLock:

pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
keepScreenOn = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_LOCK,"tpd");

在我的 onStart、onResume 和 onRestart 中,我用

if (keepScreenOn == null) {
    keepScreenOn = pm.newakeLock(PowerManager,SCREEN_BRIGHT_LOCK,"tpd");
}
keepScreenOn.acquire();

在我的 onDestroy、onPause 和 onStop 中,我使用以下命令释放锁:

if (keepScreenOn != null) {
  keepScreenOn.release();
  keepScreenOn = null
}

在我的应用程序退出后,我得到一个失败屏幕并且 adb 抱怨说

java.lang.Exception:WakeLock 在仍被持有时完成:tpd

跟踪显示我在退出之前释放了锁。我错过了什么?

如果不跨越、 或中的至少一个,就无法退出应用 onPause程序。我可以看到应用程序调用 的频率与调用 acquire() 一样频繁,因此即使唤醒锁是引用计数的,它仍然应该具有零引用。onStoponDestroyrelease()

4

3 回答 3

32

好的,我相信我发现了问题。

WakeLock 是引用计数的。这意味着如果第二次acquire() 发生它只会增加引用计数。每个调用都acquire() 需要通过调用来保护,isHeld()如下所示:

if ((keepScreenOn != null) &&           // we have a WakeLock
    (keepScreenOn.isHeld() == false)) {  // but we don't hold it 
  keepScreenOn.acquire();
}

我曾假设acquire()在我持有的锁上什么也没做,所以多次acquire()调用导致了问题。由于引用计数不为零,GC 会引发错误。

于 2011-05-07T18:45:03.020 回答
4

我知道这个问题很老,但请记住,WakeLocks 默认是“引用计数”的。您可以使用关闭引用计数setReferenceCounted(boolean),请参阅http://developer.android.com/reference/android/os/PowerManager.WakeLock.html#setReferenceCounted(boolean)

于 2013-04-22T18:10:48.133 回答
0

不,在全局范围内只有一个声明,所有对 acquire() 和 release() 的调用都发生在该范围内。当它们发生并且acquire()发生一次并且释放发生一次时,我 println 。

于 2011-05-07T18:26:30.383 回答