2011-05-07 10 views
20

Las variables pm y keepScreenOn están definidas globalmente.WakeLock finalizado mientras aún estaba ocupado

me agarra el PowerManager.WakeLock en mi método OnCreate:

pm = (PowerManager) getSystemService(Context.POWER_SERVICE); 
keepScreenOn = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_LOCK,"tpd"); 

en mi onStart, onResume y onRestart agarro la cerradura con

if (keepScreenOn == null) { 
    keepScreenOn = pm.newakeLock(PowerManager,SCREEN_BRIGHT_LOCK,"tpd"); 
} 
keepScreenOn.acquire(); 

en mi OnDestroy, onPause y onStop Suelte el bloqueo con:

if (keepScreenOn != null) { 
    keepScreenOn.release(); 
    keepScreenOn = null 
} 

Después de que mi aplicación sale, aparece una pantalla de error y adb compl AINS que

java.lang.Exception: WakeLock finalizado al tiempo que celebró: tpd

Rastreo muestra que solté la cerradura antes de la salida. ¿Qué me he perdido?

No hay manera de salir de la aplicación sin tener que cruzar al menos uno de , onStop o onDestroy. Puedo ver que la aplicación llama a release() tan a menudo como se llama a acquire() así que aunque el contador de tiempo se cuente como referencia, todavía debería tener cero referencias.

+0

Puede ser que no esté relacionado con su problema, pero ¿por qué está creando y liberando el bloqueo en tantos lugares? ¿Por qué no hacerlo solo en onResume y onPause? – Olegas

+0

Lo intenté. Luego rastreé cada rutina onXXX. Luego lo agregué –

+0

¿Su variable 'keepScreenOn' se declara solo una vez en una clase? ¿Hay algunas otras declaraciones con menor alcance (es decir, declaradas en el método). – Olegas

Respuesta

0

No, solo hay una declaración en el ámbito global y todas las llamadas a adquirido() y release() se producen en ese ámbito. I println cuando suceden y adquiere() una vez y la versión se produce una vez.

27

Ok, creo que he encontrado el problema.

El WakeLock es una referencia contada. Eso significa que si se produce un segundo acquire() , se reducirá el recuento de referencias. Cada llamada a acquire() necesita ser protegido por una llamada a isHeld() como en:

if ((keepScreenOn != null) &&   // we have a WakeLock 
    (keepScreenOn.isHeld() == false)) { // but we don't hold it 
    keepScreenOn.acquire(); 
} 

había asumido que acquire() en un bloqueo Sostuve no hicieron nada por lo múltiples llamadas acquire() causó el problema. Como el recuento de referencia no es cero, el GC arroja un error.

Cuestiones relacionadas