2014-06-11 35 views
6

ho bisogno di avvertire l'utente di alcuni eventi per mezzo di:Come mantenere il vibratore all'infinito da un servizio o un ricevitore

  • vibrazioni
  • notifica

La vibrazione dovrebbe rimanere su indefinitamente finché l'utente non accetta la notifica.

Il problema è la vibrazione si interrompe quando il dispositivo va in stop. Ho letto le seguenti domande:
Allow phone to vibrate when screen turns off
Continue vibration even after the screen goes to sleep mode in Android

C'era an answer a una delle domande sopra menzionate dicendo che vibra senza modelli ha fatto il trucco. Così ho provato a chiamare la versione di Vibrator.vibrate che accetta i millisecondi anziché un modello con un numero elevato ma la vibrazione si arresta comunque.

Altre risposte suggeriscono di registrare un ricevitore sull'azione ACTION_SCREEN_OFF. Ciò mi consentirebbe di riprendere le vibrazioni se il dispositivo si mette in stato di riposo dopo l'avvio dell'allarme, ma non funzionerà se il dispositivo è già stato dormito.

Tuttavia, potrei far funzionare la cosa se prima potessi accendere lo schermo, quindi registrare il ricevitore per gestire qualsiasi evento di schermo che potrebbe accadere da lì in poi. Quindi ho provato ad acquisire un wake lock completo quando viene ricevuto l'evento di attivazione, prima di avviare il suono o la vibrazione, ma non funziona nonostante io stia utilizzando i flag FULL_WAKE_LOCK e ACQUIRE_CAUSES_WAKEUP. La parte di attivazione funziona, ma subito dopo il dispositivo torna a dormire. Mi piacerebbe pensare che il flag FULL_WAKE_LOCK non funzioni perché è stato deprecato in API 17, ma il mio dispositivo è un Samsung in esecuzione 4.1.2 che è API 16!

L'approccio consigliato sembra essere quello di utilizzare WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON ma questo dovrebbe essere chiamato da un'attività, e non ho alcuna schermata fino a quando l'utente non fa clic nella notifica, e se ciò accade il suono e la vibrazione dovrebbero già avere stato fermato

Quindi sembra un vicolo cieco.

Cos'altro potrei provare?

AGGIORNAMENTO:
Non ho avuto fortuna a mantenere lo schermo sempre acceso con i lucchetti, ma d'altra parte mi consentono di accendere lo schermo anche solo per pochi secondi. In realtà non ho bisogno di tenere lo schermo acceso, quindi sto registrando il ricevitore sull'azione Intent.ACTION_SCREEN_OFF, e quando lo schermo si spegne, il ricevitore riprende a vibrare. Questo ha funzionato bene nel Samsung, ma ora sono passato a un Huawei per continuare i test e il ricevitore non funziona.

UPDATE:
Ecco la traccia dello stack dell'eccezione nel dispositivo Huawei:

java.util.NoSuchElementException: Death link does not exist 
    at android.os.BinderProxy.unlinkToDeath(Native Method) 
    at com.android.server.VibratorService.unlinkVibration(VibratorService.java:294) 
    at com.android.server.VibratorService.removeVibrationLocked(VibratorService.java:284) 
    at com.android.server.VibratorService.cancelVibrate(VibratorService.java:213) 
    at android.os.IVibratorService$Stub.onTransact(IVibratorService.java:83) 
    at android.os.Binder.execTransact(Binder.java:338) 
    at dalvik.system.NativeStart.run(Native Method) 

risposta

1

Dopo alcuni test sono finalmente riuscito a farlo funzionare.

I Vibrator classe Hass due metodi:

  • vibrate (long[] pattern, int repeat)
  • vibrate (long milliseconds)

Il first one è l'unico modo di vibrare indefinitamente utilizzando l'API (passando 0 come secondo argomento). Ma questo ha dimostrato di irrompere in alcuni dispositivi (Huawei), come ho postato nella domanda. Non sto parlando della vibrazione arrestata dal sistema operativo quando il dispositivo va a dormire, questo è stato risolto usando un ricevitore più un blocco scia come descritto nella domanda. Sto parlando di eccezioni, causate da un'implementazione bug (la classe Vibrator è astratta).

Il second variant di questo metodo non accetta un modello e non consente una vibrazione indefinita, ma possiamo imbrogliarlo passando un numero molto grande di millisecondi come parametro. Funziona bene su alcuni dispositivi (Huawei) come the answer I cited in the question correttamente puntati, ma non funziona in altri (Samsung), dove l'implementazione ha un valore max predefinito che verrà utilizzato se il valore passato come parametro lo supera. Questo valore massimo è in realtà inferiore a un minuto e questo significa che non possiamo fare affidamento su questo approccio.

Così sono andato tutti fuori su questo e ha creato un servizio, dove ho vibrare manualmente a tempo indeterminato come questo:

while(vibrationActive){ 
     Vibrator.vibrate(1000); 
     Thread.sleep(1000); 
    } 

Il trucco ricevitore per rilevare quando lo schermo si spegne non è più necessaria. Ovviamente il sistema operativo continua a spegnere il vibratore quando questo accade, ma la successiva iterazione del ciclo riprenderà nuovamente a vibrare. Con questo approccio è possibile creare anche una sorta di pattern, se il tempo di sonno è maggiore del tempo di vibrazione, ma di nuovo questo pattern verrà interrotto in qualsiasi momento se lo schermo si spegne.

Un servizio dedicato solo per accendere e spegnere il vibratore in modo affidabile. Potete crederci? Circa 150 righe di codice (senza i test unitari) per qualcosa che avrebbe dovuto essere possibile con poche righe.

1

Ti intenzione di lasciare che il dispositivo di andare a dormire o no? Puoi acquisire un wakelock che riattiva lo schermo.

PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE); 
    WakeLock wl = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP | PowerManager.ON_AFTER_RELEASE, "myTAG"); 
    wl.acquire(LOCK_SCREEN_TIME_MINUTES * 60 * 1000); 

Che non funziona per voi? Dopo che è possibile mostrare la notifica, ma non sono sicuro dell'effetto, manterrà le vibrazioni. Sopra uno funziona su GalaxyTab 2 con Android 4.2.2 e HTC Hero con Android 2.3.4.

+0

Queste sono in realtà le mie bandiere, ad eccezione di "ON_AFTER_RELEASE", di cui non ho bisogno. E ciò che accade in questo Samsung è che in realtà si accende, ma dopo 1 o 2 secondi si spegne di nuovo senza che io abbia rilasciato il blocco. Non importa ora, perché in realtà non ho bisogno dello schermo tutto il tempo. Pubblicherò una risposta spiegando cosa ho fatto. –

+0

ok, aspettando la tua risposta, sono curioso. – Nexowski

+0

Appena pubblicato. –