Search code examples
androidkotlinspeech

Speech to Text using EditText


Ok I am building a small app to learn some Speech Recognition in Kotlin. The issue I am experiencing is that my EditText is not posting what is being said. It returns a null value. So when I access the text.text = result?.get(0).tostring() it says it has to an Editable!.

I then changed it to text.append(Editable.Factory.getInstance().newEditable(result?.get(0).toString())) I have also tried setText, append and text.text

I am not understanding where my code is posting null in the editText field of the app. I have the correct permissions in my manifest, here is my code:

MainActivity

import android.app.Activity
import android.content.Intent
import android.os.Bundle
import android.speech.RecognizerIntent
import android.speech.SpeechRecognizer
import android.widget.Button
import android.widget.EditText
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity 
import java.util.*

   class MainActivity : AppCompatActivity() {

private val RQ_SPEECH_REC = 102
private lateinit var mic : Button
private lateinit var text : EditText

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    mic = findViewById(R.id.btnMic)
    text = findViewById(R.id.etMain)

    mic.setOnClickListener {
        askSpeechInput()

    }


}

@Suppress("DEPRECATION")
@Deprecated("Deprecated in Java")
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)
    if (requestCode == RQ_SPEECH_REC && resultCode == Activity.RESULT_OK){
        val result = data?.getStringArrayExtra(RecognizerIntent.EXTRA_RESULTS)


        if(text.length() >= 0){
            text.append(text.editableText.toString() + result?.get(0).toString())
        }else{
            text.setText(result?.get(0).toString())
        }


            // text.append(Editable.Factory.getInstance().newEditable(result?.get(0).toString()))

    }
}

@Suppress("DEPRECATION")
private fun askSpeechInput() {
    if (!SpeechRecognizer.isRecognitionAvailable(this)){
        Toast.makeText(this, "Speech is Not Available", Toast.LENGTH_SHORT).show()
    }else{
        val i = Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH)
        i.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM)
        i.putExtra(RecognizerIntent.EXTRA_LANGUAGE, Locale.getDefault())
        i.putExtra(RecognizerIntent.EXTRA_PROMPT, "Begin Speaking")
        startActivityForResult(i, RQ_SPEECH_REC)
    }
}
}

I am learning the concepts of speech in kotlin. However this app, will be used as a typing source and also voice recognition source to type in the document. I have built numerous Speech in C#, however I wanting to learn Speech in Kotlin to expand my apps and knowledge.I have looked at this for over 3 hours trying different methods. I even used a TextView and the same results appear. Any help is greatly appreciated.

also here is the result:

mainview

speech

null in edittext


Solution

  • Ok after some testing and conversion I finally got the solution. When you are calling the Google Speech you have to place the speech as an Array. Then pull the Array to the Edit Text. So the code below is the correct way to use the Speech to Text with the sequence of appending new text as well to what is already said. Also I commend @Winston for the pointing in the right direction. I t was not the exact code but it opened my eyes to the right possibility.

    Mainifest

     <uses-permission android:name="android.permission.INTERNET"/>
     <uses-permission android:name="android.permission.RECORD_AUDIO"/>
    

    MainActivity.xml

    <?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.ConstraintLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
    
    
    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/constraintEditText"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:padding="5dp"
        app:layout_constraintBottom_toTopOf="@+id/constraintMic"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">
    
        <EditText
            android:id="@+id/etMain"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="@drawable/text_outline"
            android:text=""
            android:gravity="start"
            android:hint="Text Goes Here"
            android:inputType="textMultiLine"
            android:textSize="15sp"
            android:padding="10dp"
            android:scrollbarAlwaysDrawVerticalTrack="true"
            tools:ignore="Autofill" />
    
    
    </androidx.constraintlayout.widget.ConstraintLayout>
    
    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/constraintMic"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_marginBottom="24dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent">
    
        <Button
            android:id="@+id/btnMic"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@drawable/round_button_mic"
            android:text="Start"
            app:icon="@drawable/ic_baseline_mic_none_24"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
    
       </androidx.constraintlayout.widget.ConstraintLayout>
    
      </androidx.constraintlayout.widget.ConstraintLayout>
    

    MainActivity

    import android.app.Activity
    import android.content.Intent
    import android.os.Bundle
    import android.speech.RecognizerIntent
    import android.speech.SpeechRecognizer
    import android.widget.Button
    import android.widget.EditText
    import android.widget.Toast
    import androidx.appcompat.app.AppCompatActivity
    import java.util.*
    import kotlin.collections.ArrayList
    
    class MainActivity : AppCompatActivity() {
    
    private val RQ_SPEECH_REC = 102
    private lateinit var mic : Button
    lateinit var text : EditText
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    
        mic = findViewById(R.id.btnMic)
        text = findViewById(R.id.etMain)
    
        mic.setOnClickListener {
            askSpeechInput()
    
        }
    
    
    }
    
    @Suppress("DEPRECATION")
    @Deprecated("Deprecated in Java")
    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        if ((requestCode == RQ_SPEECH_REC) && (resultCode == Activity.RESULT_OK && data != null)){
    
    
            val res: ArrayList<String> =
                data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS) as ArrayList<String>
    
    
            if (text.text.length >= 0)
            {
             text.append(" " + res[0])
            }else {
                text.setText(Objects.requireNonNull(res)[0])
            }
    
    
        }
    }
    
    @Suppress("DEPRECATION")
    private fun askSpeechInput() {
        if (!SpeechRecognizer.isRecognitionAvailable(this)){
            Toast.makeText(this, "Speech is Not Available", 
    Toast.LENGTH_SHORT).show()
        }else{
            val i = Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH)
            i.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, 
    RecognizerIntent.LANGUAGE_MODEL_FREE_FORM)
            i.putExtra(RecognizerIntent.EXTRA_LANGUAGE, Locale.getDefault())
            i.putExtra(RecognizerIntent.EXTRA_PROMPT, "Begin Speaking")
            startActivityForResult(i, RQ_SPEECH_REC)
        }
      }
    }
    

    With this you can change the UI some and add more features, you can also edit the text and add text by typing, as well with voice.