Android RecognitionListener: onResults wird zweimal aufgerufen


10

Ich habe ein Projekt mit RecognitionListener in Kotlin geschrieben. Die Sprach-Text-Funktion war immer ein Erfolg und brachte keine Probleme mit sich.

Seit letzter Woche wurde die Funktion onResult zweimal aufgerufen. Am Projekt wurden keine Änderungen vorgenommen. Ich habe alte Versionen des Projekts (von vor Monaten) getestet und diese hatten das gleiche Problem.

Es gibt drei verschiedene Fälle:

  1. Kleiner Text (1 bis 8 Wörter) und SpeechRecognizer werden automatisch gestoppt -> onResult () zweimal aufgerufen;
  2. Großer Text (9 Wörter oder mehr) und SpeechRecognizer werden automatisch gestoppt -> Normales Verhalten (onResult () wird einmal aufgerufen);
  3. Beliebige Textgröße und SpeechRecognizer stopListening () -Funktion, die manuell (aus Code) aufgerufen wird -> Normales Verhalten.

Hier ist der Voice-Recognition-Sprach-Text-Klassencode:

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()
    }

listen (), endListening () und cancelListening () werden alle über eine Schaltfläche aufgerufen.


Ich habe das gleiche Problem, das Problem ist nur auf Samsung s8 mit API 9 - hier kann ich auch Teilergebnisse sehen, wenn die Erkennung läuft. Auf älteren Geräten ist dies nicht der Fall.
Uhr

Ich habe dieses Problem ab Android 7 gesehen ... Ich habe mein Projekt nicht einmal geändert ... es hat gerade erst begonnen.
Pedro Henrique Flores

"das problem liegt nur bei Samsung s8 mit api 9" - damit meinte ich in meinen tests auf
geräten die

1
Das gleiche Problem bei Pocophone F1 war meine Lösung, zu überprüfen, ob die Ergebnisse identisch sind, und dann das zweite Ergebnis zu ignorieren, wenn dies der
Lotan

Dies geschah erst gestern in einer meiner Apps. Ich habe einen Booleschen Wert hinzugefügt, damit der Code nur einmal ausgeführt werden kann, aber ich würde gerne erklären, warum er plötzlich damit begonnen hat. Irgendwelche Updates?
Gavin Wright

Antworten:



1

Dies geschah erst gestern in einer meiner Apps. Ich habe einen Booleschen Wert hinzugefügt, damit der Code nur einmal ausgeführt werden kann, aber ich würde gerne erklären, warum er plötzlich damit begonnen hat. Irgendwelche Updates?


0

Ich hatte das gleiche Problem und habe gerade ein boolesches Flag in meinen Code eingefügt, aber natürlich ist es eine vorübergehende Lösung und ich kenne die Ursache dieses Problems nicht.

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
            }
        }
    }

Bitte fügen Sie einen Beispielcode hinzu.
m02ph3u5
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.