Android在BroadcastReceiver中调用TTS

问题描述 投票:7回答:3

我需要在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);
    }


}
}
android text-to-speech
3个回答
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);
....
}

然后在活动中使用附加参数调用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
投票

Al Zil的回答并不完全正确。 Android TTS是一项有限的服务。广播接收器确实具有有限的上下文,但它们不能将自己绑定到任何服务。但是,他们可以开始服务。从活动开始tts是可以的,但是如果你不需要UI,你也可以从服务初始化它。看看this answer,看看它是如何完成的

祝好运。


1
投票

您可以尝试使用JobIntentService(Post 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();
            }
        }
    }
© www.soinside.com 2019 - 2024. All rights reserved.