java.lang.RuntimeException:WakeLock未锁定C2DM_LIB

时间:2012-08-27 11:08:45

标签: android android-service android-c2dm google-cloud-messaging

我已将我的应用程序上传到谷歌播放,但用户报告了以下异常

java.lang.RuntimeException:WakeLock未锁定C2DM_LIB 。当我尝试释放WakeLock时会发生此异常。任何人都可以告诉可能是什么问题。

4 个答案:

答案 0 :(得分:158)

你没有发布你的代码,所以我不知道你是否已经完成了我的建议, 但我也有这个例外,所有我添加的修复它是一个简单的“if”到确保WakeLock实际上被保留,然后再尝试发布

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

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

并且异常消失了。

答案 1 :(得分:52)

我也在新的GCM库中追踪了同样的异常。实际上旧的C2DM Android库有同样的错误,同样的崩溃,谷歌还没有修复它。正如我从统计数据中看到的那样,大约有0.1%的用户遇到了此次崩溃。

我的调查显示问题在于GCM库中网络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");
        }
    }

<强>更新 另外,正如his answer中建议@fasti一样,您可以使用mWakeLock.isHeld()方法来检查唤醒锁是否实际上持有此锁。

答案 2 :(得分:4)

虽然isHeld()解决方案看起来更好,但它实际上可能失败 - 因为它不是原子的(即不是线程安全的)。如果你有多个可能释放锁的线程,那么在check(isHeld)和重新调用之间的另一个线程可能会释放锁...然后你就失败了。

通过使用try / catch,您可以以线程安全的方式伪装错误。

答案 3 :(得分:1)

只要我不重新初始化唤醒锁并在新对象上调用acquire,我就没有这个问题。你应该只保留一个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();