2012-08-02 2 views
18

내 안드로이드 응용 프로그램은 기능을 말하기위한 텍스트를 가지고 있으며, 하나의 활동이이 기능을 사용합니다. 이렇게 쉽게 정적 도우미 클래스를 만들었습니다.Android "말하기 실패 : TTS 엔진에 연결되지 않음"

import java.util.Locale; 

import android.content.Context; 
import android.speech.tts.TextToSpeech; 
import android.speech.tts.TextToSpeech.OnInitListener; 
import android.util.Log; 

public class TextToSpeechController implements OnInitListener { 

    private static final String TAG = "TextToSpeechController"; 
    private TextToSpeech myTTS; 
    private String textToSpeak; 
    private Context context; 

    private static TextToSpeechController singleton; 

    public static TextToSpeechController getInstance(Context ctx) { 
     if (singleton == null) 
      singleton = new TextToSpeechController(ctx); 
     return singleton; 
    } 

    private TextToSpeechController(Context ctx) { 
     context = ctx; 
    } 

    public void speak(String text) { 
     textToSpeak = text; 

     if (myTTS == null) { 
      // currently can't change Locale until speech ends 
      try { 
       // Initialize text-to-speech. This is an asynchronous operation. 
       // The OnInitListener (second argument) is called after 
       // initialization completes. 
       myTTS = new TextToSpeech(context, this); 

      } catch (Exception e) {    
       e.printStackTrace(); 
      } 
     } 

     sayText(); 

    } 

    public void onInit(int initStatus) { 
     if (initStatus == TextToSpeech.SUCCESS) { 
      if (myTTS.isLanguageAvailable(Locale.UK) == TextToSpeech.LANG_AVAILABLE) 
       myTTS.setLanguage(Locale.UK); 
     } 

     // status can be either TextToSpeech.SUCCESS or TextToSpeech.ERROR. 
     if (initStatus == TextToSpeech.SUCCESS) { 
      int result = myTTS.setLanguage(Locale.UK); 
      if (result == TextToSpeech.LANG_MISSING_DATA 
        || result == TextToSpeech.LANG_NOT_SUPPORTED) { 
       Log.e(TAG, "TTS missing or not supported (" + result + ")"); 
       // Language data is missing or the language is not supported. 
       // showError(R.string.tts_lang_not_available); 

      } else { 
       // Initialization failed. 
       Log.e(TAG, "Error occured"); 
      } 

     } 
    } 

    private void sayText() { 
     // ask TTs to say the text 
     myTTS.speak(this.textToSpeak, TextToSpeech.QUEUE_FLUSH,  null); 
    } 

    public void stopTTS() { 
     if (myTTS != null) { 
      myTTS.shutdown(); 
      myTTS.stop(); 
      myTTS = null; 
     } 
    } 

} 

저는이 헬퍼 클래스를 이와 같이 사용하고 있습니다.

TextToSpeechController.getInstance(this).speak(readableMessage); 

가끔 LogCat에서 다음과 같은 오류가 표시됩니다.

"speak:failed not bound to tts engine" 

예외는 발생하지 않지만 TTS에서 읽지는 않습니다. BroadcastReceiver에서 활동을 시작하면이 오류가 발생한다는 것을 알았습니다. 그렇지 않으면 응용 프로그램 코드에서 수동으로 열린 활동이 문제없이 작동하는지 여부. 여기

당신의 코드가 TextToSpeech 클래스의 생성자에서 비동기 반환을 기다리고되지 않는 브로드 캐스트 리시버 코드

private final BroadcastReceiver mHandleMessageReceiver = new BroadcastReceiver() { 
    @Override 
    public void onReceive(Context context, Intent intent) { 
     String newMessage = intent.getExtras().getString(EXTRA_MESSAGE);    
     String readableMessage = intent.getExtras().getString(READABLE_MESSAGE);  

     Bundle b = new Bundle(); 
     b.putString(EXTRA_MESSAGE, newMessage); 
     b.putString(READABLE_MESSAGE, readableMessage); 
     Intent newIntent = new Intent("android.intent.action.MAIN"); 
     newIntent.setClass(context, Speak.class); 
     newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 
     newIntent.putExtra("MessageReceived", b); 
     newIntent.putExtra("CallType", CallType.NOTIFICATION); 
     context.startActivity(newIntent);   
    } 
}; 

답변

6

입니다. 심지어 비동기라고하는 주석이 있습니다. Receiver에서 항상 실패하지만 내가 잘 모르는 활동이 아닌 이유 - 포어 그라운드 작업으로서의 Activity가 우선 순위가 높고 sayText를 호출하기 전에 완료하는 경우가 있습니다.

새 TTS 객체를 새로 작성해야하는 경우 init 호출이 반환 될 때까지 sayText를 호출 할 때까지 기다려야합니다.

+0

어떻게하면됩니까? 스레드. 잠깐? 나는 말할 수있는 방법이 없으며 말을 할 때까지 기다린다. –

+0

안녕하세요. 이 TTS 스레드를 병렬로 시작할 수 있습니까? –

3

다음은 텍스트 음성 변환 용 코드입니다. 내 코드는 간단하게 speakWords ("say something")라고 입력하십시오. 모든 활동.

public class VoiceRecognition extends Activity implements OnClickListener, 
     OnInitListener { 

    public static final int VOICE_RECOGNITION_REQUEST_CODE = 1234; 

    public Button speakButton; 
    // TTS object 
    public TextToSpeech myTTS; 
    // status check code 
    public int MY_DATA_CHECK_CODE = 0; 

    // setup TTS 
    public void onInit(int initStatus) { 

     // check for successful instantiation 
     if (initStatus == TextToSpeech.SUCCESS) { 
      if (myTTS.isLanguageAvailable(Locale.US) == TextToSpeech.LANG_AVAILABLE) 
       myTTS.setLanguage(Locale.US); 
     } else if (initStatus == TextToSpeech.ERROR) { 
      Toast.makeText(this, "Sorry! Text To Speech failed...", 
        Toast.LENGTH_LONG).show(); 
     } 
    } 

    /** 
    * Called with the activity is first created. 
    */ 
    @Override 
    public void onCreate(Bundle voiceinput) { 
     super.onCreate(voiceinput); 

     // Inflate our UI from its XML layout description. 
     setContentView(R.layout.voice_recognition); 

     // check for TTS data 
     Intent checkTTSIntent = new Intent(); 
     checkTTSIntent.setAction(TextToSpeech.Engine.ACTION_CHECK_TTS_DATA); 
     startActivityForResult(checkTTSIntent, MY_DATA_CHECK_CODE); 

    } 

    // speak the user text 
    public void speakWords(String speech) { 

     // speak straight away 
     myTTS.speak(speech, TextToSpeech.QUEUE_FLUSH, null); 
    } 


    public void onClick(View v) { 
     speakWords("hello"; 
    } 


    /** 
    * Handle the results from the recognition activity. 
    */ 
    @Override 
    public void onActivityResult(int requestCode, int resultCode, Intent data) { 

     if (requestCode == MY_DATA_CHECK_CODE) { 
      if (resultCode == TextToSpeech.Engine.CHECK_VOICE_DATA_PASS) { 
       // the user has the necessary data - create the TTS 
       myTTS = new TextToSpeech(this, this); 
      } else { 
       // no data - install it now 
       Intent installTTSIntent = new Intent(); 
       installTTSIntent 
         .setAction(TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA); 
       startActivity(installTTSIntent); 
      } 
     } 

     super.onActivityResult(requestCode, resultCode, data); 

    } 

    @Override 
    protected void onDestroy() { 
     super.onDestroy(); 
     myTTS.shutdown(); 
    } 
+0

당신이 아마 당신의 코드를 고치 겠지만 이것이 더 간단 할 것이라고 생각합니다. 또한 onCreate 번들 위에있는 코드의 onInit 섹션을 사용해보십시오. 미래의 오류로부터 당신을 구할 것입니다. \ –

+1

활동에 구현하는 동안 아무런 문제가 없습니다. 글로벌 TTS 시스템을 만들고 싶습니다. –