我写了以下代码:
public class MainActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
private TextToSpeech mTTS;
@Override
protected void onPause() {
super.onPause();
if (mTTS != null) {
mTTS.stop();
mTTS.shutdown();
}
}
@Override
protected void onResume() {
super.onResume();
mTTS = new TextToSpeech(getApplicationContext(),
new TextToSpeech.OnInitListener() {
@Override
public void onInit(int status) {
if(status != TextToSpeech.ERROR){
mTTS.setLanguage(Locale.ENGLISH);
mTTS.speak("Hello!", TextToSpeech.QUEUE_FLUSH, null);
}
}
});
}
public void onButtonClick(View view) {
mTTS.speak("Hello!", TextToSpeech.QUEUE_FLUSH, null);
}
}
但是这段代码:mTTS = new TextToSpeech(...冻结UI线程5-8秒。
我注意到延迟发生在logcat(第一行)的这一行:
07-13 11:51:11.304 5296-5296/com.example.TextToSpeachTest I/TextToSpeech﹕ Connected to ComponentInfo{com.google.android.tts/com.google.android.tts.service.GoogleTTSService}
07-13 11:51:17.317 5296-5296/com.example.TextToSpeachTest I/Choreographer﹕ Skipped 391 frames! The application may be doing too much work on its main thread.
我试图把它放在AsyncTask中:
@Override
protected void onResume() {
super.onResume();
MyAsyncTask newTask = new MyAsyncTask() {
protected void onPostExecute(Boolean result) {
}
};
newTask.context = getApplicationContext();
newTask.execute();
}
...
class MyAsyncTask extends AsyncTask<Void, Integer, Boolean> {
private TextToSpeech mTTS;
public Context context;
@Override
protected Boolean doInBackground(Void... arg0) {
mTTS = new TextToSpeech(context,
new TextToSpeech.OnInitListener() {
@Override
public void onInit(int status) {
if(status != TextToSpeech.ERROR){
mTTS.setLanguage(Locale.ENGLISH);
mTTS.speak("Hello!", TextToSpeech.QUEUE_FLUSH, null);
}
}
});
return true;
}
}
但没有改变。你能告诉一个正确的解决方案/想法吗?
此延迟显示在我的手机LG L4 II(E440)上。在Nexus 10上 - 没有延迟。 我在LG L4上尝试了Play商店的不同说话应用程序。在一些应用程序上还有UI阻止,但有些工作没有阻止。这意味着 - 可以实施。但是如何?
答案 0 :(得分:6)
您的代码没问题,您不需要从其他线程调用TextToSpeech构造函数。
实际上,问题在于使用主UI线程进行语音处理的一些TextToSpeech库的实现。
解决方案是使TextToSpeech处理在一个独立的进程中运行,与UI线程的进程不同。这样,UI交互和语音处理在两个不同进程的主线程中完成。我发现这样做的唯一方法是使用自己的进程在Android服务中创建TextToSpeech对象和控制代码。
要使用自己的流程创建服务, AndroidManifest.xml 中的配置必须包含以下属性: android:process :
<service
android:name=".TtsService"
android:enabled="true"
android:exported="false"
android:process="com.example.ttsservice">
</service>
这引入了复杂性,因为现在Activity必须使用Messenger或AIDL(http://developer.android.com/guide/components/bound-services.html)绑定服务来管理TextToSpeech功能。
答案 1 :(得分:0)
你不必在后台线程上发言。
IMO - 你需要实现(TextToSpeech.OnInitListener,UtteranceProgressListener)
tts.setOnUtteranceProgressListener(new UtteranceProgressListener()
{
@Override
public void onDone(String utteranceId)
{
onDoneSpeaking(utteranceId);
}
@Override
public void onError(String utteranceId)
{
}
@Override
public void onStart(String utteranceId)
{
}
});
...
public void onInit(int status) {
if ( status == TextToSpeech.SUCCESS ) {
int result = tts.setLanguage( Locale.US );
if ( result == TextToSpeech.LANG_MISSING_DATA ||
result == TextToSpeech.LANG_NOT_SUPPORTED ) {
Log.e("MainActivity#onInit", "set lang error with "+result);
}
else {
tts.speak(mcomment.substring(left, right), TextToSpeech.QUEUE_FLUSH, null);