我已經上傳我在谷歌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