【问题标题】:Android TextToSpeech Initialization Blocks/Freezes UI ThreadAndroid TextToSpeech 初始化块/冻结 UI 线程
【发布时间】:2014-09-02 23:01:07
【问题描述】:

我写了以下代码:

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 Store 的不同通话应用程序。在某些应用程序上也存在 UI 阻塞,但有些应用程序没有阻塞。这意味着——可以实施。但是怎么做呢?

【问题讨论】:

  • 这个问题解决了吗?现在已经 4 年了。

标签: android multithreading user-interface blocking


【解决方案1】:

您不必在后台线程上发表演讲。

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);

【讨论】:

  • TextToSpeech.OnInitListener 已经实现(第一个代码)。我刚刚实现了 UtteranceProgressListener——没有任何改变。
  • 返回 android 示例...查看它... ./sdkRoot/samples/legacy/ttsEngine ... 将其引入您现有的应用程序,就像它在示例/片段中显示的那样
  • 我已经查看了这个 Android 示例。您是否建议实施一项服务?
  • 不,我不会在 tts 上的应用中使用它。
【解决方案2】:

你的代码没问题,你不需要从不同的线程调用 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 功能。

【讨论】:

  • 感谢您的回答和重要信息。由于这个延迟,我已经放弃了这个 TTS。稍后我将尝试使用服务解决您的问题(如果 Google 无法修复它)。
猜你喜欢
  • 2016-07-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-22
  • 2021-12-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多