Android RecognitionListener: onResults chiamato due volte


10

Ho un progetto usando RecognitionListener scritto in Kotlin. La funzione di sintesi vocale è sempre stata un successo e non ha mai presentato problemi.

Dalla scorsa settimana, la funzione onResult ha iniziato a essere chiamata due volte. Non sono state apportate modifiche al progetto. Ho testato le vecchie versioni del progetto (da mesi) e quelle avevano lo stesso problema.

Esistono tre casi diversi:

  1. Testo piccolo (da 1 a 8 parole) e SpeechRecognizer arrestati automaticamente -> onResult () chiamato due volte;
  2. Testo grande (almeno 9 parole) e SpeechRecognizer arrestati automaticamente -> Comportamento normale (onResult () chiamato una volta);
  3. Qualsiasi dimensione del testo e la funzione stopListening () SpeechRecognizer chiamata manualmente (dal codice) -> Comportamento normale.

Ecco il codice della classe di sintesi vocale VoiceRecognition:

class VoiceRecognition(private val activity: Activity, language: String = "pt_BR") : RecognitionListener {

    private val AudioLogTag = "AudioInput"

    var voiceRecognitionIntentHandler: VoiceRecognitionIntentHandler? = null
    var voiceRecognitionOnResultListener: VoiceRecognitionOnResultListener? = null //Must have this
    var voiceRecognitionLayoutChanger: VoiceRecognitionLayoutChanger? = null

    var isListening = false

    private val intent: Intent
    private var speech: SpeechRecognizer = SpeechRecognizer.createSpeechRecognizer(activity)

    init {
        speech.setRecognitionListener(this)

        intent = Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH)
        intent.putExtra(
            RecognizerIntent.EXTRA_LANGUAGE_MODEL,
            RecognizerIntent.LANGUAGE_MODEL_FREE_FORM
        )
        intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, language)
    }

    //It is important to put this function inside a clickListener
    fun listen(): Boolean {
        if (ContextCompat.checkSelfPermission(activity, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(activity, arrayOf(Manifest.permission.RECORD_AUDIO), 1)
            return false
        }

        speech.startListening(intent)

        Log.i(AudioLogTag, "startListening")

        return true
    }

    //Use this if you want to stop listening but still get recognition results
    fun endListening(){
        Log.i(AudioLogTag, "stopListening")

        speech.stopListening()
        isListening = false
    }

    fun cancelListening(){
        Log.i(AudioLogTag, "cancelListening")

        speech.cancel()
        voiceRecognitionLayoutChanger?.endListeningChangeLayout()
        isListening = false
    }

    override fun onReadyForSpeech(p0: Bundle?) {
        Log.i(AudioLogTag, "onReadyForSpeech")

        voiceRecognitionLayoutChanger?.startListeningChangeLayout()
        isListening = true
    }

    override fun onRmsChanged(p0: Float) {
//        Log.i(AudioLogTag, "onRmsChanged: $p0")
//        progressBar.setProgress((Int) p0)
    }

    override fun onBufferReceived(p0: ByteArray?) {
        Log.i(AudioLogTag, "onBufferReceived: $p0")
    }

    override fun onPartialResults(p0: Bundle?) {
        Log.i(AudioLogTag, "onPartialResults")
    }

    override fun onEvent(p0: Int, p1: Bundle?) {
        Log.i(AudioLogTag, "onEvent")
    }

    override fun onBeginningOfSpeech() {
        Log.i(AudioLogTag, "onBeginningOfSpeech")
    }

    override fun onEndOfSpeech() {
        Log.i(AudioLogTag, "onEndOfSpeech")

        voiceRecognitionLayoutChanger?.endListeningChangeLayout()
        isListening = false
    }

    override fun onError(p0: Int) {
        speech.cancel()
        val errorMessage = getErrorText(p0)
        Log.d(AudioLogTag, "FAILED: $errorMessage")
        voiceRecognitionLayoutChanger?.endListeningChangeLayout()
        isListening = false
    }

    override fun onResults(p0: Bundle?) {

        val results: ArrayList<String> = p0?.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION) as ArrayList<String>

        Log.i(AudioLogTag, "onResults -> ${results.size}")

        val voiceIntent: Int? = voiceRecognitionIntentHandler?.getIntent(results[0])
        if (voiceIntent != null && voiceIntent != 0) {
            voiceRecognitionIntentHandler?.handle(voiceIntent)
            return
        }

        voiceRecognitionOnResultListener!!.onResult(results[0])
    }

    private fun getErrorText(errorCode: Int): String {
        val message: String
        when (errorCode) {
            SpeechRecognizer.ERROR_AUDIO -> message = "Audio recording error"
            SpeechRecognizer.ERROR_CLIENT -> message = "Client side error"
            SpeechRecognizer.ERROR_INSUFFICIENT_PERMISSIONS -> message = "Insufficient permissions"
            SpeechRecognizer.ERROR_NETWORK -> message = "Network error"
            SpeechRecognizer.ERROR_NETWORK_TIMEOUT -> message = "Network timeout"
            SpeechRecognizer.ERROR_NO_MATCH -> message = "No match"
            SpeechRecognizer.ERROR_RECOGNIZER_BUSY -> message = "RecognitionService busy"
            SpeechRecognizer.ERROR_SERVER -> message = "Error from server"
            SpeechRecognizer.ERROR_SPEECH_TIMEOUT -> message = "No speech input"
            else -> message = "Didn't understand, please try again."
        }
        return message
    }

    //Use it in your overriden onPause function.
    fun onPause() {
        voiceRecognitionLayoutChanger?.endListeningChangeLayout()
        isListening = false

        speech.cancel()
        Log.i(AudioLogTag, "pause")
    }

    //Use it in your overriden onDestroy function.
    fun onDestroy() {
        speech.destroy()
    }

hear (), endListening () e cancelListening () sono tutti chiamati da un pulsante.


Sto riscontrando lo stesso problema, il problema è solo su Samsung S8 con API 9 - qui posso vedere anche risultati parziali quando è in corso il riconoscimento. Sui dispositivi più vecchi non lo provo.
marcinj,

Ho visto questo problema da Android 7 e versioni successive ... Non ho nemmeno cambiato il mio progetto .. è appena iniziato.
Pedro Henrique Flores,

"il problema è solo su Samsung S8 con API 9" - con questo intendevo nei miei test sui dispositivi che ho
marcinj

1
stesso problema su Pocophone F1, la mia soluzione era quella di verificare se i risultati sono identici, quindi ignorare il secondo risultato se lo sono
Lotan

Questo è appena iniziato in una delle mie app ieri. Ho aggiunto un valore booleano per consentire l'esecuzione del codice una sola volta, ma mi piacerebbe una spiegazione sul perché all'improvviso ha iniziato a farlo. Nessun aggiornamento?
Gavin Wright,

Risposte:



1

Questo è appena iniziato in una delle mie app ieri. Ho aggiunto un valore booleano per consentire l'esecuzione del codice una sola volta, ma mi piacerebbe una spiegazione sul perché all'improvviso ha iniziato a farlo. Nessun aggiornamento?


0

Ho avuto lo stesso problema e ho appena aggiunto una bandiera booleana nel mio codice, ma ovviamente è una soluzione temporanea e non conosco l'origine di questo problema.

object : RecognitionListener {

        var singleResult = true

        override fun onResults(results: Bundle?) {
            if (singleResult) {
                results?.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION).let {
                    // do something with result
                }
                // next result will be ignored
                singleResult = false
            }
        }
    }

Aggiungi un codice di esempio.
m02ph3u5
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.