TextToSpeech构造函数看起来像是由Activity“拥有”。我正在制作一个包含多个不同活动的应用程序,我不想为每个活动初始化一个新的TextToSpeech实例 - 我希望即使活动正在改变,语音也能顺利进行。
我的想法是让所有活动访问一个静态TextToSpeech对象,由第一个对象初始化。
答案 0 :(得分:4)
我从未尝试过,但我认为您可以将Application上下文作为参数传递给构造函数,而不一定是Activity。
但是注意documentation,我发现TTS引擎有自己的排队系统,所以你可以多次打电话讲话而不用担心线程时间。
关于你的问题,我不确定第二个问题,但正如我先写的那样,我会尝试传递一个Application上下文,而不是Activity上下文。
关于第一,嗯,我猜每个引擎一次有一个实例。而且你通常只有一个引擎,但是如果引擎控制查询排队,请不要担心线程。
答案 1 :(得分:3)
感谢那些告诉我传递ApplicationContext的人。原来那是容易的......难以理解的是TextToSpeech对象是否保证线程安全。
感谢您的回答告诉我如何制作线程安全的东西/假设它是,但问题是该对象是否已经存在。我可能应该说,我对实现线程安全很好,但我想知道我是否需要打扰。而且我不想在不确定的情况下假设线程安全。
我跑了以下,似乎工作。所以我假设Android SDK TTS是线程安全的,但是找不到任何文档说在所有设备上假设这是安全的,所以我将暂时包装我的TTS实例!
package com.example.testproject;
import java.util.Random;
import android.os.Bundle;
import android.app.Activity;
import android.speech.tts.TextToSpeech;
import android.speech.tts.TextToSpeech.OnInitListener;
public class TestActivity extends Activity implements OnInitListener {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
tts = new TextToSpeech(getApplicationContext(), this);
}
TextToSpeech tts = null;
@Override
public void onInit(int arg0) {
for (int i = 0; i < 100; ++i) {
class Irritate implements Runnable {
Irritate(int iIn) {
i = iIn;
}
@Override
public void run() {
Random r = new Random();
try {
Thread.sleep(r.nextInt(2000));
} catch (InterruptedException e) {
e.printStackTrace();
}
tts.speak(Integer.toString(i), TextToSpeech.QUEUE_ADD, null);
}
int i;
}
Thread t = new Thread(new Irritate(i));
t.start();
}
}
}
答案 2 :(得分:1)
我一直使用TTS作为我开始练习的活动。 我只是向它发出一个意图,然后等待它回来。 如果我没记错的话,如果返回一系列满意的答案。 所以如果你没有上下文,那么我不相信有另一种方法可以调用它(至少使用这个模型)。不确定是否有可以获得的对象引用。
但是,如果有,请使用您的想法。然后你可以只扩展Application并将静态引用保存到你的TTS中。这样,您的所有活动都可以看到它。我认为这是你正在寻找的答案。
答案 3 :(得分:0)
以上内容有助于我解决此问题。在我的情况下,我也有一个片段,所以,我做了以下:
从片段(来自片段,你想说&#34; getActivity()。getApplicationContext()&#34;而不仅仅是&#34; getApplicationContext()&#34;):
public void onActivityResult(int requestCode, int resultCode, Intent data){
if(requestCode == MY_DATA_CHECK_CODE){
if (resultCode == TextToSpeech.Engine.CHECK_VOICE_DATA_PASS) {
tts = new TextToSpeech(getActivity().getApplicationContext(), new TextToSpeech.OnInitListener() {
@Override
public void onInit(int status) {
if(status == TextToSpeech.SUCCESS){
result = tts.setLanguage(Locale.UK);
}
}
});
} else {
// missing data, install it
Intent installIntent = new Intent();
// The ACTION_INSTALL_TTS_DATA intent will take the user to Android Market, and will let the user initiate the download
installIntent.setAction(TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA);
startActivity(installIntent);
}
}
}
答案 4 :(得分:0)
TextToSpeech在GUI方面不是线程安全的,因为从非GUI线程调用TextToSpeech侦听器方法。
如果您的侦听器方法与GUI交互,则必须包含代码以将GUI更改放入GUI线程的Looper中。
有很多关于如何在Handler中包装GUI命令并将其发布在GUI线程的looper上的示例。这是你要做的草图:
public class SpeechUtteranceListener extends UtteranceProgressListener {
@Override
public void onDone(String utteranceId) {
Runnable guiCommand = new Runnable() {
@Override
public void run() {
someButton.setEnabled(true);
}
}
};
runOnUiThread(asrStartCommand);
}
private void runOnUiThread(Runnable command){
Looper.getMainLooper().post(command);
}
}