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_mic.xml
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:
ic_copy.xml
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:
et_bg.xml
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:
activity_main.xml
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:
