Pre-requisites:
- Android App Development Fundamentals for Beginners
- Guide to Install and Set up Android Studio
- How to Create/Start a New Project in Android Studio?
- Running your first Android app
- Spinner in Android
- RecognizerIntent in Android
In this article, we are going to build a simple Voice Typer app in Android using Java. This is a glimpse of the application we are going to build. The application contains a single Activity with two TextViews, one Spinner to choose language, an EditText to display the message, and two clickable ImageViews one to give voice input and the other to copy the message to the clipboard. We are going to use RecognizerIntent class to get voice input from users. A sample video is given below to get an idea about what we are going to do in this article.
Preview:
Step by Step Implementation
Step 1: Create a New Project
To create a new project in Android Studio please refer to How to Create/Start a New Project in Android Studio. Note that select Java as the programming language.
Step 2: Adding Vector Assets
Let’s add the necessary vector assets and drawable resource files. Go to app > res > drawable and add the following XML files.
ic_mic.xml (Mic Icon)
XML
android:width = "24dp" android:height = "24dp" android:viewportWidth = "24" android:viewportHeight = "24" android:tint = "?attr/colorControlNormal" > < path android:fillColor = "@android:color/white" android:pathData="M12,14c1.66,0 2.99,-1.34 2.99,-3L15,5c0,-1.66 -1.34,-3 -3, -3S9,3.34 9,5v6c0,1.66 1.34,3 3,3zM17.3,11c0,3 -2.54,5.1 -5.3, 5.1S6.7,14 6.7,11L5,11c0,3.41 2.72,6.23 6,6.72L11,21h2v-3.28c3.28, -0.48 6,-3.3 6,-6.72h-1.7z"/> </ vector > |
Preview:
ic_copy.xml (Clipboard Icon)
XML
android:width = "24dp" android:height = "24dp" android:viewportWidth = "24" android:viewportHeight = "24" android:tint = "?attr/colorControlNormal" > < path android:fillColor = "@android:color/white" android:pathData="M16,1L4,1c-1.1,0 -2,0.9 -2,2v14h2L4,3h12L16,1zM19, 5L8,5c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h11c1.1,0 2, -0.9 2,-2L21,7c0,-1.1 -0.9,-2 -2,-2zM19,21L8,21L8,7h11v14z"/> </ vector > |
Preview:
et_bg.xml (Custom Background for EditText)
XML
<? xml version = "1.0" encoding = "utf-8" ?> < item android:state_focused = "true" > < shape android:shape = "rectangle" > < stroke android:color = "@color/purple_200" android:width = "2dp" /> < corners android:radius = "5dp" /> </ shape > </ item > < item android:state_focused = "false" > < shape android:shape = "rectangle" > < stroke android:color = "#808080" android:width = "2dp" /> < corners android:radius = "5dp" /> </ shape > </ item > </ selector > |
Preview:
Here is a screenshot for reference.
Step 3: Working with the activity_main.xml file
We have added the necessary resource files for the application we are building. Now, Let’s design the UI for our application. Add this layout resource file to app > res > layout. Below is the code for the activity_main.xml file.
XML
<? xml version = "1.0" encoding = "utf-8" ?> < androidx.constraintlayout.widget.ConstraintLayout android:layout_width = "match_parent" android:layout_height = "match_parent" tools:context = ".MainActivity" > < TextView android:id = "@+id/textView" android:layout_width = "wrap_content" android:layout_height = "wrap_content" android:layout_marginTop = "20dp" android:text = "Lazyroar" android:textColor = "@android:color/holo_green_dark" android:textSize = "48sp" android:textStyle = "bold" app:layout_constraintEnd_toEndOf = "parent" app:layout_constraintStart_toStartOf = "parent" app:layout_constraintTop_toTopOf = "parent" /> < TextView android:id = "@+id/textView2" android:layout_width = "wrap_content" android:layout_height = "wrap_content" android:layout_marginStart = "40dp" android:layout_marginTop = "60dp" android:text = "Choose your Language" android:textColor = "@color/black" android:textSize = "20sp" android:textStyle = "normal" app:layout_constraintStart_toStartOf = "parent" app:layout_constraintTop_toBottomOf = "@+id/textView" /> < Spinner android:id = "@+id/spLang" android:layout_width = "300dp" android:layout_height = "wrap_content" android:layout_marginStart = "55dp" android:layout_marginTop = "18dp" android:layout_marginEnd = "56dp" android:minHeight = "48dp" app:layout_constraintEnd_toEndOf = "parent" app:layout_constraintStart_toStartOf = "parent" app:layout_constraintTop_toBottomOf = "@+id/textView2" tools:ignore = "SpeakableTextPresentCheck" /> < EditText android:id = "@+id/etSpeech" android:layout_width = "350dp" android:layout_height = "350dp" android:layout_marginStart = "30dp" android:layout_marginTop = "29dp" android:layout_marginEnd = "31dp" android:background = "@drawable/et_bg" android:ems = "10" android:gravity = "start|top" android:inputType = "textMultiLine" android:maxLines = "20" android:padding = "10dp" app:layout_constraintEnd_toEndOf = "parent" app:layout_constraintStart_toStartOf = "parent" app:layout_constraintTop_toBottomOf = "@+id/spLang" tools:ignore = "SpeakableTextPresentCheck" /> < ImageView android:id = "@+id/ivSpeak" android:layout_width = "50dp" android:layout_height = "50dp" android:layout_marginStart = "96dp" android:layout_marginTop = "25dp" android:clickable = "true" app:layout_constraintStart_toStartOf = "parent" app:layout_constraintTop_toBottomOf = "@+id/etSpeech" app:srcCompat = "@drawable/ic_mic" tools:ignore = "SpeakableTextPresentCheck" /> < ImageView android:id = "@+id/ivCopy" android:layout_width = "50dp" android:layout_height = "50dp" android:layout_marginTop = "25dp" android:layout_marginEnd = "96dp" android:clickable = "true" app:layout_constraintEnd_toEndOf = "parent" app:layout_constraintTop_toBottomOf = "@+id/etSpeech" app:srcCompat = "@drawable/ic_copy" tools:ignore = "SpeakableTextPresentCheck" /> </ androidx.constraintlayout.widget.ConstraintLayout > |
Preview:
Step 4: Working with the MainActivity.java file
Now it’s time to initialize everything in MainActivity and implement Spinner and RecognizerIntent. Here is the complete code for MainActivity. Below is the code for the MainActivity.java file. Comments are added inside the code to understand the code in more detail.
Java
package com.cs.voicetyper; import androidx.activity.result.ActivityResult; import androidx.activity.result.ActivityResultCallback; import androidx.activity.result.ActivityResultLauncher; import androidx.activity.result.contract.ActivityResultContracts; import androidx.appcompat.app.AppCompatActivity; import android.app.Activity; import android.content.ClipData; import android.content.ClipboardManager; import android.content.Intent; import android.os.Bundle; import android.speech.RecognizerIntent; import android.view.View; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.EditText; import android.widget.ImageView; import android.widget.Spinner; import android.widget.Toast; import java.util.ArrayList; public class MainActivity extends AppCompatActivity implements AdapterView.OnItemSelectedListener{ EditText etText; ImageView ivMic,ivCopy; Spinner spLangs; String lcode = "en-US" ; // Languages included String[] languages = { "English" , "Tamil" , "Hindi" , "Spanish" , "French" , "Arabic" , "Chinese" , "Japanese" , "German" }; // Language codes String[] lCodes = { "en-US" , "ta-IN" , "hi-IN" , "es-CL" , "fr-FR" , "ar-SA" , "zh-TW" , "jp-JP" , "de-DE" }; @Override protected void onCreate(Bundle savedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.activity_main); // initialize views etText = findViewById(R.id.etSpeech); ivMic = findViewById(R.id.ivSpeak); ivCopy = findViewById(R.id.ivCopy); spLangs = findViewById(R.id.spLang); // set onSelectedItemListener for the spinner spLangs.setOnItemSelectedListener( this ); // setting array adapter for spinner ArrayAdapter adapter = new ArrayAdapter( this , R.layout.support_simple_spinner_dropdown_item,languages); adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); spLangs.setAdapter(adapter); // on click listener for mic icon ivMic.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View view) { // creating intent using RecognizerIntent to convert speech to text Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH); intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,RecognizerIntent.LANGUAGE_MODEL_FREE_FORM); intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE,lcode); intent.putExtra(RecognizerIntent.EXTRA_PROMPT, "Speak now!" ); // starting intent for result activityResultLauncher.launch(intent); } }); // on click listener to copy the speech ivCopy.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View view) { // code to copy to clipboard ClipboardManager clipboardManager = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE); clipboardManager.setPrimaryClip(ClipData.newPlainText( "label" ,etText.getText().toString().trim())); Toast.makeText(MainActivity. this , "Copied!" , Toast.LENGTH_SHORT).show(); } }); } // activity result launcher to start intent ActivityResultLauncher<Intent> activityResultLauncher = registerForActivityResult( new ActivityResultContracts.StartActivityForResult(), new ActivityResultCallback<ActivityResult>() { @Override public void onActivityResult(ActivityResult result) { // if result is not empty if (result.getResultCode() == Activity.RESULT_OK && result.getData()!= null ) { // get data and append it to editText ArrayList<String> d=result.getData().getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS); etText.setText(etText.getText()+ " " +d.get( 0 )); } } }); @Override public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) { // setting lcode corresponding // to the language selected lcode = lCodes[i]; } @Override public void onNothingSelected(AdapterView<?> adapterView) { // automatically generated method // for implementing onItemSelectedListener } } |
That’s it. Now we can run the application. Make sure that your project contains all the following files.
Here is the preview of the final application.
Output: