2012-08-02 3 views
18

Ứng dụng Android của tôi có tính năng nói văn bản và hơn thế nữa, một hoạt động sử dụng tính năng này. Vì vậy, tạo ra một lớp trợ giúp tĩnh để thực hiện điều này dễ dàng.Android "nói không thành công: không bị ràng buộc với công cụ 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; 
     } 
    } 

} 

Tôi đang sử dụng lớp trợ giúp này như thế này.

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

Nhưng đôi khi tôi thấy lỗi giống như dòng ở LogCat.

"speak:failed not bound to tts engine" 

Không có ngoại lệ nào được ném nhưng không có gì được đọc bởi TTS. Tôi nhận ra rằng nếu tôi kích hoạt hoạt động từ BroadcastReceiver, tôi nhận được lỗi này. Nếu không, nếu hoạt động mở thủ công từ mã ứng dụng hoạt động không có vấn đề gì.

Đây là mã 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);   
    } 
}; 

Trả lời

6

Mã của bạn là không chờ đợi sự trở lại asynch từ constructor của lớp TextToSpeech. Bạn thậm chí có một bình luận nói rằng nó là asynch. Tại sao nó luôn luôn thất bại trong Receiver nhưng không phải là Activity tôi không chắc chắn - khác thì có lẽ Activity là một nhiệm vụ foreground có ưu tiên cao hơn và nó xảy ra để hoàn thành trước khi bạn gọi sayText.

Bạn cần đợi để gọi sayText cho đến khi cuộc gọi init quay trở lại trong trường hợp cần phải khởi động đối tượng TTS mới.

+0

vậy làm cách nào tôi có thể thực hiện việc này? Thread.Sleep? Tôi không biết nói thế nào, đợi cho đến khi nói xong. –

+0

Xin chào. Chúng ta có thể bắt đầu chuỗi TTS này song song không? –

3

Đây là mã tôi sử dụng cho văn bản thành lời nói. Đối với mã của tôi chỉ cần gõ speakWords ("nói điều gì đó"); trong mọi hoạt động.

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

Tôi biết bạn có thể sẽ sửa mã của bạn nhưng tôi nghĩ rằng điều này có thể đơn giản hơn để sử dụng. Ngoài ra, hãy thử sử dụng phần onInit của mã được đặt phía trên gói onCreate. Nó sẽ giúp bạn tránh khỏi các lỗi trong tương lai. \ –

+1

không có vấn đề gì trong khi triển khai trên Hoạt động. Tôi muốn tạo hệ thống TTS toàn cầu –