【问题标题】:How to make sure TextToSpeech is initialized before using speak?如何确保在使用说话之前初始化 TextToSpeech?
【发布时间】:2019-07-22 22:59:41
【问题描述】:

我想向您寻求有关 Android TextToSpeech 功能的帮助。 基本上,我想开发一个简单的人工智能,它会说话,问一个问题然后等待答案,最后,根据答案问另一个问题,依此类推,直到用户说出一个停止一切的关键字。

现在我知道TextToSpeech 必须在使用speak 方法之前进行初始化,我正在尝试通过使用onActivityResult 方法来考虑这一点。

下面是一些代码:

活动类:

public class MainActivity extends AppCompatActivity implements OnInitListener, Button.OnClickListener{
    Button sayHello;
    TextView textView;
    private static final int CHECK_DATA = 0;
    private static final Locale defaultLocale = Locale.UK;   // British English
    private static final String TAG = "TTS";
    private TextToSpeech tts;

    private boolean isInit = false;

sayIt 方法:用来说话:

public void sayIt(String text, boolean flushQ){
        if(isInit){
            if(flushQ){
                tts.speak(text, TextToSpeech.QUEUE_FLUSH, null, null);
            } else {
                tts.speak(text, TextToSpeech.QUEUE_ADD, null, null);
            }
        } else {
            Log.i(TAG, "Failure: TTS instance not properly initialized");
        }
    }

TextToSpeech 监听器:

@Override
    public void onInit(int status){
        if(status == TextToSpeech.SUCCESS){
            isInit = true;

            // Enable input text field and speak button now that we are initialized
            sayHello.setEnabled(true);

            // Set to a language locale after checking availability
            Log.i(TAG, "available="+tts.isLanguageAvailable(Locale.UK));
            tts.setLanguage(defaultLocale);
            // Examples of voice controls.  Set to defaults of 1.0.
            tts.setPitch(1.0F);
            tts.setSpeechRate(1.0F);
            // Issue a greeting and instructions in the default language
            tts.speak("Initialized!", TextToSpeech.QUEUE_FLUSH, null, Integer.toString(12));
        } else {
            isInit = false;
            Log.i(TAG, "Failure: TTS instance not properly initialized");
        }
    }

按钮监听器:

@Override
    public void onClick(View v){
        if(isInit)
            sayIt("You clicked!", true);
    }

onActivityResult 方法:

// Create the TTS instance if TextToSpeech language data are installed on device.  If not
    // installed, attempt to install it on the device.
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == CHECK_DATA) {
            if (resultCode == TextToSpeech.Engine.CHECK_VOICE_DATA_PASS) {

                // Success, so create the TTS instance.  But can't use it to speak until
                // the onInit(status) callback defined below runs, indicating initialization.

                Log.i(TAG, "Success, let's talk");
                tts = new TextToSpeech(this,  this);

                // Use static Locales method to list available locales on device
                Locale[] locales = Locale.getAvailableLocales();
                Log.i(TAG,"Locales Available on Device:");
                for(int i=0; i<locales.length; i++){
                    String temp = "Locale "+i+": "+locales[i]+" Language="
                            +locales[i].getDisplayLanguage();
                    if(locales[i].getDisplayCountry() != "") {
                        temp += " Country="+locales[i].getDisplayCountry();
                    }
                    Log.i(TAG, temp);
                }

            } else {
                // missing data, so install it on the device
                Log.i(TAG, "Missing Data; Install it");
                Intent installIntent = new Intent();
                installIntent.setAction(TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA);
                startActivity(installIntent);
            }
        }
    }

最后,onCreate 方法:

@Override
    public void onCreate(Bundle savedInstance){
        super.onCreate(savedInstance);
        setContentView(R.layout.activity_main);

        sayHello = findViewById(R.id.sayBtn);
        textView = findViewById(R.id.textView);

        sayHello.setEnabled(false);
        sayHello.setOnClickListener(this);
        Intent checkIntent = new Intent();
        checkIntent.setAction(TextToSpeech.Engine.ACTION_CHECK_TTS_DATA);
        startActivityForResult(checkIntent, CHECK_DATA);
        /* THIS SPEAK DOES NOT WORK! */
        sayIt("Speech from method!", true);
    }

问题是:当onInit 方法初始化TextToSpeech 并成功发音文本时,Button 成功启用。 我的目标是从onCreate 方法中创建Activity speak,因为目前它仅适用于onInitonClick 听众,机器人不在onCreate 中,即使我检查tts使用onActivityResult进行初始化。

基本上,我希望TextToSpeech 发言时不涉及Buttons

我知道已经发布了非常相似的问题,但没有一个能解决我的问题。有什么想法吗? 希望我已经清楚了,谢谢!

更新:日志显示在onInit 方法的else 分支中检测到错误,其中Log.i(TAG, "Failure: TTS instance not properly initialized"); 行是。

【问题讨论】:

  • TTS 似乎需要一些时间来初始化。所以如果你直接从onCreate() 调用它,它仍然没有被初始化。您可以尝试使用此处描述的方法stackoverflow.com/questions/3072173/… 延迟调用它
  • 您必须等到onInit()TextToSpeech.SUCCESS 状态运行。你已经有了isInit 变量,所以用它来检查。如果您想尽快发言,请从onInit() 触发。
  • 已经尝试使用布尔值来检查初始化,但没有成功。 @bvk256 建议虽然效果很好。非常感谢!
  • @SabrinaAldrovandi 请注意,每个设备的超时时间可能不同,因此需要进行适当的测试
  • @bvk256 是的,我正在开发这个应用程序,以便在有限数量的设备上使用它,所以我会在每台设备上进行测试,看看如何安排超时时间。

标签: android android-activity text-to-speech


【解决方案1】:

解决方案: 这里唯一要做的就是等待一点时间,以便让TextToSpeech 初始化好。 一个好方法似乎是使用延迟的Handler,如下所示:

final Handler handler = new Handler();
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                //Waiting for RobotTextToSpeech initialization for 1500ms
                rtts.speak("This speak will work!");
                rtts.speak("This other speak will work too!");
            }
        }, 1500);
    }

通过这样做,看起来TextToSpeech 即使在onCreate 方法中也能正常工作,我们只需要等待一点时间。 希望这能有所帮助。

【讨论】:

    猜你喜欢
    • 2021-05-10
    • 2021-10-09
    • 2018-02-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多