在 Android 上等待 TextToSpeech onInit() 初始化



我正在编写一个文本到语音转换的Android应用程序。我正在重构代码并尝试将 TextToSpeech 类从活动分离到服务,以便在音频在后台播放时可以更新 UI 而不会阻塞。但是,我无法等待TTS引擎初始化。

当我使用

while(isInit==false)
     Thread.sleep(1000); 

该服务从不调用 onServiceConnected 方法。

如果有人知道如何等待TTS引擎的初始化完成,并避免长时间阻塞UI(导致应用程序崩溃(,将不胜感激!

这是我的服务

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.media.AudioManager;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
import android.speech.tts.TextToSpeech;
import android.speech.tts.UtteranceProgressListener;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import java.util.HashMap;
import java.util.Locale;
public class MyTTSService extends Service {
    private static final String TAG = "Class-MyTTSService";
    private TextToSpeech tts;
    private boolean isInit = false;
    private final IBinder myBinder = new MyBinder();
    @Override
    public void onCreate() {
        super.onCreate();
        Log.d(TAG, "Creating TTS Service");
        Context context = this.getApplicationContext();
        this.tts = new TextToSpeech(context, onInitListener);
        this.tts.setOnUtteranceProgressListener(utteranceProgressListener);
        Log.d(TAG, "TTS Service Created");
        // why is this blocking everything?
        while(!isInitComplete()){
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                Log.d(TAG, e.toString());
            }
        }
    }
    public boolean isInitComplete(){
        return isInit;
    }
    @Override
    public void onDestroy() {
        // Don't forget to shutdown tts!
        if (tts != null) {
            tts.stop();
            tts.shutdown();
        }
        super.onDestroy();
    }
    public void waitToFinishSpeaking() {
        while (tts.isSpeaking()) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                Log.d(TAG, e.toString());
            }
        }
    }
    public void speak(String text, AppCompatActivity appCompatActivity) {
        Log.d(TAG, "Speak" + text);
        appCompatActivity.setVolumeControlStream(AudioManager.STREAM_MUSIC);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            HashMap<String, String> param = new HashMap<>();
            param.put(TextToSpeech.Engine.KEY_PARAM_STREAM, String.valueOf(AudioManager.STREAM_MUSIC));
            tts.speak(text, TextToSpeech.QUEUE_ADD, null);
        } else {
            String utteranceId=this.hashCode() + "";
            Bundle bundle = new Bundle();
            bundle.putInt(TextToSpeech.Engine.KEY_PARAM_STREAM, AudioManager.STREAM_MUSIC);
            tts.speak(text, TextToSpeech.QUEUE_ADD, null, null);
        }
    }
    private UtteranceProgressListener utteranceProgressListener = new UtteranceProgressListener() {
        @Override
        public void onStart(String utteranceId) {
        }
        @Override
        public void onDone(String utteranceId) {
        }
        @Override
        public void onError(String utteranceId) {
            Log.e(TAG, "Error while trying to synthesize sample text");
        }
    };
    private TextToSpeech.OnInitListener onInitListener =  new TextToSpeech.OnInitListener() {
        @Override
        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("TTS", "This Language is not supported");
                } else {
                    //init success
                    isInit = true;
                    Log.d(TAG, "TTS Initialized.");
                }
            } else {
                Log.e("TTS", "Initilization Failed!");
            }
        }
    };
    @Override
    public IBinder onBind(Intent intent) {
        Log.d(TAG, "Binding TTS Service");
        return myBinder;
    }
    public class MyBinder extends Binder {
        MyTTSService getService() {
            return MyTTSService.this;
        }
    }
    @Override
    public boolean onUnbind(Intent intent) {
        return false;
    }
}

这是我的活动

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.EditText;
import android.widget.TextView;
import java.util.ArrayList;
public class ReaderActivity extends AppCompatActivity {
    private static final String TAG = "Class-ReaderActivity";
    EditText textBox;
    ArrayList<String> sentences = new ArrayList<String>();
    MyTTSService tts;
    boolean isBound = false;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_reader);
        textBox = (EditText) findViewById(R.id.readerTextArea);
        Intent intentExtras = getIntent();
        Bundle extrasBundle = intentExtras.getExtras();
        sentences = extrasBundle.getStringArrayList("sentences");
        textBox.setText(sentences.toString(), TextView.BufferType.NORMAL);
        textBox.setKeyListener(null);
    }
    @Override
    protected void onStart() {
        super.onStart();
        Intent intent = new Intent(this, MyTTSService.class);
        bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
        Log.d(TAG, "Waiting to bind to service");
    }
    public void readSentences(){
        for(String sentence : sentences){
            Log.d(TAG +"Sencence", sentence);
            //updateUI(sentence);
            tts.speak(sentence, this);
            tts.waitToFinishSpeaking();
        }
    }
    private ServiceConnection serviceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            MyTTSService.MyBinder binder = (MyTTSService.MyBinder) service;
            tts = binder.getService();
            isBound = true;
            readSentences();
        }
        @Override
        public void onServiceDisconnected(ComponentName name) {
            isBound = false;
        }
    };
}

我找到了解决方案。从 MyTTSService.onCreate(( 中删除现有的等待循环。

将以下内容放在 onServiceConnected 方法的末尾

new Thread(new Runnable() {
     public void run(){
          readSentences();
     }
}).start();

然后将方法添加到 MyTTSSer

public boolean isInit(){
     return isInit;
}

在某些情况下,可能需要重新初始化 tts 模块。在初始化不成功的情况下,将以下内容添加到 TextToSpeech.OnInitListener.OnInit。

isInit = false;

然后最后将以下内容添加到 readsentences 方法中

while(!tts.isInit()){
     try {
          Thread.sleep(1000);
     } catch (InterruptedException e) {
          Log.d(TAG, e.toString());
     }
}
tts.speak(sentence, this);

通过这些更改,TTS 模块初始化、音频工作、活动加载,并且可以在播放音频时刷新 UI。

这最终应该把这个问题(已经问了好几次但从未解决(永远搁置。

相关内容

  • 没有找到相关文章

最新更新