Android TextToSpeech初始化阻止/冻结UI线程

ViH*_*ViH 3 user-interface multithreading android blocking

我写了以下代码:

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);
   }
}
Run Code Online (Sandbox Code Playgroud)

但是这段代码: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.
Run Code Online (Sandbox Code Playgroud)

我试着将它放在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;
    }
}
Run Code Online (Sandbox Code Playgroud)

但没有改变.你能告诉一个正确的解决方案/想法吗?

此延迟显示在我的手机LG L4 II(E440)上.在Nexus 10上 - 没有延迟.我在LG L4上尝试了Play商店的不同说话应用程序.在一些应用程序上还有UI阻止,但有些工作没有阻止.这意味着 - 可以实施.但是怎么样?

Dav*_*ado 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>
Run Code Online (Sandbox Code Playgroud)

这引入了复杂性,因为现在Activity必须使用Messenger或AIDL(http://developer.android.com/guide/components/bound-services.html)绑定服务来管理TextToSpeech功能.