У меня есть служба, в которой я начинаю прослушивание речевого оповещения несколько раз, поэтому у меня может быть сеанс открытого сеанса для того, чтобы пользователь мог говорить. Класс также обрабатывает проблему в желе Bean, где вызывается ERROR_SPEECH_TIMEOUT, если за 5 секунд не будет слышна речь. Так что в основном это работает. Однако, если я неоднократно вызываю функцию распознавания .startListening(распознающий элемент), он бесшумно терпит неудачу, о чем свидетельствует тот факт, что onBeginningOfSpeech() никогда не вызывается в этом случае. Теперь, если я просто не говорю вообще, мой обработчик timewelly Bean будет перезапускать слушателя каждый раз в обязательном порядке. Кажется, он только терпит неудачу после того, как onResults() вызвана, потому что речь БЫЛА услышана. После вызова onResults() распознавание распознавания .startListening(identizerIntent) определенно называется, но, как я уже сказал, ничего не происходит. Когда он терпит неудачу, он случайный, и в Logcat нет ничего, чтобы указать, в чем проблема. Я просто не знаю, что еще попробовать. Надеюсь, один из вас, специалисты по распознаванию речи в Android там видели это раньше...
Минимум: 2,2 Цель: Тестирование на JB: Android 4.1.2
ДОПОЛНИТЕЛЬНАЯ ИНФОРМАЦИЯ (11-01-13) Обновление 4.3 для моего HTC One определенно решило эту проблему. Теперь моя служба распознавания речи является надежной и точной. Я пропустил хотя бы несколько минут без ошибок. Что касается 4.1.2, то до моего обновления до 4.3 он, казалось, работал лучше (изменил ли Google что-нибудь на их конце?)... Я не знаю, но он все равно пропустил бы некоторые слова, произнесенные и иногда без ошибок, просто прекратите слушать (onBeginningOfSpeech() в этом случае никогда не вызывается). Полагаю, мне просто нужно будет предупредить моих пользователей об Android 4.1.2 в отношении этой проблемы, потому что я дошел до моего кода.
ДОПОЛНИТЕЛЬНАЯ ИНФОРМАЦИЯ (09-17-13) Предположительно, в конце сентября в HTC появится обновление Android (4.3) (http://www.ubergizmo.com/2013/09/htc-one-to-receive-android-4-3-jelly-bean-update-this-september/). Надеемся, что эта проблема будет устранена на этом устройстве. Проблема остается, хотя для моих пользователей приложений, которые работают под управлением Android 4.1.2, и застрял в этой версии некоторое время. Я до сих пор не знаю, что делать в этих случаях, и, надеюсь, это единственная версия Android с этой проблемой. Есть ли способ узнать, сколько устройств работает 4.1.2?
ДОПОЛНИТЕЛЬНАЯ ИНФОРМАЦИЯ (09-15-13) В этом сообщении здесь: Google voice распознаватель не запускается на Android 4.x. В заявлении автора говорится, что он видит этот вопрос на своем HTC. У меня также есть HTC, который я вижу в этой проблеме (Android 4.1.2). Интересно, уникально ли это для HTC? (или любое устройство под управлением Android 4.1.2). Я не могу подтвердить, так как его трудно проверить на всех последних устройствах под управлением JB. Автор далее утверждает, что его Nexxus с 4.2.2 отлично работает. Может ли кто-нибудь сказать мне, на каком устройстве они видят эту проблему?
ДОПОЛНИТЕЛЬНАЯ ИНФОРМАЦИЯ (9-08-13) Просто чтобы подтвердить, что с моим кодом нет проблем, я также тестировал это на Android 2.3.3, и мне удалось вызвать onResult() > startListening() 25 раз подряд. При таргетинге на Android 4.1.2 я никогда не смогу пройти 3 или 4 вызова. Я не могу поверить, что никто другой не столкнулся с этой проблемой?
public class VoiceRecogService extends Service
{
protected AudioManager mAudioManager;
protected SpeechRecognizer mSpeechRecognizer;
protected Intent mSpeechRecognizerIntent;
protected RecognitionListener mSpeechRecognizerListner;
//protected final Messenger mServerMessenger = new Messenger(new IncomingHandler(this));
protected volatile boolean mIsListening;
protected volatile boolean mIsCountDownOn;
static final int MSG_RECOGNIZER_START_LISTENING = 1;
static final int MSG_RECOGNIZER_CANCEL = 2;
private int mBindFlag;
private Messenger mServiceMessenger;
private Context m_ctx;
private Handler mHandler = new Handler();
//private boolean m_bReadyForSpeechReceived = false;
@Override
public void onCreate()
{
super.onCreate();
m_ctx = this;
mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
//do not mute beep when speech listening first kicks off
Log.d("TESTING: SPEECH SERVICE: CALL START", "onCreate()");
startListening(false);
}
private void startListening(boolean bMuteSound){
Log.d("TESTING: SPEECH SERVICE: startListening()", mIsListening? "true":"false");
if (bMuteSound==true && Build.VERSION.SDK_INT >= 16)//Build.VERSION_CODES.JELLY_BEAN)
{
// turn off beep sound
mAudioManager.setStreamMute(AudioManager.STREAM_SYSTEM, true);
}
if (!mIsListening)
{
//mSpeechRecognizer.startListening(mSpeechRecognizerIntent);
recognizeSpeechDirectly ();
mIsListening = true;
}
}
/////////////////////////////////////////////////////////////////////////
/**
* lazy initialize the speech recognizer
*/
private SpeechRecognizer getSpeechRecognizer()
{
if (mSpeechRecognizer == null)
{
mSpeechRecognizer = SpeechRecognizer.createSpeechRecognizer(m_ctx);
}
return mSpeechRecognizer;
}
private RecognitionListener getSpeechRecognizerListner()
{
if (mSpeechRecognizerListner == null)
{
mSpeechRecognizerListner = new SpeechRecognitionListener();
}
return mSpeechRecognizerListner;
}
private void recognizeSpeechDirectly()
{
Intent recognizerIntent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
recognizerIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
// accept partial results if they come
recognizerIntent.putExtra(RecognizerIntent.EXTRA_PARTIAL_RESULTS, true);
recognizeSpeechDirectly(m_ctx,recognizerIntent, getSpeechRecognizerListner(), getSpeechRecognizer());
}
public static void recognizeSpeechDirectly(Context context,
Intent recognizerIntent,
RecognitionListener listener,
SpeechRecognizer recognizer)
{
//need to have a calling package for it to work
if (!recognizerIntent.hasExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE))
{
recognizerIntent.putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE, "com.dummy");
}
recognizer.setRecognitionListener(listener);
recognizer.startListening(recognizerIntent);
}
////////////////////////////////////////////////////////////////////////////
public void stop()
{
if (getSpeechRecognizer() != null)
{
getSpeechRecognizer().stopListening();
getSpeechRecognizer().cancel();
getSpeechRecognizer().destroy();
mIsListening = false;
if (Build.VERSION.SDK_INT >= 16);//Build.VERSION_CODES.JELLY_BEAN)
mAudioManager.setStreamMute(AudioManager.STREAM_SYSTEM, false);
}
}
// Count down timer for Jelly Bean work around
protected CountDownTimer mNoSpeechCountDown = new CountDownTimer(5000, 5000)
{
@Override
public void onTick(long millisUntilFinished)
{
// TODO Auto-generated method stub
}
@Override
public void onFinish()
{
mIsCountDownOn = false;
Log.d("TESTING: SPEECH SERVICE: CALL START", "onFinish()");
startListening(true);
}
};
@Override
public void onDestroy()
{
super.onDestroy();
if (mIsCountDownOn)
{
mNoSpeechCountDown.cancel();
}
if (mSpeechRecognizer != null)
{
mSpeechRecognizer.destroy();
}
}
protected class SpeechRecognitionListener implements RecognitionListener
{
@Override
public void onReadyForSpeech(Bundle params)
{
if (Build.VERSION.SDK_INT >= 16)//Build.VERSION_CODES.JELLY_BEAN)
{
mIsCountDownOn = true;
mNoSpeechCountDown.start();
}
Log.d("TESTING: SPEECH SERVICE", "onReadyForSpeech");
}
@Override
public void onBeginningOfSpeech()
{
// speech input will be processed, so there is no need for count down anymore
if (mIsCountDownOn)
{
mIsCountDownOn = false;
mNoSpeechCountDown.cancel();
}
}
@Override
public void onEndOfSpeech()
{
Log.d("TESTING: SPEECH SERVICE", "onEndOfSpeech");
}
@Override
public void onBufferReceived(byte[] buffer)
{
//Log.d("TESTING: SPEECH SERVICE", buffer + new String(new byte[] {0x63}));
}
@Override
public void onError(int error)
{
if ((error == SpeechRecognizer.ERROR_NO_MATCH)
|| (error == SpeechRecognizer.ERROR_SPEECH_TIMEOUT)){
if (mIsCountDownOn)
{
mIsCountDownOn = false;
mNoSpeechCountDown.cancel();
}
mIsListening = false;
Log.d("TESTING: SPEECH SERVICE: CALL START", "onError()");
startListening(true);
}
}
@Override
public void onEvent(int eventType, Bundle params)
{
}
@Override
public void onPartialResults(Bundle partialResults)
{
}
@Override
public void onResults(Bundle results)
{
//String str = new String();
//Log.d(TAG, "onResults " + results);
ArrayList data = results.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION);
//if(data.size() >=1){
// //check for save it:
//}
for (int i = 0; i < data.size(); i++)
{
Log.d("TESTING: SPEECH SERVICE", (String)data.get(i));
}
//if no "save it" somewhere in there, then continue:
if (mIsCountDownOn)
{
mIsCountDownOn = false;
}
mIsListening = false;
Log.d("TESTING: SPEECH SERVICE: CALL START", "onResults()");
startListening(true);
}
@Override
public void onRmsChanged(float rmsdB)
{
}
}
@Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
}