studio google gcm_defaultsenderid gcm fcm change app airport android android-service android-c2dm google-cloud-messaging

google - push notifications android



java.lang.RuntimeException: WakeLock bloqueado C2DM_LIB (4)

Aunque la solución isHeld () parece más agradable, en realidad puede fallar, porque no es atómica (es decir, no es segura para subprocesos). Si tiene más de un hilo que puede liberar el bloqueo, entonces entre el cheque (isHeld) y la llamada para transferir otro hilo puede liberar el bloqueo ... y luego falla.

Al usar try / catch, usted oculta el error, pero de una manera segura para la ejecución de subprocesos.

He subido mi aplicación en google play pero los usuarios han informado sobre la siguiente excepción

java.lang.RuntimeException: WakeLock bloqueado C2DM_LIB . Esta excepción ocurre cuando intento liberar WakeLock . ¿Alguien puede decir cuál podría ser el problema?


No has publicado tu código, así que no sé si ya has hecho lo que voy a sugerir aquí, pero también tuve esa excepción y todo lo que agregué para solucionarlo fue un simple "si" para asegurarme de que el WakeLock en realidad se está reteniendo, antes de intentar liberarlo .

Todo lo que agregué en mi onPause fue esta declaración "if" (antes del "lanzamiento ()"):

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

y la excepción se había ido.


No tengo este problema siempre que no reinicie el bloqueo de activación y llame a adquirir en el nuevo objeto. Solo debe mantener una instancia de wakeLock (así que conviértala en una variable de campo). Entonces sabes que siempre estás liberando ese wakeLock.

Asi que....

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();


También he rastreado la misma excepción en la nueva biblioteca de GCM. En realidad, la vieja biblioteca C2DM de Android tiene el mismo error, el mismo bloqueo, y Google aún no lo ha solucionado. Como puedo ver en nuestras estadísticas, alrededor del 0.1% de los usuarios experimentan este bloqueo.

Mis investigaciones muestran que el problema está en la liberación incorrecta de la red WakeLock en la biblioteca de GCM, cuando la biblioteca intenta liberar WakeLock que no retiene nada (el contador de bloqueo interno se vuelve negativo).

Estaba satisfecho con una solución simple: simplemente tome esta excepción y no haga nada, porque no necesitamos hacer ningún trabajo adicional, entonces nuestro wakelock no tiene nada.

Para hacer esto, debe importar las fuentes de la biblioteca de GCM en su proyecto, en lugar del archivo .jar ya compilado. Puede encontrar los orígenes de la biblioteca de GCM en la carpeta " $ Android_SDK_Home $ / extras / google / gcm / gcm-client / src " (debe descargarla primero con el Administrador de Android SDK).

A continuación, abra la clase GCMBaseIntentService , find line

sWakeLock.release();

y rodearlo con try-catch.

Debe tener un aspecto como este:

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

ACTUALIZACIÓN: Alternativamente, como se sugirió @fasti en su respuesta , puede usar el método mWakeLock.isHeld() para verificar si wakelock realmente mantiene este bloqueo.