2012-08-01 21 views
14

Per tutti gli utenti che utilizzano Android voice recognition API, c'era un comodo RecognitionListener che si poteva registrare e che spingeva vari eventi ai propri callback. In particolare, c'era il onBufferReceived(byte[]) seguente metodo:Perché RecognitionListener ha smesso di funzionare in JellyBean?

public abstract void onBufferReceived (byte[] buffer)

Dal: Livello API è stata ricevuta 8 Ulteriori suono. Lo scopo di questa funzione è consentire di dare un feedback all'utente relativamente all'audio catturato . Non vi è alcuna garanzia che questo metodo verrà chiamato.

Parametribuffer un tampone contenente una sequenza di big-endian 16 bit interi che rappresentano un singolo flusso audio canale. La frequenza di campionamento dipende dall'implementazione.

Anche se il metodo dichiara esplicitamente che non v'è alcuna garanzia che sarà chiamato, in ICS e prima che sarebbe effettivamente chiamato il 100% del tempo: abbastanza regolarmente, almeno, che concatenando tutti i byte ricevuto in questo modo, è possibile ricostruire l'intero flusso audio e riprodurlo.

Per qualche motivo, tuttavia, nell'SDK Jellybean, questo dispositivo ha smesso di funzionare automaticamente. Non ci sono avvisi di deprecazione e il codice è ancora compilato, ma lo onBufferReceived è ora mai chiamato. Tecnicamente questo non sta infrangendo la loro API (dal momento che dice che non c'è "nessuna garanzia" che verrà chiamato il metodo), ma chiaramente si tratta di un cambio di rottura per molte cose che dipendono da questo comportamento.

Qualcuno sa perché questa funzionalità è stata disabilitata e se c'è un modo per replicare il suo comportamento su Jellybean?

Chiarimento: mi rendo conto che l'intera RecognizerIntent cosa è un'interfaccia con più implementazioni (tra cui alcuni disponibili sul Play Store), e che essi possono decidere ogni cosa a che fare con RecognitionListener. Mi riferisco specificamente all'implementazione predefinita di Google che viene utilizzata dalla maggior parte dei telefoni Jellybean.

risposta

8

Google non chiama questo metodo l'app vocale Jelly Bean (QuickSearchBox). Semplicemente non nel codice. A meno che non ci sia un commento ufficiale da un ingegnere di Google, non posso dare una risposta definitiva "perché" l'hanno fatto. Ho cercato nei forum degli sviluppatori ma non ho visto commenti su questa decisione.

L'impostazione predefinita di ics per il riconoscimento vocale proviene da Google VoiceSearch.apk. Puoi decompilare questo apk e vedere e trovare vedere c'è un'attività per gestire un intento di azione * android.speech.action.RECOGNIZE_SPEECH *. In questo apk ho cercato "onBufferReceived" e ho trovato un riferimento ad esso in com.google.android.voicesearch.GoogleRecognitionService $ RecognitionCallback.

Con Jelly Bean, Google ha rinominato VoiceSearch.apk in QuickSearch.apk e ha apportato molte nuove aggiunte all'app (ad esempio la dettatura offline). Ci si aspetterebbe di trovare ancora una chiamata onBufferReceived, ma per qualche motivo è completamente sparita.

+0

Grazie per l'analisi approfondita che conferma che il problema è universale su Jellybean :) Immagino che l'unico modo per ottenere un risultato più definitivo sia ottenere un tecnico Google che spieghi perché questo è successo. Grazie! –

2

Anche io stavo usando il metodo onBufferReceived e sono rimasto deluso dal fatto che la chiamata (non garantita) al metodo sia stata rilasciata in Jelly Bean. Bene, se non riusciamo a catturare l'audio con onBufferReceived(), forse c'è la possibilità di eseguire un AudioRecord simultaneamente con il riconoscimento vocale. Qualcuno ha provato questo? Altrimenti, gli darò un vortice e riferirò.

+2

Dubito che sia possibile, ma mi piacerebbe sentire i tuoi risultati. –

+5

Beh, ho fatto un buon tentativo, ma sembra che l'esecuzione di un AudioRecord e SpeechRecognizer allo stesso tempo non funzionerà. Solo uno di questi può accedere al microfono. Quindi, tornando al bisogno di onBufferReceived() per funzionare .... andiamo su Google, fallo! –

0

Mi sono imbattuto nello stesso problema. Il motivo per cui non ho semplicemente accettato che "questo non funziona" è perché Google Nows "note-to-self" registra l'audio e lo invia a te. Quello che ho scoperto nel logcat durante l'esecuzione di -operation "nota-per-sé" era:

02-20 14:04:59.664: I/AudioService(525): AudioFocus requestAudioFocus() from [email protected][email protected] 

02-20 14:04:59.754: I/AbstractCardController.SelfNoteController(8675): #attach 
02-20 14:05:01.006: I/AudioService(525): AudioFocus abandonAudioFocus() from [email protected][email protected] 

02-20 14:05:05.791: I/ActivityManager(525): START u0 {act=com.google.android.gm.action.AUTO_SEND typ=text/plain cmp=com.google.android.gm/.AutoSendActivity (has extras)} from pid 8675 
02-20 14:05:05.821: I/AbstractCardView.SelfNoteCard(8675): #onViewDetachedFromWindow 

Questo mi fa belive che Google dispone l'audioFocus da Google Now (la regonizerIntent), e che usano un audio registratore o qualcosa di simile quando il tag Note-to-Self appare in onPartialResults. Non posso confermarlo, qualcuno ha provato a farlo funzionare?

0

Ho un servizio che implementa RecognitionListener e anch'io sovrascrivo il metodo suBufferReceived (byte []). Stavo indagando sul motivo per cui il riconoscimento vocale è molto più lento da chiamare suRisultati() su < = ICS. L'unica differenza che ho trovato è che onBufferReceived viene chiamato sui telefoni < = ICS. Su JellyBean, onBufferReceived() non viene mai chiamato e onResults() viene chiamato molto più veloce e sto pensando a causa dell'overhead per chiamare suBufferReceived ogni secondo o millisecondo. Forse questo è il motivo per cui l'hanno eliminato conBufferReceived()?

Problemi correlati