2012-04-02 25 views
62

Sto sviluppando un'applicazione per la mia tesi finale sull'informatica e ho bisogno di raccogliere e registrare i dati dell'accelerometro. Ho bisogno di acquisirlo per un giorno intero, quindi ci sono limiti di batteria (per esempio, non posso lasciare lo schermo acceso). Inoltre, questa non è un'applicazione mirata al mercato, quindi è abbastanza accettabile fare un serio hacking, anche la codifica C/C++ di basso livello, se necessario.L'accelerometro Android non funziona quando lo schermo è spento

È risaputo che su molti dispositivi gli ascoltatori di eventi accelerometrici interrompono la generazione di eventi quando lo schermo si spegne (alcuni collegamenti relativi a questo problema: http://code.google.com/p/android/issues/detail?id=3708, Accelerometer stops delivering samples when the screen is off on Droid/Nexus One even with a WakeLock). Ho cercato accuratamente alcune alternative, alcune includono soluzioni alternative che non funzionano per il mio dispositivo (LG P990, stock ROM).

Quindi, ciò che accade è questo: Quando si registra un listener di eventi per sensore accelerometro Android in un servizio, funziona fino allo spegnimento dello schermo. Ho già provato a registrare eventListener su un servizio, su un IntentService, provato ad acquisire WakeLock. Per quanto riguarda i wakelock, posso verificare che il servizio sia ancora in esecuzione guardando l'output di LOGcat, ma sembra che l'accelerometro sia messo in modalità di sospensione. Una delle soluzioni presentate in alcuni dei collegamenti è quello di annullare la registrazione e ri-registrare il listener di eventi periodicamente utilizzando il filo di un IntentService come in questo frammento di codice muggito

synchronized private static PowerManager.WakeLock getLock(Context context) { 
    if (lockStatic==null) { 
     PowerManager mgr=(PowerManager)context.getSystemService(Context.POWER_SERVICE); 

     lockStatic = mgr.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,NAME); 
     lockStatic.setReferenceCounted(true); 
    } 

    return(lockStatic); 
} 

@Override 
protected void onHandleIntent(Intent intent) { 

    sensorManager=(SensorManager) getSystemService(SENSOR_SERVICE); 
    sensorManager.unregisterListener(this); 
    sensorManager.registerListener(this, sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_NORMAL); 


    synchronized (this) { 
     boolean run = true; 
     while (run){ 
      try { 
       wait(1000); 
       getLock(AccelerometerService.this).acquire(); 
       sensorManager=(SensorManager) getSystemService(SENSOR_SERVICE); 
       sensorManager.unregisterListener(this); 
       sensorManager.registerListener(this, sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_NORMAL); 
       Log.d("Accelerometer service", "tick!"); 

      } catch (Exception e) { 
       run = false; 
       Log.d("Accelerometer service", "interrupted; cause: " + e.getMessage()); 


      } 
     } 
    }  
} 


@Override 
public void onSensorChanged(SensorEvent event) { 
    Log.d("accelerometer event received", "xyz: "+ event.values[0] + "," + event.values[1] + "," + event.values[2]); 
} 

che rende davvero l'onSensorChange essere chiamato ogni volta che ci annullare la registrazione/registrare l'ascoltatore. Il problema è che l'evento ricevuto contiene sempre gli stessi valori, indipendentemente dal fatto che io scuoti il ​​dispositivo.

Quindi, in pratica le mie domande sono: (porto con me, ho quasi terminato: P)

  1. è possibile avere accesso a basso livello (C/C++ approccio) per l'hardware accelerometro SENZA registrarsi ad un ascoltatore di eventi?

  2. c'è qualche altra soluzione o hack?

  3. qualcuno con un telefono più aggiornato potrebbe verificare se il problema persiste nel firmware 3.0 e versioni successive?

[UPDATE]

Purtroppo, sembra essere un bug con alcuni cellulari. Maggiori dettagli nella mia risposta.

+1

Ciao. Ho appena testato il problema con il mio HTC Sensation (ICS). Sia l'accelerometro che il sensore del campo magnetico continuavano a riportare i valori con lo schermo spento. Inoltre, hai controllato la soluzione alternativa descritta nel commento [46] (http://code.google.com/p/android/issues/detail?id=3708)? – Renard

+0

Grazie per il feedback Renard. Riguardo al commento 46, ho anche provato che, è quasi lo stesso approccio come eseguire un thread che annulla la registrazione/registrazione di un listener di eventi .. Ma con il mio dispositivo ottengo solo valori fissi per l'accelerometro ogni volta che spengo il mio display .. Grazie anche per averlo testato su ICS ... è bello sapere che funziona come dovrebbe, purtroppo non c'è ancora ICS per LG P990 =/ – martin

+1

Potrebbe essere utile provare a risolvere il problema da altro lato: acquisire il blocco dello schermo, ma allo stesso tempo ridurre la luminosità dello schermo a zero per risparmiare la batteria? Certo, non funziona quando si spegne lo schermo con il pulsante di accensione, ma in questo caso si può provare a riattivare il dispositivo per impedire il blocco dello schermo. –

risposta

61

Fondamentalmente, è un problema con il mio telefono. Altri utenti hanno riferito che questo accade anche con i loro telefoni, di marche diverse ma con la stessa versione di Android. Altre persone non hanno alcun problema - indicando con forza che questo non è un problema con la versione di Android, ma dalle implementazioni di ciascuna azienda per i loro driver hardware.

Ho bisogno di dati di accelerometro costanti consegnati e non posso avere un dongle per misurare questi dati per me - Ho un Arduino con Bluetooth e accelerometro, quindi avrei potuto implementare questa soluzione. Così ho deciso che la soluzione temporanea per il mio cellulare era quella di lasciare lo schermo acceso (in grigio) e ignorare il consumo della batteria.Più avanti eseguirò i test per l'utilizzo della batteria usando un altro telefono Android che funziona con lo schermo spento.

Maggiori informazioni sul bug

ho studiato un po 'di più e ha trovato segnalazioni di altri utenti Android e penso che forse ho capito cosa sta succedendo. La libreria libsensors.so che ha i driver per i sensori del telefono non è sviluppata da Google ma da ogni venditore di cellulari - ovviamente, perché ogni cellulare ha il suo specifico hardware. Google fornisce solo un file di intestazione C in modo che gli sviluppatori sappiano cosa devono implementare. In alcune implementazioni per questi driver, gli sviluppatori disattivano semplicemente l'accelerometro quando lo schermo si spegne, impedendo così al listener di eventi del sensore di ricevere nuovi eventi.

Ho anche provato questo con CyanogenMod RC7.2 ma non ha funzionato neanche, perché i driver degli accelerometri sono originali di LG.

e-mail scambiate con il dipartimento risorse umane di LG

ho mandato una e-mail agli sviluppatori del LG P990 e finalmente alcune risposte concrete! Questo può essere di grande aiuto per alcune persone come me che stanno vivendo questi problemi con Android. Ho scritto la seguente domanda

Ciao! Sto sviluppando la mia tesi in informatica e attualmente I sto recuperando i dati dall'hardware dell'accelerometro. A partire da ora, ho scoperto che gli accelerometri non inviano eventi quando lo schermo è spento, quindi anche quando afferro un wakelock da uno dei miei programmi, posso verificare che il mio programma sia ancora in esecuzione (tramite l'output di LOGcat )) ma non viene emesso alcun evento di accelerometro . Devo oscurare lo schermo (cosa che non posso permettermi di fare, , la batteria si scarica troppo velocemente) per iniziare a ricevere nuovamente gli eventi dell'accelerometro . Ho anche provato ad accedervi tramite il codice nativo C , registrandomi sugli eventi dell'accelerometro ma il risultato è stato lo stesso , l'accelerometro non ha gettato alcun valore, anche se ero che ruotava il mio dispositivo. Quindi mi chiedevo se avrei potuto accedere direttamente all'hardware, con codice nativo, , senza registrarmi a un listener . È possibile? In tal caso, potresti gentilmente fornire ulteriori consigli ? Gradirei qualsiasi aiuto! Martin

Per quello che ho ricevuto questa risposta:

Caro Martin, Abbiamo ricevuto la risposta da Dev. Squadra. Hanno detto che tu non puoi ottenere l'evento accelerometro mentre lo schermo del telefono è spento. Perché il livello HAL non ha implementato il percorso sysFS per ottenere l'evento H/W come l'accelerometro e non è disponibile alcuna API pubblica per ottenere l'evento. Grazie. I migliori Saluti. (Sean Kim)

poi ho rimandato una e-mail, dicendo fra l'altro, che ho considerato questo un bug, dal momento che uno dovrebbe avere accesso a tutto l'hardware al momento di acquistare un blocco scia:

[...] Ho fatto questa domanda perché ho alcuni amici che hanno anche telefoni Android con la stessa versione di pan di zenzero, ma da altri telefoni cellulari , e alcuni di loro hanno riferito di ricevere gli eventi da gli accelerometri quando lo schermo è spento. Ho letto su alcuni forum che questo bug - lo considero un bug, dal momento che quando acquisisco un Wakelock mi aspetto di avere qualche elaborazione in corso - dipende da i driver dei sensori che i produttori implementano per i loro cellulari. c'è qualche possibilità che questi driver possano essere aggiornati o questo bug venga corretto ad un certo punto? Questo mi avrebbe aiutato enormemente con il mio lavori in corso [...]

E poi ho ricevuto questa risposta:

Nella mia conoscenza da Dev. Squadra, non è un bug. Questo è un numero illimitato di questo telefono a causa dell'architettura H/W. Abbiamo bisogno di riprogettare l'architettura e il driver del dispositivo HAL per supportare la tua richiesta. Ma, come lo sai, lo sa che è troppo difficile a causa della mancanza di risorse. Stiamo provando a aiutandoti con tutti i nostri sforzi ma non possiamo supportare la tua richiesta come ho menzionato I . (Sean Kim)

Quindi a quanto pare sanno di questo, ma non stanno cercando di correggere questo perché o non pensano che sia un bug - che credo ancora sia un difetto logico - o non lo fanno avere il tempo/le risorse per correggerlo.

Riga inferiore Se si dispone di un telefono cellulare che non invia eventi di accelerometro con lo schermo spento, provare ad aggiornare il firmware. Se questo non risolve e vuoi davvero fare un po 'di hacking, reimplementa il tuo livello hardware - suggerimento: probabilmente è qualcosa che ha a che fare con libsensors.so.

+2

Grazie martin per questa informazione molto completa. Ciò di cui abbiamo veramente bisogno è una lista che indichi quali telefoni supportano gli eventi accelerometrici sullo schermo, perché le persone potrebbero volere queste informazioni prima di acquistare (come me - ne ho bisogno). Forse una wiki, le persone potrebbero testare i loro telefoni e aggiornare la lista. C'è una lista come questa ovunque? – Fletch

+8

OK Ho creato un elenco: http://www.saltwebsites.com/2012/android-accelerometers-screen-off – Fletch

+2

Una risposta sorprendente e davvero completa. Darebbe più di un pollice in su :) Ad un certo punto si può risolvere il problema ascoltando gli eventi SCREEN_OFF e SCREEN_ON, acquisendo un nuovo wake lock e riavviando il servizio dell'accelerometro. Ma di nuovo, funziona solo su alcuni telefoni. – LambergaR

0

Detesto doverti deludere, ma alcuni dispositivi non mantengono l'accelerometro acceso mentre sono in modalità di sospensione. Alcuni lo fanno, altri no. È possibile controllare qualsiasi app per la perdita di peso del contapassi in negozio la maggior parte di essi dichiara esplicitamente che questo non funzionerà su alcuni dispositivi.

2

ho incontrato problemi simili con il Samsung Nexus esecuzione Android 4.0.2 utilizzando altri servizi di sistema che si fermano/pausa, mentre lo schermo è spento, anche se un PARTIAL_WAKE_LOCK è acquisito. La mia soluzione era quella di utilizzare un SCREEN_DIM_WAKE_LOCK come in:

lockStatic = mgr.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK,NAME); 

Sarebbe molto meglio avere lo schermo completamente fuori, ma almeno questa soluzione funziona anche se sarebbe ancora meglio se avessi potuto limitare utilizzando un SCREEN_DIM_WAKE_LOCK solo quei dispositivi/sistemi operativi che lo richiedono.

6

Non sono sicuro che questo possa effettivamente essere d'aiuto, ma ho trovato un problema (Non sono sicuro di quanto sarà utile per risparmiare la batteria).

Utilizzo di bash Ho un ciclo while cating /sys/devices/virtual/accelerometer/accelerometer/acc_file e quando si spegne lo schermo tramite il pulsante di alimentazione, l'uscita continua, ma viene congelata. (Ho avuto sshd in esecuzione in un chroot quindi l'essere in grado di vederlo.)

Tuttavia, in eco 0 > /sys/devices/platform/msm_fb.196609/leds/lcd-backlight/brightness. Lo schermo si spegne e l'uscita è continua.

Questo è su un SGH-T589W, con Android versione 2.3.6.

+0

Hai realizzato questo codice? – baash05

+0

Huh! Ben giocato, non pensare agli script di bash. Penso che proverò più tardi, anche se ho già finito questo lavoro molto tempo fa .. Grazie per l'input! – martin

0

Se l'opzione di sveglia parziale non è disponibile per il telefono, significa che il driver per il sensore ha abilitato early_suspend.

Ci sono due opzioni.

1: Disabilitare EARLY_SUSPEND nel driver

2: Aggiungere un tempo bandiera di esecuzione che possono enable/disable early_suspend funzionalità a livello di driver.

ex. cat/sys/module/earlysuspend/sensor 1/0

IMO la seconda opzione avrebbe dovuto essere lì fin dall'inizio.

2

Ho applicato il PARTIAL_WAKE_LOCK e ha funzionato come un incantesimo per me. Testato su OS 5.0, 6.0 & 7.0. Ecco il mio codice per acquisire e rilasciare il blocco della sveglia. Fare attenzione ha aumentato il drenaggio della batteria, in modo da acquisire e rilasciarlo in modo intelligente.

public void acquireWakeLock() { 
    final PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); 
    releaseWakeLock(); 
    //Acquire new wake lock 
    mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "PARTIAL_WAKE_LOCK"); 
    mWakeLock.acquire(); 
} 

public void releaseWakeLock() { 
    if (mWakeLock != null && mWakeLock.isHeld()) { 
     mWakeLock.release(); 
     mWakeLock = null; 
    } 
} 

Rif: https://developer.android.com/training/scheduling/wakelock.html#cpu

Sto lavorando su uno sdk previsione, che fanno uso di sensori del dispositivo (accelerometro/giroscopio) di dati e predice gli eventi utente. Ho sperimentato lo stesso problema.

Problemi correlati