我需要在BroadcastReceiver的子类中调用TTS服务。当我从OnInitListener实现该类时,它给出了运行时错误。
在BroadcastReceiver中有没有其他方法可以实现TTS?
谢谢,
对不起代码:
public class TextApp extends BroadcastReceiver implements OnInitListener {
private TextToSpeech tts;
private String message = "Hello";
@Override
public void onReceive(Context context, Intent intent) {
tts = new TextToSpeech(context, this);
message = "Hello TTS";
}
@Override
public void onInit(int status) {
if (status == TextToSpeech.SUCCESS)
{
tts.speak(message, TextToSpeech.QUEUE_FLUSH, null);
}
}
}
答案 0 :(得分:6)
您的代码无效:
tts = new TextToSpeech(context, this);
BroadcastReceiver上的上下文是“受限制的上下文”。这意味着您无法在BroadcastReceiver中启动上下文服务。因为TTS是一项服务,所以它不会调用任何服务。
最佳解决方案是您通过调用服务的活动开始对BroadcastReceiver的另一个意图。
public void onReceive(Context context, Intent intent) {
....
Intent speechIntent = new Intent();
speechIntent.setClass(context, ReadTheMessage.class);
speechIntent.putExtra("MESSAGE", message.getMessageBody().toString());
speechIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
context.startActivity(speechIntent);
....
}
然后在活动中使用extras参数调用TTS服务
public class ReadTheMessage extends Activity implements OnInitListener,OnUtteranceCompletedListener {
private TextToSpeech tts = null;
private String msg = "";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent startingIntent = this.getIntent();
msg = startingIntent.getStringExtra("MESSAGE");
tts = new TextToSpeech(this,this);
}
@Override
protected void onDestroy() {
super.onDestroy();
if (tts!=null) {
tts.shutdown();
}
}
// OnInitListener impl
public void onInit(int status) {
tts.speak(msg, TextToSpeech.QUEUE_FLUSH, null);
}
// OnUtteranceCompletedListener impl
public void onUtteranceCompleted(String utteranceId) {
tts.shutdown();
tts = null;
finish();
}
}
答案 1 :(得分:1)
Al Zil回答并不完全正确。 Android TTS是一项有限的服务。广播接收器确实具有有限的上下文,但它们不能将自己绑定到任何服务。但是,他们可以开始服务。从活动开始tts是可以的,但是如果你不需要UI,你也可以从服务初始化它。查看this answer,看看它是如何完成的
祝你好运。答案 2 :(得分:1)
您可以尝试使用JobIntentService(在Android-O之后)或IntentService从广播接收器调用TTS。为了给TTS提供正确的上下文,它比启动活动要少。请注意,您不能将广播接收者的上下文提供给TTS。
这是我的代码段,我在其中使用JobIntentService达到了同样的目的。
在您的自定义广播接收器的onReceive()内部,像这样调用您的自定义JobIntentService:
Intent speechIntent = new Intent();
speechIntent.putExtra("MESSAGE", "Bluetooth is on.");
MySpeakService.enqueueWork(context, speechIntent);
MySpeakService.java是这样的:
import android.content.Context;
import android.content.Intent;
import android.speech.tts.TextToSpeech;
import android.support.annotation.NonNull;
import android.support.v4.app.JobIntentService;
public class MySpeakService extends JobIntentService {
private TextToSpeech mySpeakTextToSpeech = null;
private boolean isSafeToDestroy = false;
public static void enqueueWork(Context context, Intent intent) {
enqueueWork(context, MySpeakMessageService.class, 1, intent);
}
@Override
protected void onHandleWork(@NonNull Intent intent) {
String message = intent.getStringExtra("MESSAGE");
mySpeakTextToSpeech = new TextToSpeech(getApplicationContext(), new TextToSpeech.OnInitListener() {
@Override
public void onInit(int status) {
mySpeakTextToSpeech.speak(message, TextToSpeech.QUEUE_ADD, null, null);
while (mySpeakTextToSpeech.isSpeaking()) {
}
isSafeToDestroy = true;
}
});
}
@Override
public void onDestroy() {
if (isSafeToDestroy) {
if (mySpeakTextToSpeech != null) {
mySpeakTextToSpeech.shutdown();
}
super.onDestroy();
}
}
}