WakeLock 在仍持有时完成

发布于 2024-11-05 15:05:12 字数 937 浏览 7 评论 0原文

pmkeepScreenOn 变量是全局定义的。

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

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

在 onStart、onResume 和 onRestart 中,我在 onDestroy、onPause 和 onStop 中获取锁

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

,然后释放锁:

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

在我的应用程序退出后,出现故障屏幕并且 adb 抱怨那

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

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

如果不跨越至少一个,就无法退出该应用程序 onPauseonStoponDestroy。我可以看到该应用程序名为 release() 和调用 acquire() 一样频繁,所以即使 唤醒锁是引用计数的,它应该仍然有零引用。

The pm and keepScreenOn variables are globally defined.

I grab the PowerManager.WakeLock in my OnCreate method:

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

in my onStart, onResume, and onRestart I grab the lock with

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

in my onDestroy, onPause, and onStop I release the lock with:

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

After my app exits I get a failure screen and adb complains that

java.lang.Exception: WakeLock finalized while still held: tpd

Tracing shows that I released the lock before exit.
What have I missed?

There is no way out of the app without crossing at least one of
onPause, onStop, or onDestroy. I can see that the app called
release() as often as it called acquire() so even though the
wakelock is reference counted it should still have zero refs.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

享受孤独 2024-11-12 15:05:12

好吧,我相信我找到了问题。

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

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

我假设我持有的锁上的 acquire() 没有执行任何操作,因此
多次 acquire() 调用导致了该问题。自从参考
count 不为零,GC 会抛出错误。

Ok I believe I found the problem.

The WakeLock is reference counted. That means that if a second acquire()
happens it will just bump the reference count. Every call to acquire()
needs to be protected by a call to isHeld() as in:

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

I had assumed that acquire() on a lock I held did nothing so
multiple acquire() calls caused the problem. Since the reference
count is not zero the GC throws an error.

深海蓝天 2024-11-12 15:05:12

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

I know this question is old, but keep in mind that WakeLocks are 'reference counted' by default. You can turn off reference counting using setReferenceCounted(boolean), see http://developer.android.com/reference/android/os/PowerManager.WakeLock.html#setReferenceCounted(boolean)

栩栩如生 2024-11-12 15:05:12

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

No, there is only one declaration at the global scope and all
calls to the acquire() and release() occur in that scope. I
println when they happen and the acquire() occurs once and the
release occurs once.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文