Android TTS 中没有声音 - 上下文错误?
No sound in Android TTS - wrong context?
我有一个 class DistanceAnnouncer
,它使用 Android 文本转语音引擎来宣布两个位置之间的距离。它的构造是这样的:
public class DistanceAnnouncer {
private TextToSpeech speaker;
public DistanceAnnouncer(Context context) {
speaker = new TextToSpeech(context, new TextToSpeech.OnInitListener() {
...
通过这种方法向用户说出距离:
public void speak(Location targetLocation, Location currentLocation) {
float distanceInMeters = targetLocation.distanceTo(currentLocation);
speaker.speak(String.valueOf(distanceInMeters) + " meters",TextToSpeech.QUEUE_FLUSH,null);
在我的 MainActivity
中,我创建了一个 class 级别的对象...
protected void onCreate(Bundle savedInstanceState) {
distanceAnnouncer = new DistanceAnnouncer(this);
然后在单击对话框按钮时在匿名方法中使用,如下所示。这很好用。但现在我想重构代码以使用更少的内存,并希望摆脱 class 级变量。为了测试它,我创建了一个新的测试对象并将其作为上下文给它 MainActivity.this
(与在构造函数中接收 this
的 class 级对象相反)。旧对象仍然有效,新对象无效。没有抛出异常。代码已执行但没有声音。
代码:
public void NewTargetButtonClicked(View view) {
final EditText entryEditText = new EditText(this);
AlertDialog.Builder alert = new AlertDialog.Builder(this);
alert.setTitle(R.string.enter_coordinates_prompt);
alert.setView(entryEditText);
alert.setCancelable(true);
alert.setPositiveButton(R.string.ok_button_text, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
if (entryEditText.getText() == null) return;
Location newLocation = getLocationFromCoords(entryEditText.getText().toString());
//pagaidām protam apstrādāt tikai decimālgrādus
if (!(newLocation == null)) {
mTargetLocation = newLocation;
refreshDistance();
Button targetButton = (Button) MainActivity.this.findViewById(R.id.newTargetButton);
targetButton.setText(R.string.set_new_target);
DistanceAnnouncer newDistanceAnnouncer = new DistanceAnnouncer(MainActivity.this);
//THIS DOESN'T WORK:
newDistanceAnnouncer.speak(mTargetLocation,mCurrentLocation);
//THIS WORKS:
distanceAnnouncer.speak(mTargetLocation,mCurrentLocation);
CheckBox speakCheckbox = (CheckBox) MainActivity.this.findViewById(R.id.speakDistanceCheckbox);
speakCheckbox.setVisibility(View.VISIBLE);
}
}
});
AlertDialog alertDialog = alert.create();
alertDialog.show();
}
我怀疑这是上下文问题,但在这种情况下,两个上下文之间的区别是什么?他们应该是一样的,不是吗?
编辑:Full DistanceAnnouncer class 代码:
package com.blueit.audioguide;
import android.app.Activity;
import android.content.Context;
import android.location.Location;
import android.speech.tts.TextToSpeech;
import java.util.Locale;
/**
* Created by janeks on 23.04.2016..
*/
public class DistanceAnnouncer {
private TextToSpeech speaker;
public DistanceAnnouncer(Context context) {
speaker = new TextToSpeech(context, new TextToSpeech.OnInitListener() {
@Override
public void onInit(int status) {
if(status != TextToSpeech.ERROR) {
speaker.setLanguage(Locale.ENGLISH);
}
}
});
}
public void speak(Location targetLocation, Location currentLocation) {
if (targetLocation == null) return;
if (currentLocation == null) return;
if ((!(targetLocation == null)) && (!(currentLocation == null))) {
float distanceInMeters = targetLocation.distanceTo(currentLocation);
if (distanceInMeters < 1000) {
distanceInMeters = Math.round(distanceInMeters);
speaker.speak(String.valueOf(distanceInMeters) + " meters",TextToSpeech.QUEUE_FLUSH,null);
} else if ((distanceInMeters >= 1000) && (distanceInMeters <= 100000)) {
float distanceInKilometers = distanceInMeters / 1000;
distanceInKilometers = Math.round(distanceInKilometers * 10) / 10;
speaker.speak(String.valueOf(distanceInKilometers) + " kilometers",TextToSpeech.QUEUE_FLUSH,null);
} else if (distanceInMeters > 100000) {
float distanceInKilometers = distanceInMeters / 1000;
distanceInKilometers = Math.round(distanceInKilometers);
speaker.speak(String.valueOf(distanceInKilometers) + " kilometers",TextToSpeech.QUEUE_FLUSH,null);
}
} else {
}
}
}
编辑 2:应用程序日志,由 TextToSpeech:
过滤
04-23 16:00:03.911 30815-30815/com.blueit.audioguide I/TextToSpeech: Sucessfully bound to com.google.android.tts
04-23 16:00:03.988 30815-30815/com.blueit.audioguide I/TextToSpeech: Connected to ComponentInfo{com.google.android.tts/com.google.android.tts.service.GoogleTTSService}
04-23 16:00:03.995 30815-30932/com.blueit.audioguide I/TextToSpeech: Set up connection to ComponentInfo{com.google.android.tts/com.google.android.tts.service.GoogleTTSService}
04-23 16:01:35.048 30815-30815/com.blueit.audioguide I/TextToSpeech: Sucessfully bound to com.google.android.tts
04-23 16:01:44.346 30815-30815/com.blueit.audioguide W/TextToSpeech: speak failed: not bound to TTS engine
好像系统将第一个连接到系统 TTS 服务,而不是第二个。但是为什么?我也尝试删除第一个,只留下第二个(也许不允许每个 Activity 多个 TTS?),但没有成功。
只保留DistanceAnnouncer
实例作为MainActivity
的成员变量。
总是在 AlertDialog
中创建新实例的问题是 TTS 引擎无法立即使用。现在你叫...
DistanceAnnouncer newDistanceAnnouncer = new DistanceAnnouncer(MainActivity.this);
//THIS DOESN'T WORK:
newDistanceAnnouncer.speak(mTargetLocation,mCurrentLocation);
...然后在正确初始化之前尝试通过 TTS 引擎说话,即在 onInit()
具有 运行.
之前
我有一个 class DistanceAnnouncer
,它使用 Android 文本转语音引擎来宣布两个位置之间的距离。它的构造是这样的:
public class DistanceAnnouncer {
private TextToSpeech speaker;
public DistanceAnnouncer(Context context) {
speaker = new TextToSpeech(context, new TextToSpeech.OnInitListener() {
...
通过这种方法向用户说出距离:
public void speak(Location targetLocation, Location currentLocation) {
float distanceInMeters = targetLocation.distanceTo(currentLocation);
speaker.speak(String.valueOf(distanceInMeters) + " meters",TextToSpeech.QUEUE_FLUSH,null);
在我的 MainActivity
中,我创建了一个 class 级别的对象...
protected void onCreate(Bundle savedInstanceState) {
distanceAnnouncer = new DistanceAnnouncer(this);
然后在单击对话框按钮时在匿名方法中使用,如下所示。这很好用。但现在我想重构代码以使用更少的内存,并希望摆脱 class 级变量。为了测试它,我创建了一个新的测试对象并将其作为上下文给它 MainActivity.this
(与在构造函数中接收 this
的 class 级对象相反)。旧对象仍然有效,新对象无效。没有抛出异常。代码已执行但没有声音。
代码:
public void NewTargetButtonClicked(View view) {
final EditText entryEditText = new EditText(this);
AlertDialog.Builder alert = new AlertDialog.Builder(this);
alert.setTitle(R.string.enter_coordinates_prompt);
alert.setView(entryEditText);
alert.setCancelable(true);
alert.setPositiveButton(R.string.ok_button_text, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
if (entryEditText.getText() == null) return;
Location newLocation = getLocationFromCoords(entryEditText.getText().toString());
//pagaidām protam apstrādāt tikai decimālgrādus
if (!(newLocation == null)) {
mTargetLocation = newLocation;
refreshDistance();
Button targetButton = (Button) MainActivity.this.findViewById(R.id.newTargetButton);
targetButton.setText(R.string.set_new_target);
DistanceAnnouncer newDistanceAnnouncer = new DistanceAnnouncer(MainActivity.this);
//THIS DOESN'T WORK:
newDistanceAnnouncer.speak(mTargetLocation,mCurrentLocation);
//THIS WORKS:
distanceAnnouncer.speak(mTargetLocation,mCurrentLocation);
CheckBox speakCheckbox = (CheckBox) MainActivity.this.findViewById(R.id.speakDistanceCheckbox);
speakCheckbox.setVisibility(View.VISIBLE);
}
}
});
AlertDialog alertDialog = alert.create();
alertDialog.show();
}
我怀疑这是上下文问题,但在这种情况下,两个上下文之间的区别是什么?他们应该是一样的,不是吗?
编辑:Full DistanceAnnouncer class 代码:
package com.blueit.audioguide;
import android.app.Activity;
import android.content.Context;
import android.location.Location;
import android.speech.tts.TextToSpeech;
import java.util.Locale;
/**
* Created by janeks on 23.04.2016..
*/
public class DistanceAnnouncer {
private TextToSpeech speaker;
public DistanceAnnouncer(Context context) {
speaker = new TextToSpeech(context, new TextToSpeech.OnInitListener() {
@Override
public void onInit(int status) {
if(status != TextToSpeech.ERROR) {
speaker.setLanguage(Locale.ENGLISH);
}
}
});
}
public void speak(Location targetLocation, Location currentLocation) {
if (targetLocation == null) return;
if (currentLocation == null) return;
if ((!(targetLocation == null)) && (!(currentLocation == null))) {
float distanceInMeters = targetLocation.distanceTo(currentLocation);
if (distanceInMeters < 1000) {
distanceInMeters = Math.round(distanceInMeters);
speaker.speak(String.valueOf(distanceInMeters) + " meters",TextToSpeech.QUEUE_FLUSH,null);
} else if ((distanceInMeters >= 1000) && (distanceInMeters <= 100000)) {
float distanceInKilometers = distanceInMeters / 1000;
distanceInKilometers = Math.round(distanceInKilometers * 10) / 10;
speaker.speak(String.valueOf(distanceInKilometers) + " kilometers",TextToSpeech.QUEUE_FLUSH,null);
} else if (distanceInMeters > 100000) {
float distanceInKilometers = distanceInMeters / 1000;
distanceInKilometers = Math.round(distanceInKilometers);
speaker.speak(String.valueOf(distanceInKilometers) + " kilometers",TextToSpeech.QUEUE_FLUSH,null);
}
} else {
}
}
}
编辑 2:应用程序日志,由 TextToSpeech:
过滤04-23 16:00:03.911 30815-30815/com.blueit.audioguide I/TextToSpeech: Sucessfully bound to com.google.android.tts
04-23 16:00:03.988 30815-30815/com.blueit.audioguide I/TextToSpeech: Connected to ComponentInfo{com.google.android.tts/com.google.android.tts.service.GoogleTTSService}
04-23 16:00:03.995 30815-30932/com.blueit.audioguide I/TextToSpeech: Set up connection to ComponentInfo{com.google.android.tts/com.google.android.tts.service.GoogleTTSService}
04-23 16:01:35.048 30815-30815/com.blueit.audioguide I/TextToSpeech: Sucessfully bound to com.google.android.tts
04-23 16:01:44.346 30815-30815/com.blueit.audioguide W/TextToSpeech: speak failed: not bound to TTS engine
好像系统将第一个连接到系统 TTS 服务,而不是第二个。但是为什么?我也尝试删除第一个,只留下第二个(也许不允许每个 Activity 多个 TTS?),但没有成功。
只保留DistanceAnnouncer
实例作为MainActivity
的成员变量。
总是在 AlertDialog
中创建新实例的问题是 TTS 引擎无法立即使用。现在你叫...
DistanceAnnouncer newDistanceAnnouncer = new DistanceAnnouncer(MainActivity.this);
//THIS DOESN'T WORK:
newDistanceAnnouncer.speak(mTargetLocation,mCurrentLocation);
...然后在正确初始化之前尝试通过 TTS 引擎说话,即在 onInit()
具有 运行.