java.lang.RuntimeException:WakeLock被locking为C2DM_LIB

我已经上传我的应用程序谷歌播放,但用户已经报告了以下exception

java.lang.RuntimeException:WakeLock被locking为C2DM_LIB 。 当我尝试释放WakeLock时会发生此exception。 任何人都可以告诉可能是什么问题。

我也在新的GCM库中追踪了同样的例外情况。 其实老的C2DM Android库有同样的错误,同样的崩溃,而Google还没有修复它。 从我们的统计数据中可以看出,约有0.1%的用户正在经历这次崩溃。

我的调查显示,问题是GCM库中networkingWakeLock错误释放,当库试图释放WakeLock包含任何内容的WakeLock (内部locking计数器变为负数)。

我对简单的解决scheme感到满意 – 只要赶上这个例外,什么都不做,因为我们不需要做任何额外的工作,那么我们的wakelock什么也没有。

为了做到这一点,您需要在您的项目中导入GCM库源代码,而不是已经编译好的.jar文件。 您可以在“ $ Android_SDK_Home $ / extras / google / gcm / gcm-client / src ”文件夹下findGCM库源文件(您需要先使用Android SDK Manager下载它)。

接下来打开GCMBaseIntentService类,find一行

 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"); } } 

更新:另外,在他的回答build议@fasti,你可以使用mWakeLock.isHeld()方法来检查是否实际持有这个锁的wakelock。

你没有发布你的代码,所以我不知道你是否已经做了我会build议在这里,但我也有这个例外,所有我补充,以解决这是一个简单的“如果”, 以确保WakeLock实际上正在举行之前,试图释放它

我在onPause中添加的所有内容都是这个“if”语句(在“release()”之前):

 if (mWakeLock.isHeld()) mWakeLock.release(); 

而例外已经消失了。

尽pipeisHeld()解决scheme看起来更好,但实际上可能会失败 – 因为它不是primefaces的(即不是线程安全的)。 如果你有多个可能释放锁的线程,那么在检查(isHeld)和另一个线程的调用之间可能会释放锁,然后你失败。

通过使用try / catch,你可以隐藏错误,但是是以线程安全的方式。

我没有这个问题,只要我不重新初始化唤醒锁和调用获取新的对象。 你应该只保留wakeLock的一个实例(所以把它作为一个字段variables)。 那么你知道你总是发布一个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();