I'm trying to get Speech Recognition working for my Android 2.3.3 app but something fundamental is missing.
First off, at the top of my AndroidManifest.xml
file I have:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.myuser.myapp">
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
... remainder omitted for brevity
Which I believe should be prompting Android to ask the end user if they wish to grant my app permission to the microphone when it starts up (if not, please correct me!)...
Next, I have the Activity
which houses the entire need for my app's speech recognition capabilities. Basically, I want the app to detect whenever someone says, out loud, "Go":
public class SpeechActivity extends AppCompatActivity implements RecognitionListener {
private SpeechRecognizer speechRecognizer;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_speech);
int check = ContextCompat.checkSelfPermission(this, android.Manifest.permission.RECORD_AUDIO);
if(check != PackageManager.PERMISSION_GRANTED) {
throw new RuntimeException("Ya can't do that now, ya here.");
}
speechRecognizer = SpeechRecognizer.createSpeechRecognizer(this);
speechRecognizer.setRecognitionListener(this);
Intent speechIntent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
speechIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
speechIntent.putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE, "voice.recognition.test");
speechIntent.putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, 5);
speechRecognizer.startListening(speechIntent);
Log.i("SpeechActivity", "Speech Recognizer is listening");
}
@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) {
Log.i("SpeechActivity", "Speech was detected...");
String spoken = "";
ArrayList<String> data = bundle.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION);
for (int i = 0; i < data.size(); i++) {
spoken += data.get(i);
}
Log.i(this.getClass().getName(), String.format("The word \"%s\" was detected.", spoken));
if(spoken.equalsIgnoreCase("go")) {
doSomething();
}
}
@Override
public void onPartialResults(Bundle bundle) {
}
@Override
public void onEvent(int i, Bundle bundle) {
}
}
I run the app on my Samsung Galaxy S7 Edge by connecting my phone to my laptop (via USB), clicking the Run (app) button in Android Studio, and selecting my phone as the connected device.
When the app starts up on my phone, the first thing I notice is that it does not prompt me to accept/reject the app's permission to use the microphone. This is an early warning sign to me that something is awry.
But then, when I navigate to the SpeechActivity/activity_speech.xml
screen, I get:
When this runs I get:
FATAL EXCEPTION: main
Process: com.example.myuser.myapp, PID: 9585
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.myuser.myapp/com.example.myuser.myapp.SpeechActivity}: java.lang.RuntimeException: Ya can't do that now, ya here.
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2947)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3008)
at android.app.ActivityThread.-wrap14(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1650)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6688)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1468)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1358)
Caused by: java.lang.RuntimeException: Ya can't do that now, ya here.
at com.example.myuser.myapp.SpeechActivity.onCreate(SpeechActivity.java:43)
at android.app.Activity.performCreate(Activity.java:6912)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1126)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2900)
Is it possible I need to download and install a plugin or APK in order for speech recognition to work? Why is my app not asking permission to use my phone's mic? How is the speech recognizer started/listening, but then doesn't seem to pick up on any speech at all?
According to the documentation, it is a dangerous permission. You should request for it from user.
RECORD_AUDIO : Allows an application to record audio.
Protection level: dangerous
Constant Value: "android.permission.RECORD_AUDIO"
Simply, you can check if your app has this permission using
int permissionCheck = ContextCompat.checkSelfPermission(thisActivity,
Manifest.permission.RECORD_AUDIO);
if (permissionCheck == PERMISSION_GRANTED) {
// you have the permission, proceed to record audio
speechRecognizer = SpeechRecognizer.createSpeechRecognizer(this);
speechRecognizer.setRecognitionListener(this);
Intent speechIntent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
speechIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
speechIntent.putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE, "voice.recognition.test");
speechIntent.putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, 5);
speechRecognizer.startListening(speechIntent);
Log.i("SpeechActivity", "Speech Recognizer is listening");
}
else {
// you don't have permission, try requesting for it
ActivityCompat.requestPermissions(thisActivity,
new String[]{Manifest.permission.RECORD_AUDIO},
MY_PERMISSION_REQUEST_RECORD_AUDIO);
}
Take your time, read Requesting Permissions guide at Android Guides.