Android RecognitionListener: onResults dipanggil dua kali


10

Saya punya proyek menggunakan RecognitionListener yang ditulis di Kotlin. Fungsi bicara-ke-teks selalu sukses dan tidak pernah menghadirkan masalah.

Sejak minggu lalu, fungsi onResult mulai dipanggil dua kali. Tidak ada perubahan yang dibuat pada proyek. Saya menguji versi lama proyek (dari bulan lalu) dan mereka memiliki masalah yang sama.

Ada tiga kasus berbeda:

  1. Teks kecil (1 hingga 8 kata) dan SpeechRecognizer dihentikan secara otomatis -> onResult () dipanggil dua kali;
  2. Teks besar (9 kata atau lebih) dan SpeechRecognizer dihentikan secara otomatis -> Perilaku normal (onResult () dipanggil sekali);
  3. Setiap ukuran teks dan fungsi StopListening () SpeechRecognizer disebut secara manual (dari kode) -> Perilaku normal.

Berikut adalah kode kelas bicara-ke-teks 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()
    }

Listen (), endListening () dan cancelListening () semuanya dipanggil dari sebuah tombol.


Saya memiliki masalah yang sama, masalahnya hanya pada Samsung s8 dengan api 9 - di sini saya dapat melihat juga hasil parsial ketika pengakuan sedang berlangsung. Pada perangkat yang lebih lama saya tidak mengalami ini.
marcinj

Saya melihat masalah ini dari Android 7 dan di atas ... Saya bahkan tidak mengubah proyek saya .. itu baru saja mulai terjadi.
Pedro Henrique Flores

"masalahnya hanya pada Samsung s8 dengan api 9" - maksud saya dalam tes pada perangkat yang saya miliki
marcinj

1
masalah yang sama pada Pocophone F1, solusi saya adalah untuk memeriksa apakah hasilnya identik, lalu abaikan hasil kedua jika mereka
Lotan

Ini baru mulai terjadi di salah satu aplikasi saya kemarin. Saya menambahkan boolean untuk memungkinkan kode untuk mengeksekusi hanya sekali, tapi saya ingin penjelasan mengapa tiba-tiba mulai melakukan ini. Adakah pembaruan?
Gavin Wright

Jawaban:



1

Ini baru mulai terjadi di salah satu aplikasi saya kemarin. Saya menambahkan boolean untuk memungkinkan kode untuk mengeksekusi hanya sekali, tapi saya ingin penjelasan mengapa tiba-tiba mulai melakukan ini. Adakah pembaruan?


0

Saya memiliki masalah yang sama dan saya baru saja menambahkan bendera boolean dalam kode saya, tetapi tentu saja ini adalah solusi sementara dan saya tidak tahu sumber masalah ini.

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

Silakan tambahkan beberapa kode contoh.
m02ph3u5
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.