Android RecognitionListener: onResults ถูกเรียกสองครั้ง


10

ฉันมีโครงการที่ใช้ RecognitionListener เขียนใน Kotlin ฟังก์ชั่นพูดเป็นข้อความประสบความสำเร็จและไม่เคยมีปัญหาใด ๆ

ตั้งแต่สัปดาห์ที่แล้วฟังก์ชั่น onResult เริ่มถูกเรียกสองครั้ง ไม่มีการเปลี่ยนแปลงใด ๆ ในโครงการ ฉันทดสอบเวอร์ชันเก่าของโครงการ (จากเดือนก่อน) และสิ่งเหล่านั้นมีปัญหาเดียวกัน

มีสามกรณีที่แตกต่างกัน:

  1. ข้อความขนาดเล็ก (1 ถึง 8 คำ) และ SpeechRecognizer จะหยุดโดยอัตโนมัติ -> onResult () เรียกว่าสองครั้ง;
  2. ข้อความขนาดใหญ่ (9 คำขึ้นไป) และ SpeechRecognizer ถูกหยุดโดยอัตโนมัติ -> พฤติกรรมปกติ (onResult () เรียกว่าหนึ่งครั้ง);
  3. ขนาดข้อความใด ๆ และฟังก์ชั่น SpeechRecognizer stopListening () เรียกว่าด้วยตนเอง (จากรหัส) -> พฤติกรรมปกติ

นี่คือรหัสคลาสของคำพูดเป็นข้อความแบบ 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 () และ cancelListening () ถูกเรียกจากปุ่มทั้งหมด


ฉันมีปัญหาเดียวกันปัญหาอยู่ที่ Samsung s8 กับ api 9 เท่านั้น - ที่นี่ฉันสามารถเห็นผลลัพธ์บางส่วนเมื่อการรับรู้อยู่ในระหว่างดำเนินการ สำหรับอุปกรณ์รุ่นเก่าฉันไม่เคยเจอสิ่งนี้
marcinj

ฉันเห็นปัญหานี้จาก Android 7 ขึ้นไป ... ฉันไม่ได้เปลี่ยนโครงการของฉัน .. มันเพิ่งเริ่มเกิดขึ้น
Pedro Henrique Flores

"ปัญหาที่เกิดขึ้นเป็นเพียงบน Samsung s8 กับ API 9" - โดยที่ฉันหมายความว่าในการทดสอบของฉันบนอุปกรณ์ที่ฉันมี
marcinj

1
ปัญหาเดียวกันกับ Pocophone F1, วิธีแก้ปัญหาของฉันคือการตรวจสอบว่าผลลัพธ์เหมือนกัน, จากนั้นให้ละเว้นผลลัพธ์ที่สองหากพวกเขาเป็น
Lotan

สิ่งนี้เพิ่งเริ่มเกิดขึ้นในหนึ่งในแอพของฉันเมื่อวานนี้ ฉันเพิ่มบูลีนเพื่ออนุญาตให้โค้ดรันเพียงครั้งเดียว แต่ฉันชอบคำอธิบายว่าทำไมมันเริ่มทำสิ่งนี้ในทันที อัพเดทใด ๆ
กาวินไรท์

คำตอบ:


2

ฉันพบปัญหาที่เปิดอยู่นี้: https://issuetracker.google.com/issues/152628934

ตามที่ฉันแสดงความคิดเห็นฉันถือว่าเป็นปัญหากับ "บริการรู้จำเสียง" และไม่ใช่กับคลาส Android RecognitionListener


ใช่ฉันยังเชื่อว่านี่เป็นปัญหา ..
เปโดร Henrique Flores

1

สิ่งนี้เพิ่งเริ่มเกิดขึ้นในหนึ่งในแอพของฉันเมื่อวานนี้ ฉันเพิ่มบูลีนเพื่ออนุญาตให้โค้ดรันเพียงครั้งเดียว แต่ฉันชอบคำอธิบายว่าทำไมมันเริ่มทำสิ่งนี้ในทันที อัพเดทใด ๆ


0

ฉันมีปัญหาเดียวกันและฉันเพิ่งเพิ่มการตั้งค่าสถานะบูลีนในรหัสของฉัน แต่แน่นอนว่ามันเป็นวิธีการแก้ปัญหาชั่วคราวและฉันไม่ทราบสาเหตุของปัญหานี้

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

โปรดเพิ่มรหัสตัวอย่างบางส่วน
m02ph3u5
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.