2011-02-19 8 views
6

Nella mia app, nel metodo onCreate() dell'attività principale sto creando un wake lock in modo che la CPU continui a funzionare se il telefono continua standb/schermo si spegne.Android: il blocco Wake non si acquisisce correttamente, l'app deve continuare a essere in standby

Anche nel metodo onCreate ho intenzione di creare un servizio che utilizza l'accelerometro. Questo servizio deve essere continuamente attivo mentre l'app è aperta e monitorare i valori dell'accelerometro (so che questo non va bene per la batteria, ma ne ho bisogno per farlo). Ecco il mio codice al momento e il servizio inizia bene.

public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 

     PowerManager pm = (PowerManager) getSystemService(POWER_SERVICE); 
     PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "Howaya"); 
     wl.acquire(); 

     if (appStart == true) 
     { 
      Intent AccelService = new Intent(this, Accelerometer.class); 
      AccelService.putExtra("unreg", false); 
      startService(AccelService); 
     } 
     appStart = false; 
    } 

Ho il seguente set di autorizzazioni nel mio manifesto -

<uses-permission android:name="android.permission.WAKE_LOCK" /> 

Ho provato questo con diverse serrature - Oscura schermo e la luminosità piena inutilmente troppo. La mia uscita sul logcat è qui -

F/PowerManager(15628): android.util.Log$TerribleFailure: WakeLock finalized while still held: Howaya 
F/PowerManager(15628): at android.util.Log.wtf(Log.java:260) 
F/PowerManager(15628): at android.util.Log.wtf(Log.java:239) 
F/PowerManager(15628): at android.os.PowerManager$WakeLock.finalize(PowerManager.java:329) 
F/PowerManager(15628): at dalvik.system.NativeStart.run(Native Method) 

ho visto gente che dice che wakelocks parziali non funzionano come dovrebbero fare, come ad esempio questo link Google standby error page, ma questo è stato rilasciato e ha chiuso l'anno scorso quindi non so è che il caso, qualcuno può aiutare qui per favore? Ho un desiderio HTC anche per quanto riguarda l'ultimo punto, grazie.

risposta

2

Nella mia app, nel metodo onCreate() dell'attività principale sto creando un wake lock in modo che la CPU continui a funzionare se il telefono si accende standb/lo schermo si spegne.

Utilizzare invece android:keepScreenOn in uno dei widget del proprio layout. Questo è molto, molto più sicuro per le attività rispetto a quello manuale con uno WakeLock. Inoltre, non è necessaria l'autorizzazione WAKE_LOCK, IIRC.

La mia uscita sul logcat è qui

Tale errore è perché non hai mai rilascia il WakeLock. Si prega di non perdere WakeLocks.

Ora, sei riuscito a scrivere tutta questa prosa e includere tutte queste inserzioni, e hai dimenticato una piccola cosa: effettivamente dirci qual è la tua domanda. Questo è un elemento piuttosto importante per un sito di domande e risposte come StackOverflow. E, no, "qualcuno può aiutare qui per favore?" non conta come una domanda quando non si definisce mai quale "aiuto" si sta cercando di ricevere.

+0

Ok scusa se non sono stato chiaro e grazie per la risposta. La mia domanda era: come posso far funzionare una wakelock sul mio telefono in modo che la mia app funzioni mentre lo schermo è ancora spento, poiché il codice che sto usando sopra non funziona. Preferirei non avere lo schermo acceso in modo tale da non sprecare tanta batteria e non dover utilizzare il widget nel caso in cui avessi deciso di metterlo sul mercato (quindi altri utenti avrebbero dovuto usare il widget) – bobby123

+1

@ bobby123 : Un'attività non può avere un'esigenza logica per un 'WakeLock' parziale. Un * servizio * potrebbe avere bisogno di un 'WakeLock' parziale, ma non di un'attività, il cui unico scopo è quello di visualizzare elementi sullo schermo. Quindi, prendi il tuo 'WakeLock' dall'attività e nel servizio (aggiustando la tua logica di business per farlo corrispondere), o usa' android: keepScreenOn'. Acquisisci il tuo 'WakeLock' in' onCreate() 'del tuo servizio e rilascialo in' onDestroy() '. Usa 'startForeground()' in modo che il tuo servizio non sia oscurato e offri all'utente un modo semplice per raggiungere un'attività per interrompere il servizio. – CommonsWare

+0

Questo è quello che volevo sapere, grazie. Sposterò il wake lock al servizio perché è quello per cui ho davvero bisogno. Ho un pulsante di menu per l'utente per terminare il servizio in qualsiasi momento. Un'ultima domanda, per favore, sai se il metodo onSensorChanged() per l'accelerometro funziona ancora mentre è attivo un blocco parziale della sveglia o si tratta ancora di un problema con Google? – bobby123

9

Il problema si verifica perché l'oggetto WakeLock è una variabile con ambito locale all'interno del metodo OnCreate. Dopo l'esecuzione del metodo, l'oggetto WakeLock non viene più referenziato, quindi idoneo per la garbage collection. Se il GC Dalvik si verifica - l'oggetto è pronto per la finalizzazione - e il codice interno del finalizzatore ti avverte, quel WakeLock è ancora trattenuto - e attivo - ma sarà convertito in GC. Devi ottenere un nuovo oggetto WakeLock e assegnarlo a un campo di tipo WakeLock nella classe derivata dalla tua attività. Leggi di programmazione orientata agli oggetti e Garbage Collector: capirai il problema.

0

Come ha detto @Michal P, si acquisisce un wakelock nel metodo onCreate, ma non lo si rilascia mai.

Quando GC esegue la scansione di questo oggetto di riferimento zero, chiama il metodo di finalizzazione predefinito, ma in realtà è attivo.

@Override 
    protected void finalize() throws Throwable { 
     synchronized (mToken) { 
      if (mHeld) { 
       Log.wtf(TAG, "WakeLock finalized while still held: " + mTag); 
       Trace.asyncTraceEnd(Trace.TRACE_TAG_POWER, mTraceName, 0); 
       try { 
        mService.releaseWakeLock(mToken, 0); 
       } catch (RemoteException e) { 
       } 
      } 
     } 
    }