Android 在 BroadcastReceiver 中调用 TTS

发布于 2024-10-09 05:09:12 字数 614 浏览 1 评论 0原文

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


}
}

I need to call TTS service within subclass of BroadcastReceiver. When I am implement that class from OnInitListener, it gave run-time error.

Is there any other-way to implement TTS within BroadcastReceiver?

Thank You,

Sorry Code:

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);
    }


}
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

偏闹i 2024-10-16 05:09:12

您的代码不起作用:

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();
}
}

Your code didn't work on :

tts = new TextToSpeech(context, this);

Context on BroadcastReceiver is a "restricted context". It means you cannot start service on context in BroadcastReceiver. Because TTS is a service, so it doesn't call anyting.

The Best Solutions is you start another intent on BroadcastReceiver with activity that call the service.

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);
....
}

And then on the activity you call the TTS service with parameter from extras

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();
}
}
梦里的微风 2024-10-16 05:09:12

您可以尝试使用 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, MySpeakService.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();
            }
        }
    }

You can try using either JobIntentService (Post Android-O) or IntentService to invoke TTS from Broadcast receiver. It has less overhead than launching an activity for the sake of giving TTS a correct context. Note that you cannot give a broadcast receiver's context to TTS.

Here is my code snippet where I acheived same thing using JobIntentService.

Inside your custom Broadcast receiver's onReceive() invoke your custom JobIntentService like this:

Intent speechIntent = new Intent();
speechIntent.putExtra("MESSAGE", "Bluetooth is on.");
MySpeakService.enqueueWork(context, speechIntent);

And MySpeakService.java is this:

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, MySpeakService.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();
            }
        }
    }
半窗疏影 2024-10-16 05:09:12

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

祝你好运。

Al Zil answer is not totally correct. Android TTS is a bounded service. Broadcast receivers truly has a limited context but they can't bind themselves to any service. However, they can START a service. Starting the tts from activity is ok, but if you don't need UI you can also initialize it from a service. Look at this answer to see how it's done

Good luck.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文