2012-08-02 64 views
18

我的android應用程序具有文本說話功能,而且更多的是一個活動使用此功能。所以創建了一個靜態輔助類來簡化它。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中看到像beloew這樣的錯誤。

"speak:failed not bound to tts engine" 

沒有發生異常,但沒有TTS產生。 我意識到,如果我從BroadcastReceiver觸發活動,我得到了這個錯誤。否則,如果手動打開來自應用程序代碼的活動並沒有問題。

這裏是廣播接收器代碼

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中失敗 - 其他則可能Activity作爲前臺任務具有更高的優先級,並且它在調用sayText之前完成。

您需要等待調用sayText,直到init調用返回時,它必須新建一個新的TTS對象。

+0

那麼我該如何做到這一點? Thread.sleep代碼?我不怎麼能說,等到說完了。 – 2012-08-03 09:53:24

+0

嗨。我們可以同時啓動這個TTS線程嗎? – 2015-01-15 18:44:32

3

這是我用於文本到語音的代碼。對於我的代碼,只需輸入speakWords(「說點什麼」);在任何活動中。

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 Bundle上方的代碼的onInit部分。它會爲您節省將來的錯誤。\ – 2012-08-02 17:07:46

+1

在Activity上實現時沒有任何問題。我想創建全球TTS系統 – 2012-08-03 09:50:17