0

I have a project that invokes android's default speech recognition system, using RecognizerIntent.ACTION_RECOGNIZE_SPEECH

The UI is 1 textview and 1 command button, to show the result of speech recognition and to start speech recognition, respectively

I also record the input to the speech recogniser in an AMR file using the method shown here:

record/save audio from voice recognition intent

This is possible because the input audio tot he speech recogniser is available as an InputStream in the Intent data returned by the speech recogniser activity

However, I have noticed that when the speech recogniser activity fails to recognise speech (different from incorrect recognition), the onActivityResult(...) function is still called, but it does not return the Intent data, causing NullPointerException when trying to read the AMR file. How do I get the input to the speech recogniser when it fails to recognise speech?

Code:

import android.content.ContentResolver;
import android.content.Intent;
import android.net.Uri;
import android.os.Environment;
import android.speech.RecognizerIntent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Locale;

public class MainActivity extends AppCompatActivity {

    Button btnSpeak;
    TextView txtViewResult;
    private static final int VOICE_RECOGNITION = 1;
    String saveFileLoc = Environment.getExternalStorageDirectory().getPath();
    File fileAmrFile = new File(saveFileLoc+"/recordedSpeech.amr");
    OutputStream outputStream = null;
    InputStream filestream = null;
    Uri audioUri = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        btnSpeak = (Button)findViewById(R.id.button1);
        txtViewResult = (TextView)findViewById(R.id.textView1);

        if(fileAmrFile.exists() ){
            fileAmrFile.delete();
        }

        runprog();



    }   // protected void onCreate(Bundle savedInstanceState) { CLOSED


    private void runprog(){

        btnSpeak.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View view) {
                // Toast.makeText(getApplicationContext(), "Button pressed", Toast.LENGTH_LONG).show();
                // Fire an intent to start the speech recognition activity.
                Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);

                // Specify free form input
                intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
                intent.putExtra(RecognizerIntent.EXTRA_PROMPT,"Please start speaking");
                intent.putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, 1);
                intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, Locale.ENGLISH);

                // secret parameters that when added provide audio url in the result
                intent.putExtra("android.speech.extra.GET_AUDIO_FORMAT", "audio/AMR");
                intent.putExtra("android.speech.extra.GET_AUDIO", true);

                startActivityForResult(intent, VOICE_RECOGNITION);
            }
        });
    }       // private void runprog(){ CLOSED

    // handle result of speech recognition
    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        // if (requestCode == VOICE_RECOGNITION && resultCode == RESULT_OK) {
        if (requestCode == VOICE_RECOGNITION ) {
            ArrayList<String> results;
            results = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
            txtViewResult.setText(results.get(0));
            Log.v("MYLOG", "Speech 2 text");

            // the required audio will be returned by getExtras:
            Bundle bundle = data.getExtras();
            ArrayList<String> matches = bundle.getStringArrayList(RecognizerIntent.EXTRA_RESULTS);

            // Toast.makeText(getApplicationContext(), "HEREHERE", Toast.LENGTH_LONG).show();


            Log.v("MYLOG", "B4 Uri creation");

        // /*
            // the recording url is in getData:
            audioUri = data.getData();
            ContentResolver contentResolver = getContentResolver();
            try {
                filestream = contentResolver.openInputStream(audioUri);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
            // TODO: read audio file from inputstream

            try {
                outputStream = new FileOutputStream(new File(saveFileLoc + "/recordedSpeech.wav"));
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }

            try {

                int read = 0;
                byte[] bytes = new byte[1024];

                while ((read = filestream.read(bytes)) != -1) {
                    outputStream.write(bytes, 0, read);
                }

                // System.out.println("Done!");
                Toast.makeText(getApplicationContext(), "Done", Toast.LENGTH_LONG).show();

            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (filestream != null) {
                    try {
                        filestream.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if (outputStream != null) {
                    try {
                        // outputStream.flush();
                        outputStream.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }

                }
            }
          // */
        }
    }       // public void onActivityResult(int requestCode, int resultCode, Intent data) { CLOSED


}   // protected void onCreate(Bundle savedInstanceState) { CLOSED

layout.xml:

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/spoken" />

    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/textView1"
        android:layout_below="@+id/textView1"
        android:text="@string/button_text"
         />

</LinearLayout>  

For reference, this is what I mean when I said the speech recogniser fails to recognise speech (Note that this is different from when the speech recogniser detects wrongly; in case of a wrong detection, it is still recognising speech)

enter image description here

Phone details:

Model : Samsung Galaxy S4
Model No : SHV-E330L
Android version : 5.01

user13267
  • 6,871
  • 28
  • 80
  • 138
  • Simply check `data.getData() != null` - is that what you mean? – brandall Dec 31 '17 at 16:52
  • @brandall no I want to know how to get the input to the speech recognizer even when speech detection fails as shown in the picture above – user13267 Dec 31 '17 at 20:52
  • If the API fails to detect speech within the audio, I cannot imagine it would then supply this audio along with the failure. I'm making assumptions, but that would seem practical to me. If you always need the audio regardless, you'll need to use a more comprehensive API, such as Google's Cloud Speech – brandall Jan 05 '18 at 15:01

0 Answers0