You might have already used this feature. We can use voice commands search on google. This feature is inbuilt in Android, and if you want you can use this feature to get voice input in your application as well. And this post will explain to you how to use android speech to text feature in your application.
Now let’s see how we use voice input using Android Speech to Text.
Android Speech to Text Tutorial
Creating a new Project
- We will start by creating a new Android Studio Project. Here I have created a project named SpeechToText.
- Now let’s begin with the UI design.
User Interface Design
- We will try to create a beautiful UI as shown in the below image.
- First, we will define the colors. And to do this go inside, res->values->colors.xml.
1 2 3 4 5 6 7 8 9 10 11 |
<?xml version="1.0" encoding="utf-8"?> <resources> <color name="colorPrimary">#5aa184</color> <color name="colorPrimaryDark">#487b66</color> <color name="colorAccent">#2b644c</color> <color name="colorButton">#3d5f51</color> <color name="colorButtonActive">#1bea95</color> </resources> |
- Change the style to NoActionBar as well (res->values->styles.xml).
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<resources> <!-- Base application theme. --> <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar"> <!-- Customize your theme here. --> <item name="colorPrimary">@color/colorPrimary</item> <item name="colorPrimaryDark">@color/colorPrimaryDark</item> <item name="colorAccent">@color/colorAccent</item> </style> </resources> |
- As you see in the above image, we have a circular button with an audio recorder icon. You can use any image for the icon. But the tricky thing here is we are using both a custom background and a picture. So for this here we will create two more drawable XML files. One is for the default state of the button, and one is for the active state.
- So first create an XML file named round_default.xml inside the drawable folder.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<?xml version="1.0" encoding="utf-8"?> <layer-list xmlns:android="http://schemas.android.com/apk/res/android"> <item> <shape android:shape="oval"> <solid android:color="@color/colorButton" /> </shape> </item> <item android:bottom="20dp" android:drawable="@drawable/icon_record" android:left="20dp" android:right="20dp" android:top="20dp" /> </layer-list> |
- Now, create one more file named round_active.xml inside the drawable folder.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<?xml version="1.0" encoding="utf-8"?> <layer-list xmlns:android="http://schemas.android.com/apk/res/android"> <item> <shape android:shape="oval"> <solid android:color="@color/colorButtonActive" /> </shape> </item> <item android:bottom="20dp" android:drawable="@drawable/icon_record" android:left="20dp" android:right="20dp" android:top="20dp" /> </layer-list> |
- Remember, here we are using icon_record which is already in my project’s drawable folder. In your case, you need to paste an image for this inside your drawable folder.
- Now for the button background, we will create one more drawable resource file inside the same directory. Create a file named button_background.xml and write the following code.
1 2 3 4 5 6 7 8 9 10 11 12 |
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="@drawable/round_default" android:state_pressed="false" /> <item android:drawable="@drawable/round_active" android:state_pressed="true" /> </selector> |
- Now finally we will come inside activity_main.xml to create our User Interface. Open activity_main.xml and write the following code.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/colorPrimary" android:padding="12dp" tools:context="net.simplifiedcoding.speechtotext.MainActivity"> <EditText android:id="@+id/editText" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_centerVertical="true" android:hint="You will see input here" android:textAppearance="@style/Base.TextAppearance.AppCompat.Large" /> <ImageButton android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_centerHorizontal="true" android:layout_marginBottom="20dp" android:background="@drawable/button_background" /> </RelativeLayout> |
- After writing the above-given code in your activity_main.xml you will see the following design.
Adding Permission
- For this application, we need RECORD_AUDIO permission. So, lets first define it in the AndroidManifest.xml.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="net.simplifiedcoding.speechtotext"> <uses-permission android:name="android.permission.RECORD_AUDIO" /> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest> |
Checking Permission on Runtime
- You might already be knowing that after Android Marshmallow we have to ask permission at runtime. So we need to check the permission on runtime if the device running our app is on the android marshmallow or ahead.
- To do this come inside MainActivity.java and write the following method.
1 2 3 4 5 6 7 8 9 10 11 12 |
private void checkPermission() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { if (!(ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) == PackageManager.PERMISSION_GRANTED)) { Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, Uri.parse("package:" + getPackageName())); startActivity(intent); finish(); } } } |
- Here we are checking if the device is running android marshmallow or ahead. If this condition is true again, we are testing the permission granted or not. If the permission is not granted, we are opening the settings from where the user can allow the permission.
- So, if the permission is not granted user will see the settings activity, from where the user can allow the permission needed. If the permission is already granted user will directly see our application screen.
- To achieve our goal that the user should not see the app screen if the permission is not granted, we will first call the above method inside onCreate().
1 2 3 4 5 6 7 8 9 |
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); checkPermission(); } |
- Now when you first run the application, you will see the following screen.
- From this screen, you can allow the RECORD_AUDIO permission. Just click on Permissions and enable the RECORD_AUDIO permission.
The user has to keep the button pressed when he wants to speak to get the text. So when the button is in the pressed state, it will get the speech and start listening, and after removing the finger from the button, it will stop listening.
To achieve this thing we need an OnTouchListener in our Button.
- First we will define the EditText. Inside onCreate() just after the line where we are calling the checkPermission() add the following line.
1 2 3 |
final EditText editText = findViewById(R.id.editText); |
- Come inside onCreate() and write the following code after defining the EditText.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
findViewById(R.id.button).setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View view, MotionEvent motionEvent) { switch (motionEvent.getAction()) { case MotionEvent.ACTION_UP: //when the user removed the finger editText.setHint("You will see input here"); break; case MotionEvent.ACTION_DOWN: //finger is on the button editText.setText(""); editText.setHint("Listening..."); break; } return false; } }); |
- Now if you run the application, you will see listening after tapping the record button.
- Now our task is to listen to the speech after this.
Creating a SpeechRecognizer
- Just after the line where you defined the EditText write the following line.
1 2 3 |
final SpeechRecognizer mSpeechRecognizer = SpeechRecognizer.createSpeechRecognizer(this); |
- We also need an Intent to listen to the speech. So After the above line write the following code.
1 2 3 4 5 6 7 |
final Intent mSpeechRecognizerIntent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH); mSpeechRecognizerIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM); mSpeechRecognizerIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, Locale.getDefault()); |
Using the RecognitionListener to Listen
- After defining the Intent. Write the following code.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
mSpeechRecognizer.setRecognitionListener(new RecognitionListener() { @Override public void onReadyForSpeech(Bundle bundle) { } @Override public void onBeginningOfSpeech() { } @Override public void onRmsChanged(float v) { } @Override public void onBufferReceived(byte[] bytes) { } @Override public void onEndOfSpeech() { } @Override public void onError(int i) { } @Override public void onResults(Bundle bundle) { //getting all the matches ArrayList<String> matches = bundle .getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION); //displaying the first match if (matches != null) editText.setText(matches.get(0)); } @Override public void onPartialResults(Bundle bundle) { } @Override public void onEvent(int i, Bundle bundle) { } }); |
- Now you need to modify the OnTouchListener as below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
findViewById(R.id.button).setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View view, MotionEvent motionEvent) { switch (motionEvent.getAction()) { case MotionEvent.ACTION_UP: mSpeechRecognizer.stopListening(); editText.setHint("You will see input here"); break; case MotionEvent.ACTION_DOWN: mSpeechRecognizer.startListening(mSpeechRecognizerIntent); editText.setText(""); editText.setHint("Listening..."); break; } return false; } }); |
The Complete Final Code
- After doing everything as we discussed above, we have our MainActivity.java as shown below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
package net.simplifiedcoding.speechtotext; import android.Manifest; import android.content.Intent; import android.content.pm.PackageManager; import android.net.Uri; import android.os.Build; import android.provider.Settings; import android.speech.RecognitionListener; import android.speech.RecognizerIntent; import android.speech.SpeechRecognizer; import android.support.v4.content.ContextCompat; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.MotionEvent; import android.view.View; import android.widget.EditText; import java.util.ArrayList; import java.util.Locale; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); checkPermission(); final EditText editText = findViewById(R.id.editText); final SpeechRecognizer mSpeechRecognizer = SpeechRecognizer.createSpeechRecognizer(this); final Intent mSpeechRecognizerIntent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH); mSpeechRecognizerIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM); mSpeechRecognizerIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, Locale.getDefault()); mSpeechRecognizer.setRecognitionListener(new RecognitionListener() { @Override public void onReadyForSpeech(Bundle bundle) { } @Override public void onBeginningOfSpeech() { } @Override public void onRmsChanged(float v) { } @Override public void onBufferReceived(byte[] bytes) { } @Override public void onEndOfSpeech() { } @Override public void onError(int i) { } @Override public void onResults(Bundle bundle) { //getting all the matches ArrayList<String> matches = bundle .getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION); //displaying the first match if (matches != null) editText.setText(matches.get(0)); } @Override public void onPartialResults(Bundle bundle) { } @Override public void onEvent(int i, Bundle bundle) { } }); findViewById(R.id.button).setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View view, MotionEvent motionEvent) { switch (motionEvent.getAction()) { case MotionEvent.ACTION_UP: mSpeechRecognizer.stopListening(); editText.setHint("You will see input here"); break; case MotionEvent.ACTION_DOWN: mSpeechRecognizer.startListening(mSpeechRecognizerIntent); editText.setText(""); editText.setHint("Listening..."); break; } return false; } }); } private void checkPermission() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { if (!(ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) == PackageManager.PERMISSION_GRANTED)) { Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, Uri.parse("package:" + getPackageName())); startActivity(intent); finish(); } } } } |
- Now you can try running your application.
But remember we need voice data in the device where we are testing the application. You can check the below image to know how to download voice data.
- Now you can test the application.
Android Speech to Text App Source Code
Still having troubles creating this application? Don’t worry I’ve got the source code for you.
Unlock the link given below to get the source code.
[sociallocker id=1372] Android Speech to Text App Source Code Download [/sociallocker]
So that’s all for this Android Speech to Text Tutorial. If you have any question regarding this Android Speech to Text tutorial, then let’s discuss it in comments.
If you found this post helpful, then please SHARE it with your friends. Thank You 🙂