我已经上传我在谷歌Play应用程序,但用户报告以下异常了java.lang.RuntimeException:唤醒锁定在锁定C2DM_LIB
了java.lang.RuntimeException:唤醒锁定在锁定C2DM_LIB。当我尝试释放WakeLock
时,会发生此异常。任何人都可以告诉可能是什么问题。
我已经上传我在谷歌Play应用程序,但用户报告以下异常了java.lang.RuntimeException:唤醒锁定在锁定C2DM_LIB
了java.lang.RuntimeException:唤醒锁定在锁定C2DM_LIB。当我尝试释放WakeLock
时,会发生此异常。任何人都可以告诉可能是什么问题。
我也在新的GCM库中追踪了相同的异常。其实老C2DM Android库有相同的错误,同样的崩溃,谷歌还没有修复它。从我们的统计数据中可以看出,大约有0.1%的用户遇到这种崩溃。
我的调查显示,问题是在GCM库中的网络WakeLock
的错误释放,当库试图释放不包含任何内容的WakeLock
(内部锁定计数器变为负数)时。
我对简单的解决方案感到满意 - 只是赶上这个例外,什么也不做,因为我们不需要做任何额外的工作,那么我们的wakelock什么也不要。
为了做到这一点,您需要在您的项目中导入GCM库源代码,而不是已经编译好的.jar
文件。您可以在“$ Android_SDK_Home $/extras/google/gcm/gcm-client/src”文件夹下找到GCM库源文件(您需要先使用Android SDK Manager下载它)。
下一页开放GCMBaseIntentService
类,发现线
sWakeLock.release();
,并用的try-catch围绕着它。
它应该是这样的:
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,如建议@fasti在his answer,您可以使用mWakeLock.isHeld()
的方法来检查,如果激活锁定实际持有这个锁。
你没有发布你的代码,所以我不知道你是否已经完成了我在这里的建议, 但我也有这个例外,我补充说,所有我修复它是一个简单的“如果”到确保WakeLock实际上正在举行之前,试图释放它。
所有我在加的onPause是这样的: “如果” 的声明(以下简称 “发行()” 前):
if (mWakeLock.isHeld())
mWakeLock.release();
和异常不见了。
这个解决方案对我来说似乎比接受的更清洁。 – ottel142
这是因为它是 - 而且 - 正确的做法。这应该是被接受的答案。 – ComputerEngineer88
我没有.release()在我的代码(没有mWakeLock是如此),但我仍然得到这个错误。我看到的唯一stacktrace是: java.lang.RuntimeException:WakeLock未锁定GCM_LIB at com.google.android.gcm.GCMBaseIntentService.onHandleIntent(GCMBaseIntentService.java:252) at android.app。 IntentService $ ServiceHandler.handleMessage(IntentService.java:65) – Ted
尽管isHeld()解决方案看起来更好,但它实际上可能会失败 - 因为它不是原子的(即不是线程安全的)。如果你有多个可能释放锁的线程,那么在检查(isHeld)和另一个线程的调用之间可能会释放锁......然后你失败。
通过使用try/catch,你掩饰了这个错误,但是以一种线程安全的方式。
有没有一个很好的选择,以可重用的方式使WakeLock发布原子?它应该是一个原子操作。它的名字实际上有“锁定”。 – colintheshots
我没有这个问题,只要我不重新初始化唤醒锁和调用获取新对象。你应该只保留一个wakeLock实例(所以把它作为一个字段变量)。然后你知道你总是发布那个wakeLock。
所以....
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();
你已经尝试过了..?它是否运行良好后围绕它尝试赶上.. – Rookie
是的,我已经在我们所有的项目中实施了这个解决方案,它完美的工作(用户数超过2M用户) – HitOdessit
好的,谢谢..... – Rookie