音声認識リスナーを繰り返しキックオフするサービスがあるので、ユーザーが話すためのオープンエンドのセッションを持つことができます。このクラスは、5秒間音声が聞こえない場合にERROR_SPEECH_TIMEOUTがスローされるJellyBeanの問題も処理します。したがって、基本的にこれは機能します。ただし、recognizer.startListening(recognizerIntent)を繰り返し呼び出すと、この場合はonBeginningOfSpeech()が呼び出されないことからもわかるように、サイレントに失敗します。これで、まったく話さない場合、JellyBeanタイムアウトハンドラーは毎回必ずリスナーを再起動します。音声が聞こえたため、onResults()が呼び出された後にのみ失敗するようです。 onResults()が呼び出された後、recognizer.startListening(recognizerIntent)が確実に呼び出されますが、前述したように、何も起こりません。失敗した場合はランダムであり、Logcatには問題が何であるかを示すものは何もありません。他に何をしようかわからない。うまくいけば、あなたの1人Android音声認識の専門家がこれを以前に見たことがあるでしょう...
最小:2.2ターゲット:JBでのテスト:Android 4.1.2
詳細情報(11-01-13)HTC Oneの4.3アップデートにより、この問題は確実に解決されました。以下の私の音声認識サービスは、信頼性が高く正確になりました。私はエラーなしで少なくとも数分間走りました。 4.1.2に関しては、4.3にアップデートする前は、うまく機能していたようでした(Googleは彼らの側で何かを変更しましたか?)...わかりませんが、それでも話されたいくつかの単語を見逃し、時にはエラーなしで、ただ聞くのをやめてください(この場合、onBeginningOfSpeech()は決して呼び出されません)。私は自分のコードでできる限り進んだので、この問題に関してAndroid 4.1.2についてユーザーに警告する必要があると思います。
詳細情報(09-17-13)おそらく、9月末にAndroidアップデート(4.3)がHTCのものに提供されます( 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 VoiceRecogniterはAndroid 4.xでは起動しません 。著者の状態は、彼が彼のHTCのものでこの問題を見ていると述べています。この問題が発生しているHTC(Android 4.1.2)もあります。これはHTCのものに固有のものかどうか疑問に思いますか? (またはAndroid 4.1.2を実行しているデバイス)-JBを実行している最新のすべてのデバイスでテストするのが難しいことを確認できません。著者はさらに、4.2.2を使用した彼のNexxusは正常に機能すると述べています。この問題が発生したデバイスを教えてもらえますか?
詳細(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;
}
}
私はNexus5でAndroid 4.4 KitKatを使用していますが、これと同じ問題があります。Androidのバグは、クリーンなソリューション。
このソリューションはAndrew_CSソリューションに似ていますが、実際にはより良い認識が可能になると思います。 Andrewsソリューションは常に認識機能を開始および停止しており、音声を処理しているかどうかなどの状態を追跡する必要があります。この新しいソリューション/回避策は基本的にこれを行います:
さらに良い方法を見つけたら教えてくださいが、今のところこれは本当にうまくいくようです。これがAndroidのバグであることを実際に証明できれば、誰かがGoogleに提出してほしいと思います。
@Override
public void onReadyForSpeech(Bundle params) {
Log.d("Speech", "onReadyForSpeech: Cancel Timer");
if(mTimer != null) {
mTimer.cancel();
}
}
@Override
public void onResults(Bundle results) {
//If the timer is available, cancel it so it doesn't interrupt our result processing
if(mTimer != null){
mTimer.cancel();
}
Log.d("Speech", "onResults");
//Start processing data
ArrayList<String> strlist = results.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION);
for (int i = 0; i < strlist.size();i++ ) {
Log.d("Speech", "YOU SAID: " + strlist.get(i));
}
//Start listening again
Log.d("Speech", "onResults: Start Listening");
mSpeechRecognizer.startListening(mRecognizerIntent);
//Start a timer in case OnReadyForSpeech is never called back (Android Bug?)
Log.d("Speech", "onResults: Start a timer");
if(mTimer == null) {
mTimer = new CountDownTimer(2000, 500) {
@Override
public void onTick(long l) {
}
@Override
public void onFinish() {
Log.d("Speech", "Timer.onFinish: Timer Finished, Restart recognizer");
mSpeechRecognizer.cancel();
mSpeechRecognizer.startListening(mRecognizerIntent);
}
};
}
mTimer.start();
}
次を使用できます。
intent.putExtra("Android.speech.extra.DICTATION_MODE", true);
このコードにより、サービスは長時間リッスンします。
SpeechRecognizerのsingle instanceを使用してみてください。stop()メソッドで再作成する必要はありません。 。 onCreate()でgetSpeechRecognizer()を呼び出し、それを忘れてください。ただし、onDestroy()メソッドで破棄することを忘れないでください。
この問題を回避するために、CountDownTimerを使用して、cancelとstartListeningを段階的に呼び出しました。
_timer = new CountDownTimer(300000000, 1000){
@Override
public void onTick(long millisUntilFinished){
if(!_processingSpeech){
_mSpeechRecognizer.cancel();
_mSpeechRecognizer.startListening(_mSpeechRecognizerIntent);
}
}
@Override
public void onFinish(){
setUpTimer();
}
};
_processingSpeech = false;
_timer.start();
私は、RecognitionListenerメソッドでブール処理Speechを使用して、入力の取得/処理中にキャンセルおよび再起動しないことを確認しました。
これがあなたに役立つかどうか、またはあなたがより多くの情報を必要とするかどうか私に知らせてください。幸運を!