无法直接调用 TextToSpeech 实例的 speak()

Can't call speak() of the TextToSpeech instance directly

我会先添加代码。

public class MainActivity extends Activity {
    TextToSpeech myTTS;
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button btnSpeak = (Button)findViewById(R.id.button1);
        btnSpeak.setOnClickListener(new View.OnClickListener() {
            public void onClick(View arg0) {
                speakOut();
            }
        });
        myTTS = new TextToSpeech(this, new OnInitListener() {
            public void onInit(int arg0) {}
        });


        myTTS.speak("Why doesn't this work?", TextToSpeech.QUEUE_FLUSH, null);
        speakOut();     // why doesn't this work either???
    }
    private void speakOut() {
        myTTS.speak("Why does this work?", TextToSpeech.QUEUE_FLUSH, null);
    }
    protected void onDestroy() {
        super.onDestroy();
        myTTS.shutdown();
    }
}

我正在努力处理 TextToSpeech 实例。

当我点击按钮时,它会说话。

然而,当我直接用 TextToSpeech 实例调用 speak() 方法时,它根本不说话。

调用点击按钮时调用的 speakOut() 方法也不起作用。

我不知道为什么会这样。

点击按钮时方法 起作用的原因是因为 onClickListener()onClick() 方法。

相反,行

myTTS.speak("Why doesn't this work?", TextToSpeech.QUEUE_FLUSH, null);

没有 listener/method-call Android 可以开火的 listener/method-call。所以基本上要解决这个问题,您需要在事件侦听器中调用上述方法,例如 onTouchEvent()onClickListener().

TextToSpeech 构造函数启动与另一个进程中的服务的连接。在建立连接之前,您创建的 TTS 对象不可用。连接状态在侦听器的 onInit() 方法中报告。您需要保留那里报告的状态,以了解服务何时可用。

我稍微修改了您的示例并添加了日志语句来演示该行为。

public class MainActivity extends Activity {
    private static final String TAG = "Demo";

    TextToSpeech myTTS;
    boolean mInitComplete;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.i(TAG, "onCreate()");

        setContentView(R.layout.activity_main);

        Button btnSpeak = (Button)findViewById(R.id.button1);
        btnSpeak.setOnClickListener(new View.OnClickListener() {
            public void onClick(View arg0) {
                speakOut("You pressed the button");
            }
        });
    }

    private void speakOut(String msg) {
        if (mInitComplete) {
            int status = myTTS.speak(msg, TextToSpeech.QUEUE_FLUSH, null);
            if (status == TextToSpeech.SUCCESS) {
                Log.i(TAG, "speakOut(): SUCCESS");
            } else {
                Log.i(TAG, "speakOut(): ERROR");
            }
        } else {
            Log.i(TAG, "speakOut(): TTS Not Initialized");
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        Log.i(TAG, "onResume()");

        myTTS = new TextToSpeech(this, new TextToSpeech.OnInitListener() {
            @Override
            public void onInit(int status) {
                if (status == TextToSpeech.SUCCESS) {
                    mInitComplete = true;
                    Log.i(TAG, "onInit(): TTS Initialized");
                } else {
                    Log.i(TAG, "onInit(): TTS Init Failed");
                }
            }
        });

        speakOut("This will fail because TTS init is not complete");
    }

    @Override
    protected void onPause() {
        super.onPause();
        Log.i(TAG, "onPause()");

        myTTS.shutdown();
        mInitComplete = false;
    }
}

如果在 UI 出现时尽快按 btnSpeakspeakOut 方法也会失败。在调用 onInit 之前,您不能调用 Text To Speech 方法 speak。在 onInit 之前调用 speak 方法不是非法的,但是你可以看到没有任何反应。

呼叫speakOut发言并启用onInit中的btnSpeak。如果在调用 onInit 之前启用 bntSpeak 并按下,则不会听到任何声音。如果网速很慢,这很容易发生。