绕过Android中的Google TTS引擎初始化延迟

绕过Android中的Google TTS引擎初始化延迟,android,android-service,google-text-to-speech,Android,Android Service,Google Text To Speech,我曾尝试在手机中触发特定事件时播放TextToSpeech对象 然而,我面临着安装在大多数手机上的默认谷歌TTS引擎的问题。现在,我正在初始化TextToSpeech对象后立即播放一些文本,并在语音完成后立即关闭资源,如下代码所示: public class VoiceGenerator { private Context context = null; private static TextToSpeech voice = null; public VoiceGenerator(Conte

我曾尝试在手机中触发特定事件时播放TextToSpeech对象

然而,我面临着安装在大多数手机上的默认谷歌TTS引擎的问题。现在,我正在初始化TextToSpeech对象后立即播放一些文本,并在语音完成后立即关闭资源,如下代码所示:

public class VoiceGenerator {
private Context context = null;

private static TextToSpeech voice = null;

public VoiceGenerator(Context context)
{
    this.context = context;
}


public void voiceInit(String text)
{
    try {
        if (voice == null) {

            new Thread(new Runnable() {
                @Override
                public void run() {
                    voice = new TextToSpeech(context, new TextToSpeech.OnInitListener() {
                        @Override
                        public void onInit(final int status) {
                            try {
                                if (status != TextToSpeech.ERROR) {
                                    voice.setLanguage(Locale.US);
                                    Log.d("VoiceTTS", "TTS being initialized");
                                    HashMap p = new HashMap<String, String>();
                                    p.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, "ThisUtterance");

 //Speaking here
                           voice.speak(text, TextToSpeech.QUEUE_ADD, p);

                                    voice.setOnUtteranceProgressListener(new UtteranceProgressListener() {
                                        @Override
                                        public void onStart(String utteranceId) {

                                        }

                                        @Override
                                        public void onDone(String utteranceId) {
                                            Log.d("VoiceTTS", "TTS being released");
                                            clearTtsEngine();
                                        }

                                        @Override
                                        public void onError(String utteranceId) {

                                        }
                                    });
                                }

                            } catch (Exception e) {
                                clearTtsEngine();
                                Log.d("ErrorLog", "Error occurred while voice play");
                                e.printStackTrace();
                            }


                        }
                    });
                }
            }).start();

        }
    }
    catch(Exception e)
    {
        clearTtsEngine();
        Log.d("ErrorLog","Error occurred while voice play");
        e.printStackTrace();
    }
}

public static void clearTtsEngine()
{
    if(voice!=null)
    {
        voice.stop();
        voice.shutdown();
        voice = null;
    }



 }
}
}

TTS服务代码:

public class TTSService extends Service {

private static TextToSpeech voice =null;

public static TextToSpeech getVoice() {
    return voice;
}

@Nullable
@Override

public IBinder onBind(Intent intent) {
    // not supporting binding
    return null;
}

public TTSService() {
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {

    try{
        Log.d("TTSService","Text-to-speech object initializing");

        voice = new TextToSpeech(TTSService.this,new TextToSpeech.OnInitListener() {
            @Override
            public void onInit(final int status) {
                Log.d("TTSService","Text-to-speech object initialization complete");                   

            }
            });

    }
    catch(Exception e){
        e.printStackTrace();
    }


    return Service.START_STICKY;
}

@Override
public void onDestroy() {
    clearTtsEngine();
    super.onDestroy();

}

public static void clearTtsEngine()
{
    if(voice!=null)
    {
        voice.stop();
        voice.shutdown();
        voice = null;
    }



}
}
修改的语音发生器代码:

public class VoiceGenerator {

private TextToSpeech voice = null;

public VoiceGenerator(Context context)
{
    this.context = context;
}


public void voiceInit(String text)
{
   try {
        if (voice == null) {

            new Thread(new Runnable() {
                @Override
                public void run() {

                    voice = TTSService.getVoice();
                    if(voice==null)
                        return;

                    voice.setLanguage(Locale.US);
                    HashMap p = new HashMap<String, String>();
                    p.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, "ThisUtterance");
                    voice.speak(text, TextToSpeech.QUEUE_ADD, p);

                    voice.setOnUtteranceProgressListener(new UtteranceProgressListener() {
                        @Override
                        public void onStart(String utteranceId) {

                        }

                        @Override
                        public void onDone(String utteranceId) {
                        }

                        @Override
                        public void onError(String utteranceId) {

                        }
                    });
                }
            }).start();

        }
    }
    catch(Exception e)
    {
        Log.d("ErrorLog","Error occurred while voice play");
        e.printStackTrace();
    }
}




}
公共类语音生成器{
私有TextToSpeech voice=null;
公共语音生成器(上下文)
{
this.context=上下文;
}
公共void voiceInit(字符串文本)
{
试一试{
如果(语音==null){
新线程(newrunnable()){
@凌驾
公开募捐{
voice=TTSService.getVoice();
如果(语音==null)
返回;
voice.setLanguage(Locale.US);
HashMap p=新的HashMap();
p、 put(TextToSpeech.Engine.KEY_参数_话语ID,“This话语”);
voice.speak(text,TextToSpeech.QUEUE\u ADD,p);
voice.setOnPatternanceProgressListener(新的话语ProgressListener(){
@凌驾
public void onStart(字符串outtanceid){
}
@凌驾
公共无效onDone(字符串OUTTANCEID){
}
@凌驾
public void onError(字符串outtanceid){
}
});
}
}).start();
}
}
捕获(例外e)
{
Log.d(“ErrorLog”,“语音播放时出错”);
e、 printStackTrace();
}
}
}

我是Android应用程序Saiy的开发者。这不是一个无耻的插件,它是为了证明我使用了您正在考虑的设计模式,并且我已经“经历”了引发您问题的原因

这在我的脑海中是新鲜的,因为我花了去年的时间重写我的代码,并且不得不考虑周围的问题

  • 我们是否可以通过编程或其他方式减少或消除Google TTS引擎的初始化延迟?
我问了一个问题,在不与其他任务竞争的背景线程上初始化Text-to-Speech对象可以稍微减少延迟(正如我看到您已经在发布的代码中所做的那样)

您还可以通过选择嵌入式语音,而不是依赖于网络的语音,确保通话请求不会进一步延迟:

在API 21+中,查看上的选项。特别是当您可以检查网络的延迟和要求时


在API好了,伙计们!我想我找到了正确的代码来毫不拖延地完成这项工作

您可以在onCreate()中初始化TextToSpeach,如下所示:

TextToSpeach textToSpeech = new TextToSpeech(this, this);
private void speakOut(final String detectedText){
        if(textToSpeech !=null){
            textToSpeech.stop(); //stop and say the new word
            textToSpeech.speak(detectedText ,TextToSpeech.QUEUE_FLUSH, null, null);
        }
    }
但首先需要
实现TextToSpeech.OnInitListener
,然后需要重写
onInit()方法:

@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) {
            Toast.makeText(getApplicationContext(), "Language not supported", Toast.LENGTH_SHORT).show();
        } else {
            button.setEnabled(true);
        }

    } else {
        Toast.makeText(getApplicationContext(), "Init failed", Toast.LENGTH_SHORT).show();
    }
}
我还注意到,如果不在
onInit()
中设置语言,将会有延迟

现在您可以编写表示文本的方法:

TextToSpeach textToSpeech = new TextToSpeech(this, this);
private void speakOut(final String detectedText){
        if(textToSpeech !=null){
            textToSpeech.stop(); //stop and say the new word
            textToSpeech.speak(detectedText ,TextToSpeech.QUEUE_FLUSH, null, null);
        }
    }

你检查过这个吗?我在
服务中保持
TextToSpeech
实例处于活动状态,不能说我发现了任何问题。当你说完某件事时,没有必要释放资源。然后它会出现“tts实例已泄漏”异常或类似的情况。你可以为此发布代码吗?你可能在
上下文中遇到问题。您应该给
TextToSpeech
一个
Context
,直到您最终在TTS上调用
shutdown()
,该上下文才有效。因此,在
服务中
关键字
将为您提供一个在服务生命周期内有效的上下文,您可以在服务的
onDestroy()
中关闭TTS。非常感谢您仔细的回答。。真是太遗憾了……考虑到我刚刚合并了一个粘性服务和一个引导时重新初始化broadast接收器来解决这个问题……到目前为止,我已经创造了奇迹。。。我最初是按照您的最终解决方案做了一些事情(向用户推荐其他TTS引擎)。。。因此,我还有一些进一步的问题…我让sticky service仅处理tts引擎的初始化部分的方法是否会导致高内存使用率…因为..它仅用于在一天中的某些离散时间点发生事件*服务初始化的tts对象将仅在一天中的某些离散时间点使用上述事件的发生event@SoulRayder只要应用程序的任何部分绑定到另一个进程,它就会在运行Android的应用程序中显示为一个集合。在这些设置中,它显示内存崩溃。您现在应该可以查看此内容了吗?唯一的负面影响是用户的感知——当然,除非用户的设备硬件较差——因此,这种大小的内存分配“比例过高”。根据您的经验,这种“高内存使用率”错误会在多少天内出现?目前,我正在使用基于服务的设计运行我的应用程序超过10小时。。而且该应用程序甚至没有出现在我设备的后台应用程序中消耗高内存(RAM)的应用程序中list@SoulRayder它是恒定的。如果您的应用程序确实绑定到该应用程序,它应该显示吗?您确定它当前已绑定且未被终止,并且该服务仍在运行吗?