I'm trying to create a continous speech recognition in Android 4.4, simple displaying the spoken words in a TextView, like a dictate. I followed multiple tutorials, like https://github.com/fcrisciani/android-speech-recognition/blob/master/VoiceRecognition/src/com/speech/fcrisciani/voicerecognition/ContinuousDictationFragment.java, or Is there a way to use the SpeechRecognizer API directly for speech input? and implemented the following version:
import java.util.ArrayList;
import android.app.Activity;
import android.content.Intent;
import android.graphics.PorterDuff;
import android.os.Bundle;
import android.speech.RecognitionListener;
import android.speech.RecognizerIntent;
import android.speech.SpeechRecognizer;
import android.view.KeyEvent;
import android.view.View;
import android.widget.ImageButton;
import android.widget.TextView;
public class VoiceReadActivity extends Activity {
private ImageButton mButtonSpeech;
private TextView mTextView;
private SpeechRecognizer mSpeechRecognizer = null;
private SpeechRecognizer getSpeechRecognizer() {
if (mSpeechRecognizer == null) {
mSpeechRecognizer = SpeechRecognizer.createSpeechRecognizer(this);
mSpeechRecognizer.setRecognitionListener(new RecognitionListener() {
@Override
public void onReadyForSpeech(Bundle params) {
mButtonSpeech.getBackground().setColorFilter( 0xFFFF0000, PorterDuff.Mode.MULTIPLY );
}
@Override
public void onBeginningOfSpeech() {
mTextView.append( "BEGINNING TO HEAR..." );
mButtonSpeech.getBackground().setColorFilter( 0xFFFFFFFF, PorterDuff.Mode.MULTIPLY );
}
@Override
public void onBufferReceived(byte[] buffer) {}
@Override
public void onEndOfSpeech() {
mTextView.append( "STOP HEARING..." );
mButtonSpeech.getBackground().setColorFilter( 0xFF00FFFF, PorterDuff.Mode.DST );
}
@Override
public void onError(int error) {
String message;
boolean restart = true;
switch (error)
{
case SpeechRecognizer.ERROR_AUDIO:
message = "Audio recording error";
break;
case SpeechRecognizer.ERROR_CLIENT:
message = "Client side error";
restart = false;
break;
case SpeechRecognizer.ERROR_INSUFFICIENT_PERMISSIONS:
message = "Insufficient permissions";
restart = false;
break;
case SpeechRecognizer.ERROR_NETWORK:
message = "Network error";
break;
case SpeechRecognizer.ERROR_NETWORK_TIMEOUT:
message = "Network timeout";
break;
case SpeechRecognizer.ERROR_NO_MATCH:
message = "No match";
break;
case SpeechRecognizer.ERROR_RECOGNIZER_BUSY:
message = "RecognitionService busy";
break;
case SpeechRecognizer.ERROR_SERVER:
message = "error from server";
break;
case SpeechRecognizer.ERROR_SPEECH_TIMEOUT:
message = "No speech input";
break;
default:
message = "Not recognised";
break;
}
mTextView.append("onError code:" + error + " message: " + mes sage);
if (restart) {
getSpeechRecognizer().cancel();
startVoiceRead();
}
}
@Override
public void onEvent(int eventType, Bundle params) {}
@Override
public void onPartialResults(Bundle partialResults) {}
@Override
public void onResults(Bundle results) {
ArrayList<String> text = results.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION);
mTextView.append(text.get(0));
mTextView.append( ". " );
startVoiceRead();
}
@Override
public void onRmsChanged(float rmsdB) {}
});
}
return mSpeechRecognizer;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mButtonSpeech = (ImageButton)findViewById(R.id.button_speech);
mTextView = (TextView)findViewById(R.id.text_slave);
mButtonSpeech.setOnClickListener( new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mSpeechRecognizer == null) {
startVoiceRead();
} else {
stopVoiceRead();
}
}
});
}
public void startVoiceRead() {
Intent speechIntent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
speechIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
getSpeechRecognizer().startListening(speechIntent);
mButtonSpeech.getBackground().setColorFilter( 0xFFFFFF00, PorterDuff.Mode.MULTIPLY );
}
public void stopVoiceRead() {
if (mSpeechRecognizer != null) {
mSpeechRecognizer.destroy();
mSpeechRecognizer = null;
}
mButtonSpeech.getBackground().setColorFilter( 0xFFFFFFFF, PorterDuff.Mode.DST);
}
}
I already added permissions to my Android Manifest:
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<uses-permission android:name="android.permission.INTERNET"/>
The problem is, that the RecognitionListener functions like onBeginningOfSpeech() is called randomly in average every third time I want to activate it threw button presses. Furthermore I don't receive any results, but ErrorCode 2: Network Error, if the RecognitionListener is activated. Even though I followed the tutorials, I wasn't able to spot the difference, making my code not work until now. My LogCat output throws the following errors when pressing the button:
07-04 10:20:22.714: E/DatabaseUtils(869): Writing exception to parcel
07-04 10:20:22.714: E/DatabaseUtils(869): java.lang.SecurityException: Permission Denial: get/set setting for user asks to run as user -2 but is calling from user 0; this requires android.permission.INTERACT_ACROSS_USERS_FULL
07-04 10:20:22.714: E/DatabaseUtils(869): at com.android.server.am.ActivityManagerService.handleIncomingUser(ActivityManagerService.java:14614)
07-04 10:20:22.714: E/DatabaseUtils(869): at android.app.ActivityManager.handleIncomingUser(ActivityManager.java:2258)
07-04 10:20:22.714: E/DatabaseUtils(869): at com.android.providers.settings.SettingsProvider.call(SettingsProvider.java:663)
07-04 10:20:22.714: E/DatabaseUtils(869): at android.content.ContentProvider$Transport.call(ContentProvider.java:325)
07-04 10:20:22.714: E/DatabaseUtils(869): at android.content.ContentProviderNative.onTransact(ContentProviderNative.java:275)
07-04 10:20:22.714: E/DatabaseUtils(869): at android.os.Binder.execTransact(Binder.java:404)
07-04 10:20:22.714: E/DatabaseUtils(869): at dalvik.system.NativeStart.run(Native Method)
07-04 10:20:22.714: W/ActivityManager(869): Permission Denial: get/set setting for user asks to run as user -2 but is calling from user 0; this requires android.permission.INTERACT_ACROSS_USERS_FULL
07-04 10:20:22.734: E/VoiceEngineWrapper(16366): getInstance() : get existed VoiceEngine
07-04 10:20:22.734: E/VSG(16366): VSG: speechEndpointTimeout = 1500
07-04 10:20:22.734: E/VSG(16366): VSG: DEFAULT_ENDPOINT_MEDIUM is 1750
07-04 10:20:22.734: E/VSG(16366): VSG: Not using dynamic HANGOVER ... speechEndpointTimeout is 1500
07-04 10:20:22.734: E/VSG(16366): VSG: SHORT = 400
07-04 10:20:22.734: E/VSG(16366): VSG: MEDIUM = 750
07-04 10:20:22.734: E/VSG(16366): VSG: MEDIUM_LONG = 1250
07-04 10:20:22.734: E/VSG(16366): VSG: LONG = 1750
07-04 10:20:22.734: E/VSG(16366): VSG: LONG_LONG = 2250
But even if I add
<uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL"/>
the problems, described above, continue.
Thanks for taking the time to help. This has been a hurdle I haven't been able to get over yet.
According to Use of SpeechRecognizer produces ERROR_NETWORK (Value 2), the error was caused by Samsungs speech API (powered by Vlingo). Changing the speech API in the phone settings to standard Google API solved the problems.
For others that may have this issue, I encountered NetworkError with a SpeechRecognizer due to having an overlapping MediaRecorder or AudioRecord instance active at the same time. It seemed to work fine on a Lenovo Tab 2 A10 that I was developing on, but not on any of the mobile devices I tested.
Searching for SpeechRecognizer and NetworkError was not productive.
If you have this issue, you might find this question useful (or start searching for SpeechRecognizer and AudioRecord/MediaRecorder)...
Android speech recognizing and audio recording in the same time
I kept seeing network errors. Disabled Samsung Auto Bixby wake up and booooom! problem solved!
User contributions licensed under CC BY-SA 3.0