I stumbled with this random issue...
Here is my code
mSpeechRecognizer = SpeechRecognizer.createSpeechRecognizer(mContext);
initializeRecognitionListener();
mSpeechRecognizer.setRecognitionListener(mRecognitionListener);
Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,
RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
intent.putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE, getClass().getPackage().getName());
intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, "en-US");
intent.putExtra(RecognizerIntent.EXTRA_SPEECH_INPUT_COMPLETE_SILENCE_LENGTH_MILLIS, Long.valueOf(3000L));
intent.putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, 5);
mSpeechRecognizer.startListening(intent);
Method initializeRecognitionListener():
private void initializeRecognitionListener() {
mRecognitionListener = new RecognitionListener() {
#Override
public void onReadyForSpeech(Bundle params) {
Log.d("onReadyForSpeech()", "onReadyForSpeech!");
isRecognizing = true;
}
#Override
public void onBeginningOfSpeech() {
Log.d("onBeginningOfSpeech()", "onBeginningOfSpeech!");
}
#Override
public void onEndOfSpeech() {
Log.e("onEndOfSpeech()", "onEndOfSpeech! stop SCO");
}
...
}
Main issue that is "onReadyForSpeech()" and "onBeginningOfSpeech()" methods sometimes doesn't called after mSpeechRecognizer.startListening(intent). Also "onEndOfSpeech()" also can be not called.
I'm using Nexus 4 with Android 4.2.2
I posted a very similar answer on another post:
This is a Google Voice Search/Jelly Bean bug that has been outstanding on the AOSP bug tracker for nearly a year.
I posted on the Google Product Forum about it here too, but no response. If you are reading this and would like these issues to be resolved, please do star the AOSP issue and comment on the Product Forum post to get it noticed!
To work around this issue, you'll need an implementation such as the one demonstrated here.
In my testing today, it does appear that the latest version of Google Search has fixed this problem internally though - So update Google Search on the Play Store and this problem may disappear - If that's not the case for you, please do comment below, as it may be fixed in only certain versions of the Google Search apk, in which case it would be helpful to know where these variations occur to handle them gracefully in our code!
Seems to be I've fixed my problem. Main idea to fix is keep single instance of SpeechRecognizer object instead of recreating it each time. After these changes I didn't get any "Recognizer busy" error. But my HTC One S still freezes when I use my app. I could not understand why...
Related
Ok, I know this has been an issue tracked since the release of Jelly Bean. I would like to extend the time before the speech.recognizer shuts off. I'm aware that the documentation states "Additionally, depending on the recognizer implementation, these values may have no effect."
So, If I want this to work is there a solution to "implementing" the recognizer or is this simply a limit prescribed by Google and we have no way to implement the recognizer so these values do mean something?
Intent i = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
i.putExtra(RecognizerIntent.EXTRA_SPEECH_INPUT_MINIMUM_LENGTH_MILLIS, Long.valueOf(10000));
i.putExtra(RecognizerIntent.EXTRA_SPEECH_INPUT_COMPLETE_SILENCE_LENGTH_MILLIS, Long.valueOf(10000));
i.putExtra(RecognizerIntent.EXTRA_SPEECH_INPUT_POSSIBLY_COMPLETE_SILENCE_LENGTH_MILLIS, Long.valueOf(10000));
i.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, "en-US");
If Google has set the parameters, does anyone have a workaround?
It looks as though Google has made offline speech recognition available from Google Now for third-party apps. It is being used by the app named Utter.
Has anyone seen any implementations of how to do simple voice commands with this offline speech rec? Do you just use the regular SpeechRecognizer API and it works automatically?
Google did quietly enable offline recognition in that Search update, but there is (as yet) no API or additional parameters available within the SpeechRecognizer class. {See Edit at the bottom of this post} The functionality is available with no additional coding, however the user’s device will need to be configured correctly for it to begin working and this is where the problem lies and I would imagine why a lot of developers assume they are ‘missing something’.
Also, Google have restricted certain Jelly Bean devices from using the offline recognition due to hardware constraints. Which devices this applies to is not documented, in fact, nothing is documented, so configuring the capabilities for the user has proved to be a matter of trial and error (for them). It works for some straight away – For those that it doesn't, this is the ‘guide’ I supply them with.
Make sure the default Android Voice Recogniser is set to Google not
Samsung/Vlingo
Uninstall any offline recognition files you already have installed
from the Google Voice Search Settings
Go to your Android Application Settings and see if you can uninstall
the updates for the Google Search and Google Voice Search
applications.
If you can't do the above, go to the Play Store see if you have the
option there.
Reboot (if you achieved 2, 3 or 4)
Update Google Search and Google Voice Search from the Play Store (if
you achieved 3 or 4 or if an update is available anyway).
Reboot (if you achieved 6)
Install English UK offline language files
Reboot
Use utter! with a connection
Switch to aeroplane mode and give it a try
Once it is working, the offline recognition of other languages,
such as English US should start working too.
EDIT: Temporarily changing the device locale to English UK also seems to kickstart this to work for some.
Some users reported they still had to reboot a number of times before it would begin working, but they all get there eventually, often inexplicably to what was the trigger, the key to which are inside the Google Search APK, so not in the public domain or part of AOSP.
From what I can establish, Google tests the availability of a connection prior to deciding whether to use offline or online recognition. If a connection is available initially but is lost prior to the response, Google will supply a connection error, it won’t fall-back to offline. As a side note, if a request for the network synthesised voice has been made, there is no error supplied it if fails – You get silence.
The Google Search update enabled no additional features in Google Now and in fact if you try to use it with no internet connection, it will error. I mention this as I wondered if the ability would be withdrawn as quietly as it appeared and therefore shouldn't be relied upon in production.
If you intend to start using the SpeechRecognizer class, be warned, there is a pretty major bug associated with it, which require your own implementation to handle.
Not being able to specifically request offline = true, makes controlling this feature impossible without manipulating the data connection. Rubbish. You’ll get hundreds of user emails asking you why you haven’t enabled something so simple!
EDIT: Since API level 23 a new parameter has been added EXTRA_PREFER_OFFLINE which the Google recognition service does appear to adhere to.
Hope the above helps.
I would like to improve the guide that the answer https://stackoverflow.com/a/17674655/2987828 sends to its users, with images. It is the sentence "For those that it doesn't, this is the ‘guide’ I supply them with." that I want to improve.
The user should click on the four buttons highlighted in blue in these images:
Then the user can select any desired languages. When the download is done, he should disconnect from network, and then click on the "microphone" button of the keyboard.
It worked for me (android 4.1.2), then language recognition worked out of the box, without rebooting. I can now dictates instructions to the shell of Terminal Emulator ! And it is twice faster offline than online, on a padfone 2 from ASUS.
These images are licensed under cc by-sa 3.0 with attribution required to stackoverflow.com/a/21329845/2987828 ; you may hence add these images anywhere along with this attribution.
(This the standard policy of all images and texts at stackoverflow.com)
A simple and flexible offline recognition on Android is implemented by CMUSphinx, an open source speech recognition toolkit. It works purely offline, fast and configurable It can listen continuously for keyword, for example.
You can find latest code and tutorial here.
Update in 2019: Time goes fast, CMUSphinx is not that accurate anymore. I recommend to try Kaldi toolkit instead. The demo is here.
In short, I don't have the implementation, but the explanation.
Google did not make offline speech recognition available to third party apps. Offline recognition is only accessable via the keyboard. Ben Randall (the developer of utter!) explains his workaround in an article at Android Police:
I had implemented my own keyboard and was switching between Google
Voice Typing and the users default keyboard with an invisible edit
text field and transparent Activity to get the input. Dirty hack!
This was the only way to do it, as offline Voice Typing could only be
triggered by an IME or a system application (that was my root hack) .
The other type of recognition API … didn't trigger it and just failed
with a server error. … A lot of work wasted for me on the workaround!
But at least I was ready for the implementation...
From Utter! Claims To Be The First Non-IME App To Utilize Offline Voice Recognition In Jelly Bean
I successfully implemented my Speech-Service with offline capabilities by using onPartialResults when offline and onResults when online.
I was dealing with this and I noticed that you need to install the offline package for your Language. My language setting was "Español (Estados Unidos)" but there is not offline package for that language, so when I turned off all network connectivity I was getting an alert from RecognizerIntent saying that can't reach Google, then I change the language to "English (US)" (because I already have the offline package) and launched the RecognizerIntent it just worked out.
Keys: Language setting == Offline Voice Recognizer Package
It is apparently possible to manually install offline voice recognition by downloading the files directly and installing them in the right locations manually. I guess this is just a way to bypass Google hardware requirements.
However, personally I didn't have to reboot or anything, simply changing to UK and back again did it.
Working example is given below,
MyService.class
public class MyService extends Service implements SpeechDelegate, Speech.stopDueToDelay {
public static SpeechDelegate delegate;
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
//TODO do something useful
try {
if (VERSION.SDK_INT >= VERSION_CODES.KITKAT) {
((AudioManager) Objects.requireNonNull(
getSystemService(Context.AUDIO_SERVICE))).setStreamMute(AudioManager.STREAM_SYSTEM, true);
}
} catch (Exception e) {
e.printStackTrace();
}
Speech.init(this);
delegate = this;
Speech.getInstance().setListener(this);
if (Speech.getInstance().isListening()) {
Speech.getInstance().stopListening();
} else {
System.setProperty("rx.unsafe-disable", "True");
RxPermissions.getInstance(this).request(permission.RECORD_AUDIO).subscribe(granted -> {
if (granted) { // Always true pre-M
try {
Speech.getInstance().stopTextToSpeech();
Speech.getInstance().startListening(null, this);
} catch (SpeechRecognitionNotAvailable exc) {
//showSpeechNotSupportedDialog();
} catch (GoogleVoiceTypingDisabledException exc) {
//showEnableGoogleVoiceTyping();
}
} else {
Toast.makeText(this, R.string.permission_required, Toast.LENGTH_LONG).show();
}
});
}
return Service.START_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
//TODO for communication return IBinder implementation
return null;
}
#Override
public void onStartOfSpeech() {
}
#Override
public void onSpeechRmsChanged(float value) {
}
#Override
public void onSpeechPartialResults(List<String> results) {
for (String partial : results) {
Log.d("Result", partial+"");
}
}
#Override
public void onSpeechResult(String result) {
Log.d("Result", result+"");
if (!TextUtils.isEmpty(result)) {
Toast.makeText(this, result, Toast.LENGTH_SHORT).show();
}
}
#Override
public void onSpecifiedCommandPronounced(String event) {
try {
if (VERSION.SDK_INT >= VERSION_CODES.KITKAT) {
((AudioManager) Objects.requireNonNull(
getSystemService(Context.AUDIO_SERVICE))).setStreamMute(AudioManager.STREAM_SYSTEM, true);
}
} catch (Exception e) {
e.printStackTrace();
}
if (Speech.getInstance().isListening()) {
Speech.getInstance().stopListening();
} else {
RxPermissions.getInstance(this).request(permission.RECORD_AUDIO).subscribe(granted -> {
if (granted) { // Always true pre-M
try {
Speech.getInstance().stopTextToSpeech();
Speech.getInstance().startListening(null, this);
} catch (SpeechRecognitionNotAvailable exc) {
//showSpeechNotSupportedDialog();
} catch (GoogleVoiceTypingDisabledException exc) {
//showEnableGoogleVoiceTyping();
}
} else {
Toast.makeText(this, R.string.permission_required, Toast.LENGTH_LONG).show();
}
});
}
}
#Override
public void onTaskRemoved(Intent rootIntent) {
//Restarting the service if it is removed.
PendingIntent service =
PendingIntent.getService(getApplicationContext(), new Random().nextInt(),
new Intent(getApplicationContext(), MyService.class), PendingIntent.FLAG_ONE_SHOT);
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
assert alarmManager != null;
alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, 1000, service);
super.onTaskRemoved(rootIntent);
}
}
For more details,
https://github.com/sachinvarma/Speech-Recognizer
Hope this will help someone in future.
VOICE_CALL, VOICE_DOWNLINK ,VOICE_UPLINK
not working on android 4.0 but working on android 2.3 (Actual Device),I have uploaded a dummy project to record all outgoing call so that you can see it for your self
http://www.mediafire.com/?img6dg5y9ri5c7rrtcajwc5ycgpo2nf
you just have to change audioSource = MediaRecorder.AudioSource.MIC; to audioSource = MediaRecorder.AudioSource.VOICE_CALL; on line 118 in TService.java
If you come across any error, tell me. Any suggestion related to it will be accepted.
After a lot of search I Found that Some Manufactures have closed the access to such function because call recording is not allowed in some countries. If anyone finds such question and get the solution some other way then post it over here it may be helpful to many because many people are have the same issue.
Try to use MediaRecorder.AudioSource.VOICE_RECOGNITION. I had the same problem - ASUS Transformer uses microphone near the back camera by default and audio is very silent in this case. VOICE_CALL doesn't work on this tablet and I have tried VOICE_RECOGNITION - in that case it uses front microphone and audio volume is OK.
OK, in my case this code (thank you eyal!) worked for Samsung Galaxy Note 6:
String manufacturer = Build.MANUFACTURER;
if (manufacturer.toLowerCase().contains("samsung")) {
recorder.setAudioSource(MediaRecorder.AudioSource.VOICE_COMMUNICATION);
} else {
recorder.setAudioSource(MediaRecorder.AudioSource.VOICE_CALL);
}
you try to add this,it may be
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
mMediaRecorder.start();
}
}, 1000);
In my voice recognition based app, I sometimes receive ERROR_RECOGNIZER_BUSY. Intuitively, this calls for... retries, right?
The problem is that this error is very undocumented, so obviously I have questions that perhaps someone more experienced in the field is able to answer:
What triggers such an error? Is it
really only busy server (at Google)?
or this could also hint at a bug in my app?
Do I have to explicitly close/reopen
a session before a retry?
How often to retry? once every
1-second? every 5-seconds? Other?
Your experienced insights are most welcome. Thanks.
I'm not 100% sure of this, however since it's been so long since you posted, I may as well give it a shot.
It seems that you are doing something wrong in the code. As the commenter said, it would be helpful if you actually posted the code that is returning this error.
However, in the source code for the Android speech recognition service found here:
http://source-android.frandroid.com/frameworks/base/core/java/android/speech/RecognitionService.java
we have a function called dispatchStopListening which seems to end the listening process. However, before it actually ends it, there are a few checks for illegal states, including this:
else if (mCurrentCallback.mListener.asBinder() != listener.asBinder()) {
listener.onError(SpeechRecognizer.ERROR_RECOGNIZER_BUSY);
Log.w(TAG, "stopListening called by other caller than startListening - ignoring");
}
This seems to imply that you are trying to end the listening process by some other guy than you started it with, which raises this error.
I hope this helps, but it would be extremely beneficial if you posted the code.
ERROR_RECOGNIZER_BUSY is often thrown when you are already in use of the SpeechRecognizer object. (Or you didn't close one proprely).
Simply add the package to your recognizer intent and it should work. That is what I have done.
Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
...
intent.putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE, "com.package.name");
The most likely cause for ERROR_RECOGNIZER_BUSY is that you have not stopped the recognition service from the main thread and the error thrown was ignored.
This actually is a very simple error. It means the previous listening is not finished. Basically, you need to stop listening. In my App i have 2 button for different languages. calling stopListening() fixed the issue. The error does appear from time to time but the user experience is smooth now. It doesn't cause problems.
speech.stopListening();
USER_ID = 2;
Intent recognizerIntent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
recognizerIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, TARGET_CODE);
recognizerIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_PREFERENCE, TARGET_CODE);
recognizerIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
recognizerIntent.putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, 1);
recognizerIntent.putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE, Conversation.this.getPackageName());
speech.startListening(recognizerIntent);
I wrote a small app to allow the user to choose which language he uses the Voice Search via a button, rather than relying on the user's language preference (sometimes you want to voice search in Japanese without switching your whole UI to Japanese).
I am testing the app on my HTC Desire /Android 2.1 (Softbank-x06ht). However, when I call the voice api, I get a "Connection Failed" dialog box [retry/cancel], and LogCat shows this warning:
09-12 11:26:13.583: INFO/RecognitionService(545): ssfe url=http://www.google.com/m/voice-search
09-12 10:49:45.683: WARN/RecognitionService(545): required parameter 'calling_package' is missing in IntentAPI request
Note that I can use the Google Voice Search app and it works with no problems.
According to the API Docs http://developer.android.com/reference/android/speech/RecognizerIntent.html#EXTRA_CALLING_PACKAGE the calling_package parameter is not to be used by developers. Well, if that is the case, why does the log say it is missing?
I tried to provide the parameter myself but it didnt change the outcome at all.
private static final String TRIVOICE_CALLING_PACKAGE = "calling_package";
private void callSpeechWebSearch (String language) {
Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,
RecognizerIntent.LANGUAGE_MODEL_WEB_SEARCH);
intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE,
language);
intent.putExtra(TRIVOICE_CALLING_PACKAGE,
"org.filsa.trivoice");
//intent.putExtra(RecognizerIntent.EXTRA_PROMPT, "Speech recognition demo");
try {
startActivity(intent);
} catch (ActivityNotFoundException anfe) {
makeToast("ANFE:" +anfe.getMessage());
}
}
Use this code to get your package name
intent.putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE,
context.getPackageName());
I was having the same problem and set the calling package to the actual calling package (not class) and things then worked correctly. Android 2.2 on a Tmobile G2.