Android java.lang.RuntimeException:WakeLock 未锁定 C2DM_LIB
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12140844/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
java.lang.RuntimeException: WakeLock under-locked C2DM_LIB
提问by Rookie
I have uploaded my application on google play but users have reported the following exception
我已将我的应用程序上传到 google play 但用户报告了以下异常
java.lang.RuntimeException: WakeLock under-locked C2DM_LIB. This exception occurs when I try to release the WakeLock
. Can anyone tell what could be the problem.
java.lang.RuntimeException: WakeLock 未锁定 C2DM_LIB。当我尝试释放WakeLock
. 谁能告诉可能是什么问题。
回答by fasti
You didn't post your code, so I don't know if you've already done what I will suggest here, but I also had that exception and all I added to fix it was a simple "if" to make sure the WakeLock is actually being held, before trying to release it.
你没有发布你的代码,所以我不知道你是否已经完成了我在这里的建议,但我也有这个例外,我添加的所有修复它是一个简单的“if”以确保 WakeLock在试图释放它之前实际上是被持有。
All I added in my onPause was this "if" statement (before the "release()"):
我在 onPause 中添加的只是这个“if”语句(在“release()”之前):
if (mWakeLock.isHeld())
mWakeLock.release();
and the exception was gone.
并且异常消失了。
回答by HitOdessit
I have traced same exception in new GCM Library too. Actually old C2DM Android library have same error, same crash, and Google hasn't fixed it yet. As I can see by our statistics, about 0.1% of users experiencing this crash.
我也在新的 GCM 库中跟踪了相同的异常。实际上旧的 C2DM Android 库有同样的错误,同样的崩溃,谷歌还没有修复它。从我们的统计数据中可以看出,大约 0.1% 的用户遇到了这种崩溃。
My investigations shows that problem is in incorrect releasing of network WakeLock
in GCM library, when library tries to release WakeLock
that holds nothing (internal lock counter becomes negative).
我的调查表明,问题在于WakeLock
GCM 库中网络的错误释放,当库尝试释放WakeLock
不包含任何内容时(内部锁计数器变为负数)。
I was satisfied with simple solution - just catch this exception and do nothing, because we don't need to do any extra job then our wakelock hold nothing.
我对简单的解决方案感到满意 - 只需捕获此异常并且什么都不做,因为我们不需要做任何额外的工作,然后我们的唤醒锁就什么都不做。
In order to do this you need to import GCM library sources in your project, rather than already compiled .jar
file. You can find GCM library sources under "$Android_SDK_Home$/extras/google/gcm/gcm-client/src" folder (you need to download it first using Android SDK Manager).
为此,您需要在项目中导入 GCM 库源,而不是已编译的.jar
文件。您可以在“ $Android_SDK_Home$/extras/google/gcm/gcm-client/src”文件夹下找到GCM库源(您需要先使用Android SDK Manager下载)。
Next open GCMBaseIntentService
class, find line
下一个公开GCMBaseIntentService
课,找行
sWakeLock.release();
and surround it with try-catch.
并用 try-catch 包围它。
It should look like this:
它应该是这样的:
synchronized (LOCK) {
// sanity check for null as this is a public method
if (sWakeLock != null) {
Log.v(TAG, "Releasing wakelock");
try {
sWakeLock.release();
} catch (Throwable th) {
// ignoring this exception, probably wakeLock was already released
}
} else {
// should never happen during normal workflow
Log.e(TAG, "Wakelock reference is null");
}
}
UPDATE:Alternativally, as suggested @fasti in his answer, you can use mWakeLock.isHeld()
method to check if wakelock actually holding this lock.
更新:或者,正如@fasti 在他的回答中所建议的那样,您可以使用mWakeLock.isHeld()
方法来检查唤醒锁是否实际持有此锁。
回答by Shoham
Although the isHeld() solution seems nicer, it can actually fail - because it is not atomic (i.e. not thread safe). If you have more than one thread that might release the lock then between the check (isHeld) and the call to relase another thread may release the lock... and then you fail.
尽管 isHeld() 解决方案看起来更好,但它实际上可能会失败 - 因为它不是原子的(即不是线程安全的)。如果您有多个线程可能会释放锁,那么在检查 (isHeld) 和释放另一个线程的调用之间可能会释放锁……然后您会失败。
By using try/catch you disguise the bug, but in a thread-safe way.
通过使用 try/catch,您可以以线程安全的方式掩饰错误。
回答by MobileMon
I don't have this problem as long as I don't reinitialize the wake lock and call acquire on the new Object. You should only keep one instance of wakeLock (so make it a field variable). Then you know you're always releasing that one wakeLock.
只要我不重新初始化唤醒锁并在新对象上调用获取,我就没有这个问题。您应该只保留一个wakeLock 实例(因此将其设为字段变量)。然后你知道你总是释放那个wakeLock。
So....
所以....
if (mWakeLock == null) {
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
mWakeLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP
| PowerManager.ON_AFTER_RELEASE, "MyWakeLock");
}
try{
mWakeLock.release();//always release before acquiring for safety just in case
}
catch(Exception e){
//probably already released
Log.e(TAG, e.getMessage());
}
mWakeLock.acquire();