我正在努力制作我的第一个Android应用程序,但我无法让文本到语音转换工作。
应用程序的要点:用户选择要设置闹钟的时间(使用TimePicker),然后应用程序计算剩余时间,不断更新剩余时间。
我希望使用文本转语音引擎以 5 分钟的间隔口头更新用户剩余的时间。
一切都可以编译和运行,没有错误,但文本到语音转换没有任何作用。我已经寻找了几天来了解如何在java中正确初始化TextToSpeech类,但是我发现的所有内容似乎都根据具体情况以不同的方式初始化它。
在尝试了多个不同的实现之后,所有实现的结果都相同,我决定只创建一个单独的内部类来简化编辑和尝试新事物,我可以创建一个 Voice 类并在其上调用方法。
我只用Java编码了几个月,这是我的第一个Android应用程序,所以我自己在整理这个问题时遇到了很多麻烦。
下面是我用来初始化 TextToSpeech 类的单独(内部/嵌套)类:
private class Voice implements TextToSpeech.OnInitListener {
Context context = getApplicationContext();
TextToSpeech tts = new TextToSpeech(context, this);
public void onInit(int initStatus) {
if (initStatus == TextToSpeech.SUCCESS) {
tts.setLanguage(Locale.US);
}
}
private void say(String announcement) {
tts.speak(announcement, TextToSpeech.QUEUE_FLUSH, null);
}
}
这是活动中的其余代码(我使用单独的活动来显示倒计时)
import android.content.Context;
import android.speech.tts.TextToSpeech;
import android.support.v7.app.AppCompatActivity;
import android.os.*;
import android.widget.*;
import java.util.*;
import java.lang.*;
public class TimerActivity extends AppCompatActivity{
private int alarmHour = MainActivity.alarmHour;
private int alarmMinute = MainActivity.alarmMinute;
private Calendar alarmTime;
private Calendar currentTime;
private TextView timerText;
private TextView lateText;
private int hoursLeft;
private int minutesLeft;
private long difference;
private long calculatedMinutes;
private boolean late = false;
private String lateMessageString = "LATE!";
private String timeRemainingString = "remaining";
private Handler handler = new Handler();
private TextToSpeech tts;
private double pitch = 1;
private double speed = 1;
private int MY_DATA_CHECK_CODE = 0;
private Voice voice;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_timer);
voice = new Voice();
voice.say("This is some bullshit.");
initializeTimer();
}
private void initializeTimer () {
voice.say("Yes, hello. Is it me you're looking for?");
timerText = (TextView) findViewById(R.id.timerText);
lateText = (TextView) findViewById(R.id.lateText);
setAlarm();
calculateTimeLeft();
String timerString = getTimerString();
timerText.setText(timerString);
if (late) {
lateText.setText(lateMessageString);
}
else {
lateText.setText(timeRemainingString);
}
Timer timer = new Timer();
timer.schedule(new UpdateTimer(),100,60000);
}
private class UpdateTimer extends TimerTask {
public void run() {
handler.post(new Runnable() {
public void run() {
calculateTimeLeft();
String timerString = getTimerString();
timerText.setText(timerString);
if (late) {
lateText.setText(lateMessageString);
}
else {
lateText.setText(timeRemainingString);
}
}
});
}
}
private void setAlarm() {
alarmTime = Calendar.getInstance();
currentTime = Calendar.getInstance();
alarmTime.setTimeInMillis(System.currentTimeMillis());
alarmTime.set(Calendar.HOUR_OF_DAY, alarmHour);
alarmTime.set(Calendar.MINUTE, alarmMinute);
// If alarm is set for the past, then set the alarm for the next day at the specified time
if (alarmTime.getTimeInMillis() - System.currentTimeMillis() < 0) {
alarmTime.set(Calendar.DAY_OF_YEAR, alarmTime.get(Calendar.DAY_OF_YEAR) + 1);
}
}
private void calculateTimeLeft() {
currentTime.setTimeInMillis(System.currentTimeMillis());
difference = alarmTime.getTimeInMillis() - System.currentTimeMillis();
long seconds = difference/1000; // convert to seconds
long calculatedHours = seconds / 3600; // Find the number of hours until alarm
calculatedMinutes = (seconds % 3600) / 60; // Use mod to remove the number of hours, leaving only seconds since the last hour, then divide by 60 to get minutes
hoursLeft = (int)Math.abs(calculatedHours); // Get the absolute value of the time left for the string
minutesLeft = (int)Math.abs(calculatedMinutes); // Absolute value of the minutes for string use
}
private String getTimerString() {
// Format the string showing the time remaining
String timeLeftString;
if (hoursLeft == 0) {
timeLeftString = "";
}
else if (hoursLeft == 1) {
timeLeftString = hoursLeft + "hr ";
}
else {
timeLeftString = hoursLeft +"hrs ";
}
if (hoursLeft == 0) {
timeLeftString += minutesLeft;
}
/*
else if (minutesLeft < 10 && calculatedMinutes > 0) {
timeLeftString += "0" + minutesLeft;
}
*/
else {
timeLeftString += minutesLeft;
}
if (calculatedMinutes >= 0 && hoursLeft > 0) {
timeLeftString += " mins";
}
else if (calculatedMinutes > 0) {
timeLeftString += " mins";
}
else if (difference <= 0) {
late = true;
}
return timeLeftString;
}
private class Voice implements TextToSpeech.OnInitListener {
Context context = getApplicationContext();
TextToSpeech tts = new TextToSpeech(context, this);
public void onInit(int initStatus) {
if (initStatus == TextToSpeech.SUCCESS) {
tts.setLanguage(Locale.US);
}
}
private void say(String announcement) {
tts.speak(announcement, TextToSpeech.QUEUE_FLUSH, null);
}
}
}
我认为你听不到任何你想要的声音。
因为TextToSpeech
类不能在调用构造函数后立即说。
TextToSpeech
类实例在初始化时需要连接到系统 TTS 服务。
如果实例成功连接到服务,则将激活onInit
TextToSpeech.OnInitListener
!
因此,您可以在功能完成后听到onInit
声音。尝试将voice.say
函数移动到onInit
函数。
private class Voice implements TextToSpeech.OnInitListener {
Context context = getApplicationContext();
TextToSpeech tts = new TextToSpeech(context, this);
public void onInit(int initStatus) {
if (initStatus == TextToSpeech.SUCCESS) {
tts.setLanguage(Locale.US);
// try it!
voice.say("Can you hear this sentence?");
// If you want to another "say", check this log.
// Your voice will say after you see this log at logcat.
Log.i("TAG", "TextToSpeech instance initialization is finished.");
}
}
private void say(String announcement) {
tts.speak(announcement, TextToSpeech.QUEUE_FLUSH, null);
}
}