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);
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?
When I create a new Intent in an Activity:
Intent myIntent = new Intent(this, TargetActivity.class);
// apply hacks explained in above stackoverflow answers
System.out.println(myIntent.getExtras())
(this code lays in a default blank activity)
Intent#getExtras() is always null and thus Intent#putExtras(...) leads to immediate NullPointerException. Starting the Intent, however, works without any problems.
I've read all similar stackoverflow posts about this topic:
https://stackoverflow.com/a/6357330
https://stackoverflow.com/a/14288868
https://stackoverflow.com/a/16458878
https://stackoverflow.com/a/16377139
https://stackoverflow.com/a/13596581
https://stackoverflow.com/a/24047080
https://stackoverflow.com/a/3128271
I've tried them all, but none of them seems to have any effect.
Could anyone please provide a solution to simply start an Intent with non-null extras which always works?
Alternatively, is there any other way to provide extra information to an Intent which is clean and not leaky?
OK, I found the problem. Thank you #DanielNugent for pointing to the canonical answer to Intent handling.
The problem was: when I did
myIntent .putExtra("myVar", myVar);
myVar was null!
Stupid of me I didn't double check that and panic, put somehow stupid of Android that this does indeed lead to immediate NullPointerException! Please try it yourself if you don't believe me.
#njzk2: Thank you, I didn't realize that.
I have being upgrading an application to use the new Mobile Android GNSK but I have noticed that using the new MusicID-Stream is a little bit tricky. If the "identifyAlbumAsync" method get executed before the "audioProcessStart" method(since this need to be executed in a different thread), the application just crashes. In the Gracenote Demo application, the "audioProcessStart" method is continuously running so there is no need to synchronize its execution with the "identifyAlbumAsync" method call. Is it the way it is supposed to be used? It will be convenient if the application didn't crashed at least when the methods are not executed in order. Also in our application, we don't want to have the "audioProcessStart" method continuously like it is done in the demo application. We only want to run the "audioProcessStart" method when the user request identification and when the song playing gets identified , we want to stop the audio processing by calling "audioProcessStop". Is there an easy way to do this? Right now, we are getting the Thread where "identifyAlbumAsync" is running to sleep for 2 seconds in order to make sure that the Thread where the "audioProcessStart" method is supposed to run has time to get executed. Thank you in advance for your prompt response
In the upcoming 1.2 release, IGnMusicIdStreamEvents includes a callback that signals audio-processing has started, and an ID can be synced with this, e.g.:
#Override
public void musicIdStreamProcessingStatusEvent( GnMusicIdStreamProcessingStatus status, IGnCancellable canceller ) {
if (GnMusicIdStreamProcessingStatus.kStatusProcessingAudioStarted.compareTo(status) == 0) {
try {
gnMusicIdStream.identifyAlbumAsync();
} catch (GnException e) { }
}
}
Thanks for the feedback, you're right about this issue. Unfortunately right now sleeping is the best solution. But we are adding support for an explicit sync event in an upcoming release, please stay tuned.
I am using Android's MediaRouter / Presentation API (the support.v7 version).
Everything works fine so far. The only thing that doesn't is:
When I quit my activity (e.g.teardown & remove the callbacks), everything still works fine.
However, when starting this activity (the previous mediarouter-activity was forcefully finished, thus onPause/onDestroy was called FOR SURE => so those callbacks in there are gone too, as also shown in my debug messages) again at some later point in time, the callbacks get created and added and everything. Just, that there is no more onRouteAdded called, only onProviderChanged (With the default provider and thus useless).
It does always work like that (with wifi display [miracast], emulated secondary display, chromecast secondary display..). Are there any resolutions which are not in the examples?
Would you like to look at some code? Which special cases? (Can't post it all..)
I couldn't find anything so far, thanks for your help, in advance.
If you change the Google Cast sample app to support MediaRouter.Callback:
https://github.com/googlecast/CastPresentation-android
Then I'm getting the onRouteAdded called every time.
Using getSelectedRoute()instead of the RouteInfo (which is provided by the callbacks) did the job for me.
MediaRouter.RouteInfo selectedRoute = getHelper().getMediaRouter().getSelectedRoute();
if(provider != null && getCurrentRoute() != null && getCurrentRoute().equals(selectedRoute)){
Log.d(TAG, "only provider changes, dont do anything");
return false;
}
if (selectedRoute != null) {
setCurrentRoute(selectedRoute);
}
return updateContents();
this is definetly weird (as the rest of the code looks exactly as in the provided google android developer samples), but it works.
I know this problem was resolved over 1 year ago, but probably it isn't the perfect solution. Maybe it will be useful for somebody else.
I had similar problem with exactly the same symptoms (no more onRouteAdded called). In my situation it was caused by improperly implemented deactivation of MediaRouter: to deactivate it properly you should not only remove all of callbacks, but select default MediaRoute as well.
if (!mMediaRouter.getDefaultRoute().isSelected()) {
mMediaRouter.getDefaultRoute().select();
}
I'm having problems using the RecognizerIntent API on Android 2.2. When I call the API using this code:
Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_WEB_SEARCH);
startActivityForResult(intent, REQUEST_CODE_VOICE_SEARCH);
which looks like it should work, the search popup says "Unknown problem" on the device and in the logs it states:
01-17 14:25:30.433: ERROR/RecognitionActivity(9118): ACTION_RECOGNIZE_SPEECH intent called incorrectly. Maybe you called startActivity, but you should have called startActivityForResult (or otherwise included a pending intent).
01-17 14:25:30.433: INFO/RecognitionControllerImpl(9118): startRecognition(#Intent;action=android.speech.action.RECOGNIZE_SPEECH;launchFlags=0x800000;component=com.google.android.voicesearch/.IntentApiActivity;B.fullRecognitionResultsRequest=true;S.android.speech.extra.LANGUAGE_MODEL=free_form;end)
01-17 14:25:30.433: INFO/RecognitionControllerImpl(9118): State change: STARTING -> STARTING
01-17 14:25:30.443: ERROR/RecognitionControllerImpl(9118): required extra 'calling_package' missing in voice search intent
01-17 14:25:30.443: ERROR/RecognitionControllerImpl(9118): ERROR_CLIENT
01-17 14:25:30.443: ERROR/RecognitionControllerImpl(9118): ERROR_CLIENT
It looks like the problem is the missing "calling_package" extra; on the RecognizerIntent page it states that this extra is:
The extra key used in an intent to the speech recognizer for voice
search. Not generally to be used by
developers. The system search dialog
uses this, for example, to set a
calling package for identification by
a voice search API. If this extra is
set by anyone but the system process,
it should be overridden by the voice
search implementation.
As far as I can tell, I don't need to override this extra, so why am I getting this error? How can I fix my code?
I had the exact same problem. I was working on existing code that had android:launchMode="singleInstance" in the activity I was working on. This will not work for speechrecognizer intent. I changed it to android:launchMode="standard". Now let's see how it breaks the rest of my program :)
Your original code:
Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_WEB_SEARCH);
startActivityForResult(intent, REQUEST_CODE_VOICE_SEARCH);
Works correctly. I tested it on my device (HTC Desire), and also compared it to other open-source uses, by executing the following query in Google, and browsing the source code.
RecognizerIntent.ACTION_RECOGNIZE_SPEECH
site:code.google.com
One of the output lines in my logcat looks like this:
01-26 13:28:53.268: INFO/RecognitionController(1459): startRecognition(#Intent;action=android.speech.action.RECOGNIZE_SPEECH;component=com.google.android.voicesearch/.IntentApiActivity;B.fullRecognitionResultsRequest=true;S.android.speech.extra.LANGUAGE_MODEL=web_search;S.calling_package=com.test;end)
Run a similar search with one of the built in apps (or downloaded ones), see that it works (and is not a device issue, etc.).
If that works correctly, take the code to a new test project, simply put those lines in the onCreate (Change the result constant to 0), and see if it works.
Have you tried setting the extra yourself?
Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_WEB_SEARCH);
intent.putExtra("calling_package","com.yourpackagename.YourActivityClassName");
startActivityForResult(intent, REQUEST_CODE_VOICE_SEARCH);
This is the approach used by this code and is the suggested solution to a similar issue.